简体   繁体   中英

Java: How to “trim” a byte array?

So I have some code that reads a certain amount of bytes from a file and returns the resulting byte array (this is basically used for chunking up files to send over the network as (eventually) base64-encoded ascii text).

It works fine, except that when the last chunk of the file is generated, it isnt a full chunk. Therefore, the resulting byte array isnt full. However, it is a constant size, which means that the file is reassembled there is a whole bunch of extra data (0's maybe) appended to the end.

How can I make it so that the byte[] for the last chunk of the file really only contains the data it needs to? The code looks like this:

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

So if chunkSize is bigger than the remaining bytes in the file, a full sized byte[] gets returned but its only half-full with data.

You'll have to check the return value of RandomAccessFile.read() to determine the number of bytes read. If it's different than the chunkSize, you'll have to copy the array over to a smaller one and return that.

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

RandomAccessFile.read() returns the number of bytes read, so you can do copy the array if needed:

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

If you are using Java pre-6, then you need to implement Arrays.copyOf yourself:

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

You could also use the size of the file to calculate the remaining number of 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;
}

This way you don't create an additional Array and do not need the copy. Probably not a big impact.
One important point IMO: check the value returned by read , I think it can be less than the remaining bytes. The javadoc states:

The number of bytes read is, at most, equal to the length of b

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM