2012-02-14 3 views
3

Это должно быть очень просто, и я искал Google, но не видел, чтобы кто-то упоминал проблему, которую я заметил. Все, что я видел, делает то же самое. Как это:Чтение из InputStream и запись в OutputStream

byte [] buffer = new byte[256]; 
int bytesRead = 0; 
while((bytesRead = input.read(buffer)) != -1) 
{ 
    output.write(buffer, 0, bytesRead); 
} 

Я знаю, читал() возвращает -1, когда EOF будет достигнута, но что, если файл меньше, чем буфер или даже того же размера? Пример Fox, читается 200-байтный файл. Предполагаю, что он читает 200 байтов, но возвращает -1. Это соответствует javadocs, но это также означает, что write() никогда не вызывается. Я бы ожидал, что на самом деле скажу, что он читает 200 байт, а на следующей итерации - -1.

Как я могу обойти эту «проблему»?

+0

Показать, как создается «input» и что происходит с ним перед этим вызовом 'read()'. – erickson

+0

Как бы то ни было, этот вопрос «неполный». – erickson

+0

Возможный дубликат [Легкий способ записи содержимого Java InputStream в OutputStream] (http://stackoverflow.com/questions/43157/easy-way-to-write-contents-of-a-java-inputstreamtoto -an-outputstream) – rds

ответ

12

FYI, Guava имеет ByteStreams.copy(InputStream, OutputStream), который вы можете использовать напрямую или посмотреть, как он решает эту проблему.

+0

Гуава, я не слышал об этом. Я нашел много полезных библиотек Google Java. Я взглянул на код для copy(), и он по существу делает то, что я есть, но write() никогда не вызывается в моем случае. Я снова взгляну на свой код. Вот как я ожидал, что это сработает. Точно так же, как говорят все, кто прокомментировал это. – Amac

1

Для обнаружения конца непустого потока потребуется не менее двух вызовов read(). Один для чтения содержимого, затем другой для возврата EOF.

В качестве примера, если в буфере было 256 байт, а в файле только 200 байт, вызов read(byte[]) вернет 200 (или последовательность результатов вызова будет равна 200), затем последующие вызовы будут возвращать -1 в сигнал EOF.

Это не совсем понятно, как вы интерпретировали Javadoc для InputStream, но это ясно говорит о том, что она возвращает количество прочитанных байтов, и возвращает -1 только, когда не было больше данных для чтения.

Если длина b равна нулю, то никакие байты не читаются и возвращается 0; в противном случае, есть попытка прочитать хотя бы один байт. Если байт не доступен, поскольку поток находится в конце файла, возвращается значение -1; в противном случае, по меньшей мере, один байт считывается и сохраняется в b.

Далее:

Возвращает: Общее количество считанных байтов в буфер, или -1 [если] там [являются] нет больше данных, потому что конец потока был достигнут.

+0

2 читает? Это то, чего я ожидал, но это не так. Если мой файл меньше, чем тот буфер, который я использую, он возвращает -1 при первом вызове raad(). Это технически достигло EOF, поэтому он делает то, что говорит джавадок. Однако он ничего не говорит о 200 байтах, которые он прочитал. Используя цикл while, который я опубликовал, write() никогда не вызывается. – Amac

+0

@ user1209868 Тогда у вас есть ошибка в другом месте вашего кода. (Ваше сообщение не показывает полную историю потока, от открытия файла до этой точки, где read возвращает -1.) Как указано выше, в документации четко указано, можно ли читать какие-либо байты, возвращается неотрицательный счет ; Javadoc делает ** не ** говорит, что -1 будет возвращен, если будут прочитаны некоторые байты. Либо ваш поток пуст для начала, либо какая-то предшествующая операция поглотила данные, которые она хранила. – erickson

0

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

От the java documentation (1.4)

Если ни один байт не доступен, потому что поток в конце файла, то возвращается значение -1; в противном случае, по меньшей мере один байт считывается и сохраняется в b.

Это действительно то, что вы хотите. Он считывает 200 байтов (или все остальное в файле и меньше, чем указанный буфер) и возвращает -1 на следующей итерации.

+0

Я понимаю, что говорит джавадок. Когда я вызываю read(), он заполняет буфер до тех пор, пока он не достигнет EOF (мой буфер больше, чем файл). И, как говорится в документации, он возвращает -1. Он делает это, но не должен сначала сказать мне, что он читает 200 байт, а затем при последующих вызовах read() return -1. – Amac

+0

@ user1209868 Он возвращает -1, когда он ничего не читает, кроме EOF, а не раньше. Если он что-то читает, он возвращает счетчик чтения. – EJP

7

Ваш код

byte [] buffer = new byte[256]; 
int bytesRead = 0; 
while((bytesRead = input.read(buffer)) != -1) { 
    output.write(buffer, 0, bytesRead); 
} 

работает нормально.

Например представьте, у вас есть файл с 300 символов (600 байт):

Шаг 1. Буфер будет считывать 256 байт и переписывает их к выходу; 344 осталось до EOF

Шаг 2. Буфер считывает 256 байтов и переписывает их на выход; 88 осталось до EOF

Шаг 3. Буфер прочитает 88 байтов (byteRead == 88) и перепишет их для вывода; EOF оставил

Шаг 4. EOF (input.read(buffer) возвращает -1)

... редактировать

Выше шагов не теория. Я получаю это путем перезаписи фактического содержимого файла с помощью этого кода:

static void rewrite() throws IOException { 
    InputStream input = new FileInputStream("file1.txt"); 
    OutputStream output = new FileOutputStream("file2.txt"); 
    byte[] buffer = new byte[256]; 
    int bytesRead = 0; 
    while ((bytesRead = input.read(buffer)) != -1) { 
     System.out.println(bytesRead); 
     output.write(buffer, 0, bytesRead); 
    } 
} 

Возможно, что-то не так с вашей конфигурацией.

+0

Это то, чего я ожидал бы, но мне кажется, что на шаге 3 он возвращается -1. Я снова перейду через мой код, но я сделал это несколько раз с тем же результатом. – Amac

+0

@ user1209868 см. Редактировать – msi

0

Я предполагаю, что читать 200 байт, но возвращает -1

Нет, читает 200 байт и возвращает 200. Это совершенно ясно из Javadoc, и вы могли бы также пробовали достаточно легко.

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