2012-08-13 1 views
5

Я писал что-то, чтобы прочитать поток запросов (содержащий gzipped данные) из входящего HttpServletRequest («запрос» ниже), однако кажется, что обычный метод чтения InputStream фактически не читает весь контент?InputStream.read (byte [], 0 length) останавливается раньше?

Мой код был:

InputStream requestStream = request.getInputStream(); 
if ((length = request.getContentLength()) != -1) 
{ 
    received = new byte[length]; 
    requestStream.read(received, 0, length); 
} 
else 
{ 
    // create a variable length list of bytes 
    List<Byte> bytes = new ArrayList<Byte>(); 

    boolean endLoop = false; 
    while (!endLoop) 
    { 
     // try and read the next value from the stream.. if not -1, add it to the list as a byte. if 
     // it is, we've reached the end. 
     int currentByte = requestStream.read(); 
     if (currentByte != -1) 
      bytes.add((byte) currentByte); 
     else 
      endLoop = true; 
    } 
    // initialize the final byte[] to the right length and add each byte into it in the right order. 
    received = new byte[bytes.size()]; 
    for (int i = 0; i < bytes.size(); i++) 
    { 
     received[i] = bytes.get(i); 
    } 
} 

То, что я нашел во время тестирования было то, что иногда верхняя часть (для того, когда длина содержимого присутствует) просто прекратить чтение через часть входящего потока запросов и оставить остаток «принятого» байтового массива. Если я просто заставляю его запускать else-часть оператора if во все времена, он отлично читает и все ожидаемые байты помещаются в «полученные».

Итак, похоже, что я могу оставить свой код один только с этим изменением, но кто-нибудь может понять, почему обычный метод read (byte [], int, int) перестает читать? В описании говорится, что он может остановиться, если присутствует конец файла. Может ли быть, что gzipped-данные просто включали байты, соответствующие любой сигнатуре для этого?

+0

Кстати, вы можете взглянуть на [GZIPInputStream] (http://docs.oracle.com/javase/7/docs/api/java/util/zip/GZIPInputStream.html). Вместо того, чтобы читать все в массив байтов, а затем распаковывать данные отдельно, вы можете просто обернуть исходный InputStream в GZIPInputStream и сразу прочитать распакованные данные. –

+0

Ах, причина, по которой мы не делаем этого напрямую, потому что иногда ввод, который мы получаем от других систем, на самом деле не gzipped, хотя он должен быть ... :) –

ответ

8

Вам нужно добавить петлю while вверху, чтобы получить все байты. Поток будет пытаться читать столько байт, сколько он может, но не обязан возвращать len байт сразу:

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

if ((length = request.getContentLength()) != -1) 
{ 
    received = new byte[length]; 
    int pos = 0; 
    do { 
     int read = requestStream.read(received, pos, length-pos); 

     // check for end of file or error 
     if (read == -1) { 
      break; 
     } else { 
      pos += read; 
     } 
    } while (pos < length); 
} 

EDIT: фиксированный во время.

+0

А, это отлично работает, спасибо! –

+1

, вы действительно не должны использовать длину запроса для чтения данных. метод read() вернет -1, когда он достигнет конца ввода. Это должно быть вашим индикатором того, исчерпаны ли данные. – Matt

1

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

Возможно, вы бы хотели: DataInputStream.readFully();

+0

Да, я видел комментарии об этом на других сообщениях об этой проблеме - это, вероятно, сработало бы и для меня, но, исправляя это, казалось более разумным просто сохранить один способ чтения вывода :) Единственное, что я не уверен, будет ли это медленнее, чем встроенный метод ... Мы только ожидаем короткие (до 20k, возможно?) Входящие запросы, хотя это, вероятно, не имеет значения. Вывод метода «read» был правильным с точки зрения того, насколько он действительно читается, то есть для входа в 11k байт он будет указывать, что он считывает только 7k байтов. Я просто не знаю, почему это так! –

+2

Это дает вам столько данных, доступных прямо сейчас, так что вы можете обработать их, прежде чем читать еще. Это более эффективно, чем ожидание всех данных перед обработкой esp, если данные очень большие. –

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