Конструкция чтения / записи Java

Может кто-нибудь объяснить мне, почему эта конструкция не будет работать:

while (fileInputStream.available()>0) {    
    fileOutputStream.write(fileInputStream.read());
}

и этот работает просто отлично:

while (fileInputStream.available()>0) {
    int data = fileInputStream.read();
    fileOutputStream.write(data);
}

Что касается меня, они идентичны, но 1-й не будет правильно записывать данные (напишет половину длины файла / данных).

3 ответа

Решение

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

Хороший переполнение стека Вопрос о наличии ()

JavaDoc доступен ()


Правильный способ проверить, достигли ли вы EOF, это проверить, read() метод вернулся -1:

int data = fileInputStream.read();
while (data != -1) {
    fileOutputStream.write(data);
    data = fileInputStream.read();
}

Этот метод, вероятно, будет довольно медленным, если вы попытаетесь читать большие объемы данных. Вы можете ускорить это, читая больше байтов, используя read(byte[] b, int off, int len) метод. Цикл будет очень похож на другой.

byte [] buffer = new byte[1024]; // 1kb buffer
int numBytesRead = fileInputStream.read(buffer);
while (numBytesRead != -1) {
    fileOutputStream.write(buffer, 0, numBytesRead);
    numBytesRead = fileInputStream.read(buffer);
}

Мой интерес к piqued Я написал этот маленький тест:

public static void main(String[] args) throws IOException {

    FileInputStream fileInputStream = new FileInputStream("/home/nick/foo");
    FileOutputStream fileOutputStream = new FileOutputStream("/home/nick/bar");
    fileOutputStream.write(fileInputStream.read());

    fileOutputStream.flush();
    fileOutputStream.close();
    fileInputStream.close();
}

Это сработало, как и ожидалось - прочитать один байт из /home/nick/foo и написал это /home/nick/bar

РЕДАКТИРОВАТЬ:

Обновленная программа:

public static void main(String[] args) throws IOException {

    FileInputStream fileInputStream = new FileInputStream("/home/nick/foo");
    FileOutputStream fileOutputStream = new FileOutputStream("/home/nick/bar");
    while (fileInputStream.available()>0) {    
        fileOutputStream.write(fileInputStream.read());
    }

    fileOutputStream.flush();
    fileOutputStream.close();
    fileInputStream.close();
}

Скопировал весь файл. (примечание: я бы не рекомендовал копировать файл по байтам за раз, используйте классы Buffered I/O для копирования целых кусков)

Вы случайно не забыли flush() а также close() в OutputStream?

Похоже, что ваш цикл while делает приблизительные вещи и пропускает кое-что.

public int available() throws IOException {
        return 0;
    }

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

Посмотреть здесь

Другие вопросы по тегам