Java: как "обрезать" массив байтов?

Итак, у меня есть код, который считывает определенное количество байтов из файла и возвращает результирующий массив байтов (это в основном используется для разбиения файлов на куски для отправки по сети как (в конечном итоге) текст 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 ответов


вам нужно будет проверить возвращаемое значение 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;
}

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;

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

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