2013-08-26 4 views
1

В настоящее время я полагаюсь на метод ObjectInputStream.available(), чтобы рассказать мне, сколько байтов осталось в потоке. Причина для этого - я пишу некоторые тесты единицы/интеграции для некоторых функций, которые обрабатывают потоки, и я просто пытаюсь обеспечить, чтобы метод available() возвращал 0 после того, как я закончил.Лучший способ узнать, сколько байтов в потоке?

К сожалению, при тестировании на отказ (т. Е. Я отправил около 8 байтов вниз по потоку) мое утверждение для available() == 0 подходит к истине, когда оно должно быть ложным. Он должен показывать> 0 или 8 байтов!

Я знаю, что метод available() классически ненадежен, но я решил, что он покажет что-то как минимум> 0!

Есть ли более надежный способ проверки, является ли поток пустым или нет (в конце концов, моя главная цель здесь)? Возможно, в домене Apache IO или в какой-то другой библиотеке?

Кто-нибудь знает, почему метод available() настолько глубоко ненадежен; в чем смысл? Или есть конкретный, правильный способ его использования?


Update:

Так как многие из вас могут читать комментарии, главный вопрос, я столкнулся в том, что на одном конце потока, я посылаю определенное количество байтов но с другой стороны, не все байты прибывают!

В частности, я посылаю 205498 байт на одном конце и получаю только 204988 на другом, последовательно. Я контролирую обе стороны этой операции между потоками в сокете, но это должно быть неважно.

Вот код, который я написал для сбора всех байтов.

public static int copyStream(InputStream readFrom, OutputStream writeTo, int bytesToRead) 
     throws IOException { 

    int bytesReadTotal = 0, bytesRead = 0, countTries = 0, available = 0, bufferSize = 1024 * 4; 

    byte[] buffer = new byte[bufferSize]; 

    while (bytesReadTotal < bytesToRead) { 

     if (bytesToRead - bytesReadTotal < bufferSize) 
     buffer = new byte[bytesToRead - bytesReadTotal]; 

     if (0 < (available = readFrom.available())) { 
     bytesReadTotal += (bytesRead = readFrom.read(buffer)); 
     writeTo.write(buffer, 0, bytesRead); 
     countTries = 0; 

     } else if (countTries < 1000) 
     try { 
      countTries++; 
      Thread.sleep(1L); 

     } catch (InterruptedException ignore) {} 
     else 

     break; 
    } 

    return bytesReadTotal; 
    } 

Я установил переменную countTries, чтобы увидеть, что произойдет. Даже без countTires, он будет блокироваться навсегда, пока не достигнет BytesToRead.

Что может заставить поток внезапно блокировать бесконечно так? Я знаю, что на другом конце он полностью отправляет байты (поскольку он фактически использует один и тот же метод, и я вижу, что он завершает функцию с полным байтовым соглашением bytesReadTotal в конце, но получатель этого не делает. Я смотрю на массивы, они идеально совпадают до до конца, а также.

UPDATE2

Я заметил, что когда я добавил writeTo.flush() в конце моего метода copyStream, кажется, снова работать. Хм .. Почему эти ситуации очень важны в этой ситуации. Т.е. почему бы не использовать ее, чтобы поток был перма-блоком?

+2

Как вы должны знать, что есть 'x' байт в потоке, не читая его? Метод 'Доступный()' явно указывает _Отбрасывает количество байтов, которые можно читать без блокировки. Если вам нужно было прочитать больше байтов, вам нужно будет заблокировать. –

+0

Вы должны проверить с помощью 'InputStream # read()' return '-1', чтобы узнать, достигнут ли конец потока. –

+0

@SotiriosDelimanolis, не должен 'available()' давать хотя бы возвращаемое значение 1, чтобы показать, что для блокировки есть хотя бы 1 байт? –

ответ

2

available() метод возвращает только количество байтов без блокировки (что может быть 0). Чтобы увидеть, есть ли в потоке какие-либо байты, вы должны указать read() или read(byte[]), который вернет количество прочитанных байтов. Если возвращаемое значение равно -1, вы дошли до конца файла.

Этот небольшой фрагмент кода будет проходить через InputStream до тех пор, пока он не дойдет до конца (read() возвращает -1). Я не думаю, что это никогда не может возвращать 0, потому что он должен блокировать, пока он не может ни читать, 1 байт или обнаружить там не осталось ничего, чтобы читать (и, следовательно, возвращать -1)

int currentBytesRead=0; 
int totalBytesRead=0; 
byte[] buf = new byte[1024]; 

while((currentBytesRead =in.read(buf))>0){ 
     totalBytesRead+=currentBytesRead; 

} 
+0

В настоящее время я использую что-то вроде этого: int b; while ((b = singleServersT.getInputStream(). Read())! = -1) { System.err.print (b); } Но его фактическое блокирование после первого байта прочитано! Я добавил комментарии к моему оригинальному сообщению об этом новом свете. –

+0

Да, ваш код делает то же самое. TotalBytesRead == 1 после первого цикла, после чего он блокируется. –

+1

он должен блокироваться, вы не можете определить, сколько байтов осталось во всем потоке без блокировки. – dkatzel

Смежные вопросы