Рассмотрим следующий код:
private File readFromFile1(File file1) {
int offset = 0;
long message = 0;
File file2 = null;
try {
FileInputStream fis = new FileInputStream(file1);
byte[] data = new byte[8]; //Read buffer
byte[] tmpbuf = new byte[8]; //Temporary chunk buffer
file2 = new File("file2.txt");
FileOutputStream fos = new FileOutputStream(file2.getAbsolutePath(), true);
DataOutputStream dos = new DataOutputStream(fos);
int readcnt; //Read count
int chunk; //Chunk size to write to tmpbuf
while ((readcnt = fis.read(data, 0, 8)) != -1) {
//// POINT A ////
//Skip chunking system if an 8 byte octet is read directly.
if(readcnt == 8 && offset == 0){
message = someOperation(tmpbuf); // operation according to business logic
dos.writeLong(message);
continue;
}
//// POINT B ////
chunk = Math.min(tmpbuf.length - offset, readcnt); //Determine how much to add to the temp buf.
System.arraycopy(data, 0, tmpbuf, offset, chunk); //Copy bytes to temp buf
offset = offset + chunk; //Sets the offset to temp buf
if (offset == 8) {
message = someOperation(tmpbuf); // operation according to business logic
dos.writeLong(message);
if (chunk < readcnt) {
System.arraycopy(data, chunk, tmpbuf, 0, readcnt - chunk);
offset = readcnt - chunk;
} else {
offset = 0;
}
}
}
//// POINT C ////
//Process remaining bytes here...
//message = foo(tmpbuf);
//dos.writeLong(message);
fos.close();
dos.close();
fis.close();
} catch (IOException e) {
System.out.println("Some error occurred while reading from File:" + e);
}
return file2;
}
В этом фрагменте кода я сделал следующее:
- Измените свой код чтения, чтобы включить количество байтов, фактически считанных из метода read() (отмечено как readcnt).
- Добавлена система фрагментации байтов (обработка не происходит, пока в буфере фрагментации не будет не менее 8 байт).
- Разрешена отдельная обработка последних байтов (которые не составляют 8-байтовый октет).
Как видно из кода, считываемые данные сначала сохраняются в буфере фрагментации (обозначаемом как tmpbuf) до тех пор, пока не станет доступно как минимум 8 байт. Это произойдет только в том случае, если 8 байтов не всегда доступны (если 8 байтов доступны напрямую и ничего не разбито на фрагменты, обрабатывайте напрямую. См. «Точка A» в коде). Это делается как форма оптимизации для предотвращения избыточных копий массива.
Система фрагментации использует смещения, которые увеличиваются каждый раз, когда байты записываются в tmpbuf, пока не достигнет значения 8 (это не будет превышено, так как метод Math.min(), используемый при назначении 'chunk', ограничит значение). При смещении == 8 переходим к выполнению кода обработки.
Если это конкретное чтение произвело больше байтов, чем было фактически обработано, продолжайте записывать их в tmpbuf снова с самого начала, при этом соответствующим образом устанавливая смещение, в противном случае установите смещение равным 0.
Повторить цикл.
Код оставит последние несколько байтов данных, которые не помещаются в октете в массиве tmpbuf с переменной смещения, указывающей, сколько фактически было записано. Затем эти данные могут быть обработаны отдельно в точке C.
Кажется, это намного сложнее, чем должно быть, и, вероятно, есть лучшее решение (возможно, с использованием существующих методов библиотеки Java), но с моей головы это то, что я получил. Надеюсь, это достаточно ясно для вас, чтобы понять.
person
initramfs
schedule
17.10.2013
while((readcnt = fis.read(data)) > 0)
, и вам все равно никогда не придется беспокоиться о смещении, и у вас будет переменная readcnt, чтобы отслеживать, сколько байтов вы прочитали. - person Klazen108   schedule 17.10.2013DataInputStream.readFully(data).
Тогда вы будете уверены, что каждый раз у вас действительно есть 8 байтов. Что должно произойти, если длина файла не кратна 8 байтам? - person user207421   schedule 18.10.2013