2009-12-17 46 views
7

Así que tengo un código que lee una cierta cantidad de bytes de un archivo y devuelve la matriz de bytes resultante (esto se usa básicamente para fragmentar archivos para enviar a través de la red como (eventualmente) texto ascii codificado en base64).Java: ¿Cómo "recortar" una matriz de bytes?

Funciona bien, excepto que cuando se genera la última parte del archivo, no es un fragmento completo. Por lo tanto, la matriz de bytes resultante no está completa. Sin embargo, es un tamaño constante, lo que significa que el archivo se vuelve a ensamblar. Hay un montón de datos adicionales (posiblemente de 0) añadidos al final.

¿Cómo puedo hacer para que el byte [] para el último fragmento del archivo realmente solo contenga los datos que necesita? El código es el siguiente:

private byte[] readData(File f, int startByte, int chunkSize) throws Exception { 
    RandomAccessFile raf = new RandomAccessFile(f, "r"); 
    raf.seek(startByte); 
    byte[] data = new byte[chunkSize]; 
    raf.read(data);   
    raf.close(); 
    return data; 
} 

Así que si chunkSize es más grande que el resto de bytes en el archivo, un byte de tamaño completo [] es retornada pero es sólo la mitad con los datos.

Respuesta

3

Deberá verificar el valor de retorno de RandomAccessFile.read() para determinar la cantidad de bytes leídos. Si es diferente de chunkSize, tendrá que copiar la matriz a una más pequeña y devolverla.

private byte[] readData(File f, int startByte, int chunkSize) throws Exception { 
    RandomAccessFile raf = new RandomAccessFile(f, "r"); 
    raf.seek(startByte); 
    byte[] data = new byte[chunkSize]; 
    int bytesRead = raf.read(data); 
    if (bytesRead != chunkSize) { 
     byte[] smallerData = new byte[bytesRead]; 
     System.arraycopy(data, 0, smallerData, 0, bytesRead); 
     data = smallerData; 
    } 
    raf.close(); 
    return data; 
} 
+1

Usando Arrays.copyOf del poste anterior en lugar de System.arraycopy (que lanzó una excepción), ¡esto funcionó a la perfección! ¡Gracias! –

+0

Corregido, tuve un error tipográfico en la comparación, debería haber usado '==' not '='. – notnoop

+0

@Erin Drummond: ¿Cuál fue la excepción lanzada por 'System.arraycopy()'? – Asaph

2

RandomAccessFile.read() devuelve el número de bytes leídos, lo que puede hacer copiar la matriz si es necesario:

private byte[] readData(File f, int startByte, int chunkSize) throws Exception { 
    RandomAccessFile raf = new RandomAccessFile(f, "r"); 
    raf.seek(startByte); 
    byte[] data = new byte[chunkSize]; 
    int read = raf.read(data); 
    raf.close(); 
    if (read == data.length) return data; 
    else 
     return Arrays.copyOf(data, read); 
} 

Si está utilizando Java pre-6, a continuación, es necesario implementar Arrays.copyOf mismo:

byte[] r = new byte[read]; 
System.arraycopy(data, 0, r, 0, read); 
return r; 
0

También podría usar el tamaño del archivo para calcular el número restante de bytes.

private byte[] readData(File f, int startByte, int chunkSize) throws Exception { 
    RandomAccessFile raf = new RandomAccessFile(f, "r"); 
    raf.seek(startByte); 
    int size = (int) Math.min(chunkSize, raf.length()-startByte); 
    byte[] data = new byte[size]; 
    raf.read(data); 
    // TODO check the value returned by read (throw Exception or loop) 
    raf.close(); 
    return data; 
} 

De esta forma no crea una matriz adicional y no necesita la copia. Probablemente no sea un gran impacto.
Un punto importante IMO: verifique el valor devuelto por read, creo que puede ser menor que los bytes restantes. Los estados Javadoc:

El número de bytes leídos es, como máximo, igual a la longitud de b

Cuestiones relacionadas