При побайтовом чтении символов из форматированного потока DatalnputStream методом readByte() любое полученное значение будет считаться действительным, поэтому возвращаемое значение неприменимо для идентификации конца потока. Вместо этого можно использовать метод available(), который сообщает, сколько еще осталось символов. В следующем примере показано, как читать файл побайтно:
//: io/TestEOF.java
// Проверка достижения конца файла одновременно
// с чтением из него по байту.
import java.io *;
public class TestEOF {
public static void main(String[] args) throws IOException {
DatalnputStream in = new DataInputStream( new BufferedInputStream(
new FilelnputStreamCTestEOF java"))), while(in.available() != 0)
System.out print((char)in readByteO);
}
} ///:-
Заметьте, что метод available() работает по-разному в зависимости от источника данных; дословно его функция описывается следующим образом: «количество байтов, которые можно прочитать
Определить конец входного потока можно и с помощью перехвата исключения. Впрочем, применение исключений в таких целях считается злоупотреблением.
Вывод в файл
Объект FileWriter записывает данные в файл. При вводе/выводе практически всегда применяется буферизация (попробуйте прочитать файл без нее, и вы увидите, насколько ее отсутствие влияет на производительность — скорость чтения уменьшится в несколько раз), поэтому мы присоединяем надстройку BufferedWriter. После этого подключается PrintWriter, чтобы выполнять форматированный вывод. Файл данных, созданный такой конфигурацией ввода/вывода, можно прочитать как обычный текстовый файл.
//: io/BasicFileOutput.java
import java.io.*;
public class BasicFi1eOutput {
static String file = "BasicFileOutput out", public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader( new StringReader(
BufferedlnputFile read("BasicFileOutput java"))), PrintWriter out = new PrintWriter(
new BufferedWriter(new Fi1eWriter(fi1e))), int lineCount = 1, String s,
whi 1 e((s = in readLineO) != null )
out println(lineCount++ + " " + s). out closeO.
// Вывод содержимого файла
System out println(BufferedInputFile readCfile)).
}
} /// ~
При записи строк в файл к ним добавляются их номера. Заметьте, что надстройка LineNumberlnputStream для этого
Когда данные входного потока исчерпываются, метод readLine() возвращает null. Для потока outl явно вызывается метод close(); если не вызвать его для всех выходных файловых потоков, в буферах могут остаться данные, и файл получится неполным.
Сокращенная форма вывода текстового файла
В Java SE5 у PrintWriter появился вспомогательный конструктор. Благодаря ему вам не придется вручную выполнять всю работу каждый раз, когда вам потребуется создать текстовый файл и записать в него данные. Вот как выглядит пример BasicFileOutput.java в обновленном виде:
//• io/FileOutputShortcut java import java io *.
public class FileOutputShortcut {
static String file = "FileOutputShortcut.out", public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader( new StringReader(
BufferedlnputFile readC'FileOutputShortcut java"))); // Сокращенная запись PrintWriter out = new PrintWriter(file); int lineCount = 1, String s,
while((s = in.readLineO) != null )
out println(lineCount++ + " + s). out closeO.
// Вывод содержимого файла-
System out.printin(BufferedInputFile readCfile));
}
} ///;-
Буферизация по-прежнему обеспечена, но вам не приходится включать ее самостоятельно. К сожалению, для других распространенных операций сокращенной записи не предусмотрено, поэтому типичный код ввода/вывода по-прежнему содержит немало избыточного текста.
Сохранение и восстановление данных
PrintWriter форматирует данные так, чтобы их мог прочитать человек. Однако для вывода информации, предназначенной для другого потока, следует использовать классы DataOutputStream (для записи данных) и DatalnputStream (для чтения данных). Конечно, природа этих потоков может быть любой, но в нашем случае открывается файл, буферизованный как для чтения, так и для записи. Надстройки DataOutputStream и DatalnputStream ориентированы на посылку байтов, поэтому для них требуются потоки OutputStream и InputStream:
II- io/StoringAndRecoveringData.java import java io *,
public class StoringAndRecoveringData {
public static void main(String[] args) throws IOException {
DataOutputStream out = new DataOutputStream( new BufferedOutputStream(
new FileOutputStreamC'Data.txt"))); out.writeDouble(3.14159); out.writeUTFCThat was pi"); out. writeDoubled. 41413); out.writeUTFC"Square root of 2"); out.closeO;
DatalnputStream in = new DataInputStream( new BufferedlnputStreamC