Проблема чтения Java InputStream - PullRequest
8 голосов
/ 28 мая 2011

У меня есть класс Java, где я читаю данные через InputStream

    byte[] b = null;
    try {
        b = new byte[in.available()];
        in.read(b);
    } catch (IOException e) {
        e.printStackTrace();
    }

Он отлично работает, когда я запускаю свое приложение из IDE (Eclipse).

Нокогда я экспортирую свой проект и он упакован в JAR, команда чтения не читает все данные.Как я могу это исправить?

Эта проблема чаще всего возникает, когда InputStream - это файл (~ 10 КБ).

Спасибо!

Ответы [ 4 ]

6 голосов
/ 28 мая 2011

Обычно я предпочитаю использовать буфер фиксированного размера при чтении из входного потока.Как указал evilone, использование available () в качестве размера буфера может быть не очень хорошей идеей, потому что, скажем, если вы читаете удаленный ресурс, вы можете заранее не знать доступные байты.Вы можете прочитать javadoc InputStream , чтобы получить больше информации.

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

byte[] buffer = new byte[BUFFER_SIZE];

int bytesRead = 0;
while ((bytesRead = in.read(buffer)) >= 0){
  for (int i = 0; i < bytesRead; i++){
     //Do whatever you need with the bytes here
  }
}

Используемая здесь версия read () заполнит данный буфер настолько, насколько это возможно, и вернетколичество байтов фактически прочитано.Это означает, что есть вероятность, что ваш буфер может содержать конечные данные мусора, поэтому очень важно использовать байты только до bytesRead.

Обратите внимание на строку (bytesRead = in.read(buffer)) >= 0, , в которой ничего нетСпецификация InputStream гласит, что read () не может читать 0 байтов. Возможно, вам потребуется обработать случай, когда read () читает 0 байтов как особый случай, в зависимости от вашего случая.Для локального файла я никогда не сталкивался с таким случаем;однако, когда я читал удаленные ресурсы, я на самом деле видел, что read () читает 0 байтов, постоянно приводя приведенный выше код в бесконечный цикл.Я решил проблему с бесконечным циклом, подсчитав количество раз, которое я прочитал 0 байтов, когда счетчик превысит пороговое значение, я сгенерирую исключение.Вы можете не столкнуться с этой проблемой, но просто имейте это в виду:)

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

5 голосов
/ 28 мая 2011

read() вернет -1, когда InputStream истощится. Существует также версия read , которая принимает массив, что позволяет вам выполнять частичное чтение. Возвращает количество фактически прочитанных байтов или -1 в конце InputStream. Объедините это с динамическим буфером, таким как ByteArrayOutputStream , чтобы получить следующее:

InputStream in = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int read;
byte[] input = new byte[4096];
while ( -1 != ( read = in.read( input ) ) ) {
    buffer.write( input, 0, read );
}
input = buffer.toByteArray()

Это значительно сокращает количество методов, которые вы должны вызывать, и позволяет ByteArrayOutputStream быстрее наращивать свой внутренний буфер.

3 голосов
/ 28 мая 2011
File file = new File("/path/to/file");

try {
   InputStream is = new FileInputStream(file);
   byte[] bytes = IOUtils.toByteArray(is);

   System.out.println("Byte array size: " + bytes.length);
} catch (IOException e) {
   e.printStackTrace();
}
0 голосов
/ 14 сентября 2013

Ниже приведен фрагмент кода, который загружает файл (*. Png, *. Jpeg, *. Gif, ...) и записывает его в BufferedOutputStream, который представляет HttpServletResponse.

BufferedInputStream inputStream = bo.getBufferedInputStream(imageFile);
try {
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    int bytesRead = 0;
    byte[] input = new byte[DefaultBufferSizeIndicator.getDefaultBufferSize()];
    while (-1 != (bytesRead = inputStream.read(input))) {
        buffer.write(input, 0, bytesRead);
    }
    input = buffer.toByteArray();

    response.reset();
    response.setBufferSize(DefaultBufferSizeIndicator.getDefaultBufferSize());
    response.setContentType(mimeType);
    // Here's the secret. Content-Length should equal the number of bytes read.
    response.setHeader("Content-Length", String.valueOf(buffer.size()));
    response.setHeader("Content-Disposition", "inline; filename=\"" + imageFile.getName() + "\"");

    BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream(), DefaultBufferSizeIndicator.getDefaultBufferSize());
    try {
        outputStream.write(input, 0, buffer.size());
    } finally {
        ImageBO.close(outputStream);
    }
} finally {
    ImageBO.close(inputStream);
}

Надеюсь, это поможет.

...