- •Потоки данных. Работа с локальными файлами Цели работы
- •Порядок выполнения работы
- •Вопросы для самопроверки и защиты.
- •Организация ввода-вывода в Java
- •Классы потоков ввода-вывода
- •Иерархия классов потоков ввода-вывода
- •Консольный ввод/вывод
- •Файловый ввод/вывод
- •Получение свойств файла
- •Буферизованный ввод/вывод
- •Поток простых типов Java
- •Кодировка utf-8
- •Прямой доступ к файлу
- •Каналы обмена информацией
- •Сериализация объектов
Прямой доступ к файлу
Если необходимо интенсивно работать с файлом, записывая в него данные разных типов Java, изменяя их, отыскивая и читая нужную информацию, то лучше всего воспользоваться методами класса RandomAccessFile.
В конструкторах этого класса
RandomAccessFile(File file, String mode)
RandomAccessFile(String fileName, String mode)
вторым аргументом mode задается режим открытия файла. Это может быть строка "r" — открытие файла только для чтения, или "rw" — открытие файла для чтения и записи.
Этот класс собрал все полезные методы работы с файлом. Он содержит все методы классов DataInputStream и DataOutputStream, кроме того, позволяет прочитать сразу целую строку методом readLine () и отыскать нужные данные в файле.
Байты файла нумеруются, начиная с 0, подобно элементам массива. Файл снабжен неявным указателем (file pointer) текущей позиции. Чтение и запись производится, начиная с текущей позиции файла. При открытии файла конструктором указатель стоит на начале файла, в позиции 0. Текущую позицию можно узнать методом getFilePointer(). Каждое чтение или запись перемещает указатель на длину прочитанного или записанного данного. Всегда можно переместить указатель в новую позицию, роз методом seek (long pos). Метод seek(0) перемещает указатель на начало файла.
В классе нет методов преобразования символов в байты и обратно по кодовым таблицам, поэтому он не приспособлен для работы с кириллицей.
Каналы обмена информацией
В предыдущей главе мы видели, каких трудов стоит организовать правильный обмен информацией между потоками - thread. В пакете java.io есть четыре класса pipedxxx, облегчающие эту задачу.
В одном подпроцессе-потоке — источнике информации — создается объект класса PipedWriter или PipedOutputStream, в который записывается информация методами write () этих классов.
В другом .подпроцессе-потоке —приемнике информации — формируется объект класса PipedReader или PipedInputStream. Он связывается с объектом-источником с помощью конструктора или специальным методом connect (), и читает информацию методами read ().
Источник и приемник можно создать и связать в обратном порядке.
Так создается однонаправленный канал (pipe) информации. На самом деле это некоторая область оперативной памяти, к которой организован совместный доступ двух или более подпроцессов. Доступ синхронизируется, записывающие процессы не могут помешать чтению.
Если надо организовать двусторонний обмен информацией, то создаются два канала.
В листинге 5 метод run () класса Source генерирует информацию, для простоты просто целые числа k, и передает ее в канал методом pw. write (k). Метод run() класса Target читает информацию из канала методом pr.read(). Концы канала связываются с помощью конструктора класса Target. На рис. 6 видна последовательность записи и чтения информации.
Листинг 5. Канал обмена информацией
import java.io.*;
class Target extends Thread{
private PipedReader pr;
Target(PipedWriter pw){
try{
pr = new PipedReader(pw);
}catch(lOException e){
System.err.println("From Target(): " + e);
}
}
PipedReader getStream(){ return pr;}
public void run(){
while(true)
try{
System.out.println("Reading: " + pr.read());
}catch(IOException e){
System.out.println("The job's finished.");
System.exit(0);
}
}
}
class Source extends Thread{
private PipedWriter pw;
Source (){
pw = new PipedWriter();
}
PipedWriter getStream(){ return pw;}
public void run(){
for (int k = 0; k < 10; k++)
try{
pw.write(k);
System.out.println("Writing: " + k);
}catch(Exception e){
System.err.printlnf"From Source.run(): " + e) ;
}
}
}
class PipedPrWr{
public static void main(String[] args){
Source s = new Source();
Target t = new Target(s.getStream());
s.start();
t.start();
}
}
Рис. 6. Данные, передаваемые между подпроцессами-потоками