Почему FileInputStream read () не блокируется? - PullRequest
5 голосов
/ 09 сентября 2010

У меня есть программа Writer, которая записывает одну строку текста в файл, затем ждет, пока пользователь нажмет на клавишу возврата, прежде чем он пишет другую строку и затем завершает работу. Только после этого файл закрывается. Код:

public class Writer {

    Writer() {
    }

    public static String[] strings = 
        {
            "Hello World", 
            "Goodbye World"
        };

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

        java.io.FileOutputStream pw =
            new java.io.FileOutputStream("myfile.txt");

        for(String s : strings) {
            pw.write(s.getBytes());
            System.in.read();
        }

        pw.close();
    }
}

Начните сначала с:

Java писатель

Тогда у меня также есть программа для чтения, которая должна (как я и ожидал) блокировать, пока запись файла еще не закончена (т.е. pw.close () еще не вызывалось). Код:

public class ReaderFIS extends Object {

    ReaderFIS() {
    }

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

        java.io.FileInputStream in = new java.io.FileInputStream("myfile.txt");

        int ch = -1;
        while((ch = in.read()) >= 0) {
         System.out.println("ch = " + ch);
     }
        System.out.println("Last ch = " + ch);

     System.out.println("exiting");
    }
}

Начать с:

Java ReaderFIS

Теперь я ожидал, что read () заблокируется после прочтения первого текста «Hello World», основываясь на этом в документации Javadoc:

Считывает байт данных из этого входного потока. Этот метод блокируется, если вход еще не доступен. Через: http://docs.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read()

Но ReaderFIS сразу же завершает чтение «Hello World» и, по-видимому, видит EOF! Так что это не блок! Он сбрасывает значения символов, затем -1 и затем печатает "выход".

Выход: ch = 72 ch = 101 ch = 108 ch = 108 ch = 111 ch = 32 ch = 87 ch = 111 ch = 114 ch = 108 ch = 100 Последний ч = -1 выход

Другие варианты, которые я пробовал: чтение через getChannel (), проверка через getChannel (), можно ли его заблокировать (), использование available (), попытка read () с использованием буфера, попытка readLine (), непрерывная запись символ в файле с паузой 500 мсек между каждой записью, ничего не записывая, просто сохраняя файл открытым в Writer.
Ни один из этих вариантов не приводит к блокировке программы ReaderFIS, она всегда завершается.

Почему программа чтения не блокирует ? Я что-то упустил слишком очевидное? Кажется, что программа ReaderFIS находит EOF (-1), но почему? Файл еще не был закрыт программой Writer.

"Забавный" знак: System.in.read () блокируется! (и ждет, когда пользователь нажмет Enter).

PS: попробовал это на Windows XP и Suse Linux. В Windows я не могу удалить файл во время работы программы записи (как я и ожидал).

С уважением, Marco

Ответы [ 5 ]

1 голос
/ 09 сентября 2010

Ваша программа чтения просто читает все, что находится в файле, затем достигает конца и возвращает -1. Если все, что он содержит во время запуска, это «Hello World», то это все, что он сможет прочитать. Если вы запустите его снова после того, как нажмете Enter в своей записи, вы должны увидеть «Hello World Goodbye World».

Отсутствие доступных байтов и выход в конец потока - это две разные вещи. Вот почему блоки System.in.read () и FileInputStream.read () этого не делают.

1 голос
/ 10 сентября 2010

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

  • чтение с консоли / терминала
  • чтение из сети
  • чтение из трубы
  • чтение из любого потока, который ожидает данных.

Файловые потоки не должны ждать данных, поскольку они всегда имеют данные: в вашем случае read() получит, в основном случайным образом, одно из:

  • старая версия файла
  • новая версия файла
  • наполовину обновленная версия файла.
0 голосов
/ 22 мая 2012

Вам может понадобиться что-то, чтобы задержать фактическое чтение данных. Проверьте этот исходный код: http://www.java2s.com/Open-Source/Java/Web-Server/Jigsaw/org/w3c/jigsaw/ssi/DelayedInputStream.java.htm.

0 голосов
/ 10 сентября 2010

Нельзя использовать файлы в качестве каналов.

Однако вы можете использовать трубы в качестве труб.

0 голосов
/ 09 сентября 2010

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

...