2009-12-17 41 views
7

所以我有一些代碼從文件中讀取一定數量的字節並返回結果字節數組(這基本上用於分塊文件以通過網絡發送(最終)爲base64編碼的ascii文本)。Java:如何「修剪」一個字節數組?

它工作正常,除了生成文件的最後一個塊時,它不是一個完整的塊。因此,得到的字節數組不是滿的。然而,它的大小是一個常量,這意味着文件被重新組合,最後會附加一大堆額外的數據(可能是0)。

我該怎麼做才能讓文件的最後一個塊的byte []真的只包含它需要的數據?代碼如下所示:

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

所以,如果CHUNKSIZE比文件中剩餘的字節更大,一個全尺寸的byte []獲取返回,但其只是半滿的數據。

回答

3

您必須檢查返回值RandomAccessFile.read()以確定讀取的字節數。如果它與chunkSize不同,則必須將數組複製到較小的數組並返回。

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

從上方,而不是System.arraycopy後使用Arrays.copyOf的長度(其拋出一個例外),這工作完美!謝謝! – 2009-12-17 02:29:27

+0

更正,我有一個比較錯字,應該使用'=='而不是'='。 – notnoop 2009-12-17 02:37:27

+0

@Erin Drummond:'System.arraycopy()'拋出的異常是什麼? – Asaph 2009-12-17 03:00:54

2

RandomAccessFile.read()返回的字節數讀取,所以如果需要的話,你可以做副本的陣列:

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

如果您使用的是Java前6,那麼你就需要實現Arrays.copyOf自己:

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

您也可以使用文件的大小來計算剩餘的字節數。

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

這樣你就不會創建一個額外的數組,並且不需要該副本。可能不是很大的影響。
IMO重要的一點:檢查read返回的值,我認爲它可以比其餘的字節少。的Javadoc狀態:

讀取的字節的數量,頂多等於B