Запись данных в поток и чтение данных из потока
Для обмена данными с потоками можно использовать как простейшие методы write и read, так и методы, допускающие ввод или вывод форматированных данных. В зависимости от того, на базе какого класса создан поток, зависит набор доступных методов, предназначенных для чтения или записи данных.
Простейшие методы
Создав выходной поток на базе класса FileOutputStream, вы можете использовать для записи в него данных три разновидности метода write, прототипы которых представлены ниже:
public void write(byte b[]);
public void write(byte b[],
int off, int len);
public void write(int b);
Первый из этих методов записывает в поток содержимое массива, ссылка на который передается через параметр, начиная с текущей позиции в потоке. После выполнения записи текущая позиция продвигается вперед на число записанных байт, которое при успешном завершении операции равно длине массива (b.length).
Второй метод позволяет дополнительно указать начальное смещение off записываемого блока данных в массиве и количество записываемых байт len.
Третий метод просто записывает в поток один байт данных.
Если в процессе записи происходит ошибка, возникает исключение IOException.
Для входного потока, созданного на базе класса FileInputStream, определены три разновидности метода read, выполняющего чтение данных:
public int read();
public int read(byte b[]);
public int read(byte b[],
int off, int len);
Первая разновидность просто читает из потока один байт данных. Если достигнут конец файла, возвращается значение -1.
Вторая разновидность метода read читает данные в массив, причем количество прочитанных данных определяется размером массива. Метод возвращает количество прочитанных байт данных или значение -1, если в процессе чтения был достигнут конец файла.
И, наконец, третий метод позволяет прочитать данные в область массива, заданную своим смещением и длиной.
Если при чтении происходит ошибка, возникает исключение IOException.
Методы для чтения и записи форматированных данных
Вместо того чтобы записывать в потоки и читать оттуда отдельные байты или массивы байт, программисты обычно предпочитают пользоваться намного более удобными методами классов DataOutputStream и DataInputStream, допускающими форматированный ввод и вывод данных.
Вот, например, какой набор методов можно использовать для записи форматированных данных в поток класса DataOutputStream:
public final void writeBoolean(boolean v);
public final void writeByte(int v);
public final void writeBytes(String s);
public final void writeChar(int v);
public final void writeChars(String s);
public final void writeDouble(double v);
public final void writeFloat(float v);
public final void writeInt(int v);
public final void writeLong(long v);
public final void writeShort(int v);
public final void writeUTF(String s);
Хотя имена методов говорят сами за себя, сделаем замечания относительно применения некоторых из них.
Метод writeByte записывает в поток один байт. Это младший байт слова, которое передается методу через параметр v. В отличие от метода writeByte, метод writeChar записывает в поток двухбайтовое символьное значение (напомним, что в Java символы хранятся с использованием кодировки Unicode и занимают два байта).
Если вам нужно записать в выходной поток текстовую строку, то это можно сделать с помощью методов writeBytes, writeChars или writeUTF. Первый из этих методов записывает в выходной поток только младшие байты символов, а второй - двухбайтовые символы в кодировке Unicode. Метод writeUTF предназначен для записи строки в машинно-независимой кодировке UTF-8.
Все перечисленные выше методы в случае возникновения ошибки создают исключение IOException, которое вы должны обработать.
В классе DataInputStream определены следующие методы, предназначенные для чтения форматированных данных из входного потока:
public final boolean readBoolean();
public final byte readByte();
public final char readChar();
public final double readDouble();
public final float readFloat();
public final void readFully(byte b[]);
public final void readFully(byte b[],
int off, int len);
public final int readInt();
public final String readLine();
public final long readLong();
public final short readShort();
public final int readUnsignedByte();
public final int readUnsignedShort();
public final String readUTF();
public final static String readUTF(
DataInput in);
public final int skipBytes(int n);
Обратите внимание, что среди этих методов нет тех, что специально предназначены для четния данных, записанных из строк методами writeBytes и writeChars класса DataOutputStream.
Тем не менее, если входной поток состоит из отдельных строк, разделенных символами возврата каретки и перевода строки, то такие строки можно получить методом readLine. Вы также можете воспользоваться методом readFully, который заполняет прочитанными данными массив байт. Этот массив потом будет нетрудно преобразовать в строку типа String, так как в классе String предусмотрен соответствующий конструктор.
Для чтения строк, записанных методом writeUTF вы должны обязательно пользоваться методом readUTF.
Метод skipBytes позволяет пропустить из входного потока заданное количество байт.
Методы класса DataInputStream, предназначенные для чтения данных, могут создавать исключения IOException и EOFException. Первое из них возникает в случае ошибки, а второе - при достижении конца входного потока в процессе чтения.