2009-12-17 14 views
7

Vì vậy, tôi có một số mã đọc một số byte nhất định từ một tệp và trả về mảng byte kết quả (điều này về cơ bản được sử dụng để chunking các tệp để gửi qua mạng dưới dạng văn bản ascii được mã hóa base64 (cuối cùng).Java: Làm thế nào để "cắt" một mảng byte?

Nó hoạt động tốt, ngoại trừ khi đoạn cuối cùng của tệp được tạo, nó không phải là một đoạn đầy đủ. Do đó, mảng byte kết quả không đầy. Tuy nhiên, nó là một kích thước không đổi, có nghĩa là các tập tin được tập hợp lại có một bó toàn bộ dữ liệu bổ sung (có thể là 0) nối vào cuối.

Tôi làm cách nào để byte [] cho đoạn cuối cùng của tệp thực sự chỉ chứa dữ liệu cần thiết? Mã này trông như thế này:

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

Vì vậy, nếu chunkSize lớn hơn các byte còn lại trong tập tin, một kích thước byte đầy đủ [] được quay trở lại nhưng chỉ có nó đầy một nửa với dữ liệu.

Trả lời

3

Bạn sẽ phải kiểm tra giá trị trả lại của RandomAccessFile.read() để xác định số byte đã đọc. Nếu nó khác với chunkSize, bạn sẽ phải sao chép mảng sang một mảng nhỏ hơn và trả về giá trị đó.

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

Sử dụng Arrays.copyOf từ bài viết ở trên thay vì System.arraycopy (mà đã ném một ngoại lệ), điều này đã làm việc hoàn hảo! Cảm ơn! –

+0

Đã sửa, tôi có lỗi đánh máy trong so sánh, nên đã sử dụng '==' không '='. – notnoop

+0

@Erin Drummond: Ngoại lệ được ném bởi 'System.arraycopy()' là gì? – Asaph

2

RandomAccessFile.read() trả về số byte đọc, vì vậy bạn có thể làm sao chép mảng nếu cần thiết:

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

Nếu bạn đang sử dụng Java pre-6, sau đó bạn cần phải thực hiện Arrays.copyOf mình:

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

Bạn cũng có thể sử dụng kích thước của tệp để tính số byte còn lại.

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

Bằng cách này bạn không tạo thêm một mảng và không cần bản sao. Có lẽ không phải là một tác động lớn.
Một điểm quan trọng IMO: kiểm tra giá trị trả về bởi read, tôi nghĩ rằng nó có thể nhỏ hơn các byte còn lại. Các trạng thái javadoc:

Số byte đọc là, nhiều nhất, tương đương với chiều dài của b