2014-11-11 2 views
-3

Я читаю файл XML и толкая его содержимое в ByteArrayOutputStream следующим образом:Java: почему существует разница в использовании памяти между циклами for- и while?

static final MY_XML_FILE = new File("..."); 

byte[] buffer = new byte[(int) MY_XML_FILE.length()]; 
    int bytesRead; 
    ByteArrayOutputStream output = new ByteArrayOutputStream(); 
    while ((bytesRead = fileInputStream.read(buffer)) != -1) 
     output.write(buffer, 0, bytesRead); 

, который прекрасно работает.

Я не хотел сферу bytesRead быть виден снаружи while -loop, поэтому я изменил его на for -loop:

for (int bytesRead = fileInputStream.read(buffer); bytesRead != -1;) 
    output.write(buffer, 0, bytesRead); 

Но это выдает следующее сообщение об ошибке:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit 
    at java.util.Arrays.copyOf(Arrays.java:3236) 
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113) 
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93) 
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:140) 

Вопрос в том, должны ли два способа зацикливания не совпадать? Если нет, то я хотел бы знать, как петли и while отличаются в использовании памяти в Java.

+2

см. 1 в условии цикла: for (int bytesRead = fileInputStream. read (buffer); bytesRead! = 1;) – rafalopez79

+0

Похоже, ваше состояние изменяется от «! = -1» до «! = 1»? –

+0

Спасибо, что указали это. Исправлена ​​опечатка. –

ответ

7

В вашем цикле for вы устанавливаете bytesRead один раз, а не каждую итерацию, как в while. for -эквивалентны ваше время цикла будет:

for(int bytesRead; (bytesRead = fileInputStream.read(buffer)) != -1;) 

Или другой способ:

for(int bytesRead = fileInputStream.read(buffer); bytesRead != -1; bytesRead = fileInputStream.read(buffer)) 
2

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

for (int bytesRead = fileInputStream.read(buffer); bytesRead != 1;) 
    output.write(buffer, 0, bytesRead); 

Должно быть что-то вроде (и убедитесь, что bytesRead не -1)

for (int bytesRead = fileInputStream.read(buffer); bytesRead != -1;) { 
    output.write(buffer, 0, bytesRead); 
    bytesRead = fileInputStream.read(buffer); 
} 

И я действительно предлагаю вам попробовать write dumb code.

0

В цикле for вы проверяете, bytesRead != 1; в цикле while, вы проверяете, bytesRead != -1.

0

Когда в течение присвоить первое чтение в BytesRead вы размещаете начальное значение прочитанных байт. Это никогда больше не будет вызвано. Ence, вы пишете снова и снова, пока не уйдете из памяти, поскольку bytesRead никогда не будет -1.

Чтобы быть более точным, представьте себе типичный для: for(int i =0;i<x;i++). Как вы можете видеть из вашего типичного для int i = 0, вызывается только один раз. Прочитайте чтение внутри for и start bytesRead как 0.

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