2016-11-18 1 views
0

Моя цель - прочитать поток байтов из сокета в файл, а затем воспроизвести его позже в качестве тестового жгута для моего приложения. Где-то, записывая байты на диск, байт будет написан неправильно, казалось бы, случайным образом.Окна Java записывают байты в файл, некоторые неверны

Мой писатель выглядит следующим образом:

blobWriter = new BufferedOutputStream(new FileOutputStream(blobFileName)); 
blobChannel = Channels.newChannel(blobWriter); 

Я использую blobChannel так, что я могу писать прямо из ByteBuffer. На каждом чтении из сокета, я просто передать буфер писателя:

if (key.isReadable()) { 
    final int bytesRead= socketChannel.read(readBuffer); 

    if(bytesRead == -1) 
    { 
     logger.warn("no bytes to read"); 
     break; 
    } 

    readBuffer.flip(); 
    blobChannel.write(readBuffer); 
    ... 
    <continue to process data> 
} 

Когда корм живой, процессы программы чтения в записи, и они не повреждены. Скажем для каждого сообщения, он выводит кортеж из 7 полей. Один из них, например, заключается в следующем:

(tupleid=0,msgType=110,feedId=225,venueId=30,orderId=160,symbol="CHF.NOK.SPOT",venueTime=44417979) 

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

(tupleid=0,msgType=110,feedId=225,venueId=30,orderId=160,symbol="CHF.-�ûnX",venueTime=44417979) 

Обратите внимание на поврежденный символ.

Самое странное, что он будет обрабатывать тысячи сообщений с тем же символом и другими полями без проблем, но тогда необъяснимо одно сообщение будет повреждено. Это не всегда поле символов неверно, иногда orderId ошибочно и т. Д.

Я подозреваю, что blobWriter ошибочно ошибочно. Может ли моя ОС (windows 7) делать что-то напуганное? Я проверил байтовый поток, который сохраняется на диске в notepad++, и действительно, он показывает неправильные байты, поэтому ошибка должна быть в записи файла, а не в моем механизме воспроизведения. Кроме того, если основное приложение само по себе было ошибкой, оно должно неверно считывать байты в реальном времени; это не так.

Кто-нибудь знает, что может произойти неправильно?

+0

Где отображается вывод? –

+0

Какой выход конкретно? –

+0

«обработанный вывод», который вы упомянули. –

ответ

0

Похоже, WritableByteChannel JavaDoc пытался предупредить меня:

Если не указано иное, операция записи будет возвращать только после того, как писать все г просил байт. Некоторые типы каналов, в зависимости от их состояния, могут писать только некоторые из байтов или , возможно, вообще ничего. Канал сокета в неблокирующем режиме, для примера , не может писать больше байтов, чем свободные в выходном буфере сокета.

Действительно, сокетный канал находится в неблокирующем режиме. Я профилировал это, и каждый из каждых 200 просмотров или так не синхронизирован. Похоже, мой канал пишет больше байтов, которые мои читатели действительно читают из буфера.

Another SO thread offers more information.

Что, наконец, работал для меня копировал ByteArray, на каждой операции чтения, вместо того, чтобы использовать поток.Вероятно, это не оптимальная производительность, но, по крайней мере, это не приводит к неверным данным:

if (readBuffer.hasRemaining()){ 
    byte[] b = new byte[readBuffer.remaining()] 
    readBuffer.get(b) 
    blobWriter.write(b) 
} 
+0

Копирование его в массив байтов не требуется. Простой 'while (readBuffer.remaining()> 0) blobWriter.write (readBuffer);' должно быть в порядке. Но если я правильно понял это, вы действительно испытали случай, когда ответ на мой вопрос, с которым вы связаны, - это «Нет, он не всегда будет писать весь буфер» * - это правильно? – Marco13

+0

Спасибо Марко, я так считаю. –

+0

Я пробовал этот Марко, но все еще получаю неправильные данные. Я открыл отдельный поток, поскольку у меня такая же проблема, и я больше не использую каналы: http://stackoverflow.com/questions/40725665/java-bytes-to-file-are-they-miswritten –