Java: Как «обрезать» массив байтов? - PullRequest
7 голосов
/ 17 декабря 2009

Итак, у меня есть некоторый код, который читает определенное количество байтов из файла и возвращает результирующий байтовый массив (он в основном используется для разбиения файлов на блоки для отправки по сети в виде (в конечном итоге) кода ascii в кодировке base64)

Работает нормально, за исключением того, что когда генерируется последний кусок файла, он не является полным. Поэтому результирующий байтовый массив не заполнен. Тем не менее, он имеет постоянный размер, что означает, что файл повторно собран, и в конце добавлена ​​целая куча дополнительных данных (возможно 0).

Как сделать так, чтобы байт [] для последнего фрагмента файла действительно содержал только те данные, которые ему нужны? Код выглядит так:

 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 больше, чем оставшиеся байты в файле, возвращается полноразмерный байт [], но он только наполовину заполнен данными.

Ответы [ 3 ]

3 голосов
/ 17 декабря 2009

Вам придется проверить возвращаемое значение 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;
}
2 голосов
/ 17 декабря 2009

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 pre-6, вам нужно реализовать Arrays.copyOf самостоятельно:

byte[] r = new byte[read];
System.arraycopy(data, 0, r, 0, read);
return r;
0 голосов
/ 18 декабря 2009

Вы также можете использовать размер файла для вычисления оставшегося количества байтов.

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

...