2009-12-17 33 views
7

Quindi ho un codice che legge una certa quantità di byte da un file e restituisce l'array di byte risultante (questo è fondamentalmente usato per frammentare i file da inviare sulla rete come (eventualmente) testo ASCII codificato in base 64).Java: come "tagliare" un array di byte?

Funziona correttamente, tranne che quando viene generato l'ultimo blocco del file, non è un blocco completo. Di conseguenza, l'array di byte risultante non è pieno. Tuttavia, è una dimensione costante, il che significa che il file viene riassemblato, vi è una serie di dati aggiuntivi (gli 0 forse) aggiunti alla fine.

Come posso fare in modo che il byte [] dell'ultimo blocco del file contenga solo i dati necessari? Il codice è simile al seguente:

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; 
} 

Quindi, se chunksize è più grande dei restanti byte del file, un byte pieno di dimensioni [] ottiene rinviato, ma il suo unico mezzo pieno con i dati.

risposta

3

È necessario verificare il valore di ritorno di RandomAccessFile.read() per determinare il numero di byte letti. Se è diverso da chunkSize, dovrai copiare l'array su uno più piccolo e restituirlo.

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

Uso Arrays.copyOf dalla carica sopra invece di System.arraycopy (che ha gettato un'eccezione), questo ha funzionato perfettamente! Grazie! –

+0

Corretto, ho avuto un refuso nel confronto, avrei dovuto usare '==' not '='. – notnoop

+0

@Erin Drummond: Qual è stata l'eccezione lanciata da 'System.arraycopy()'? – Asaph

2

RandomAccessFile.read() restituisce il numero di byte letti, in modo da poter fare copiare la matrice, se necessario:

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); 
} 

Se si utilizza Java pre-6, quindi è necessario implementare Arrays.copyOf te stesso:

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

È inoltre possibile utilizzare la dimensione del file per calcolare il numero restante di byte.

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; 
} 

In questo modo non si crea un array aggiuntivo e non è necessaria la copia. Probabilmente non è un grande impatto.
Un punto importante IMO: controllare il valore restituito da read, penso che possa essere inferiore ai byte rimanenti. Gli stati Javadoc:

Il numero di byte letti è, al massimo, pari alla lunghezza di b