2010-09-09 4 views
5

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

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 Writer

Тогда у меня есть читательская программа, которая должна (ну я ожидал) блокировать до тех пор, написание файл еще не завершен (т. е. 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"); 
    } 
} 

Начать с:

ява ReaderFIS

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

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

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

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

других вариантов мною опробован были: чтение через GetChannel(), проверку через GetChannel(), если это может быть блокировка() ред, используя имеющейся(), стараясь прочитать() с использованием buffer, пытающийся readLine(), непрерывно записывая char acter в файле с паузой в 500 мсек между каждой записью, а не записью ничего, просто сохраняя файл открытым в Writer.
Ни один из этих вариантов не приводит к блокировке программы ReaderFIS, она всегда заканчивается.

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

"Funny" sidenote: System.in.read() блокирует! (и ждет, пока пользователь нажмет Enter).

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

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

+0

Когда вы пишете на диск, вы вынуждаете EOF, нет? EOF только перемещается при добавлении новой информации. Но блок на диске должен иметь EOF ... – jcolebrand

+0

Итак, вы говорите, что EOF * всегда * написан, потому что файл всегда нужен. Но я думал, что EOF записывается только после завершения промывки и закрытия файла. Но это означает, что мой read() никогда не будет блокироваться при чтении файла, потому что всегда есть * EOF и всегда возвращает -1, даже если файл пуст. Так неправильный JavaDoc? – QQQuestions

ответ

0

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

+0

Я не совсем понимаю, что вы здесь говорите. – QQQuestions

+0

@qqquestions ok. Это предположение: «Тогда у меня также есть программа-читатель, которая должна (я ожидаю) блокировать, пока запись файла еще не завершена (например, pw.close() еще не вызывается)». совершенно неверно. Читатель/писатель не блокируют друг друга. (Только в том случае, если вы пытаетесь одновременно читать и записывать один файл, но это не так). google "non blocking io in java", вы найдете статьи, которые подробно объясняют мой ответ. – Andrey

+0

Почему вы говорите, что мои 2 программы не читают и не записывают один и тот же файл одновременно? Или вы имеете в виду * точно * в то же время?Я googled для ваших предложенных ключевых слов, но это не дало мне никаких новых идей, только хиты, объясняющие, что не блокирует IO. Вы говорите, что мой писатель и читатель не блокируются? Но почему JavaDoc скажет, что read() следует блокировать («Этот метод блокирует, если вход еще не доступен») и как он может даже читать файл, пока он еще не написан EOF? И я * хочу * мой read() блокировать, так как Java Doc говорит, что это должно быть, я не хочу неблокировать IO. – QQQuestions

1

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

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

+0

Вы говорите, что мой read() находится в конце потока? Почему? Writer все еще существует и файл/поток открыт. И что будет примером, когда FileInputStream.read() будет блокироваться? Пример кода будет большим ... – QQQuestions

+0

Это именно то, что я говорю. Я не могу представить, что FileInputStream.read() будет блокировать значительное количество времени для чтения локального файла. Блокировка - это то, что обычно происходит на других типах InputStreams, которые являются абстракциями вещей с более высокой задержкой (сокетные прочтения и т. Д.). – Seth

+0

Итак, Javadoc неверен? В нем говорится, что он блокирует FileInputStreams. – QQQuestions

1

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

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

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

  • старая версия файла
  • новая версия файла
  • обновленная версия файла.
+0

Итак, вы также подразумеваете, что Javadoc неверен, * Файл * InputStreams никогда не блокирует чтение? – QQQuestions

+1

Нет, javadoc говорит, что InputStreams будет блокировать *, если входные данные недоступны *. Я говорю, что FileInputStreams всегда имеет доступный вход, и поэтому, согласно javadoc, их не нужно блокировать. Технически они могут все еще блокироваться в некоторых случаях, например, чтение из файла с помощью FileLock, но это, похоже, не так. – gpeche

+0

Назовите меня придирчивым, но тогда документы должны были сказать, что теперь его можно прочитать (по мне :), поскольку он всегда блокируется, если вход еще не доступен. Я удивлен тем, что он видит EOF до того, как файл закрыт, но, по-видимому (как и в первом комментарии моего первоначального сообщения), всегда будет EOF, и поэтому его можно всегда читать. – QQQuestions

0

Вы не можете использовать файлы как трубы.

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

+0

Да, я думаю, что поведение, которое я ищу, - это поведение канала. Но мой вопрос в том, почему он не блокирует, в то время как Javadoc говорит, что он блокирует ... – QQQuestions

+0

Не так ли? Где это сказано? – EJP

+0

См. Мое начальное сообщение: считывает байт данных из этого входного потока. Этот метод блокирует, если вход еще не доступен. Через: http://download-llnw.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read%28%29 – QQQuestions