Смекни!
smekni.com

Общие представления о языке Java 5 (стр. 53 из 68)

В конструкторе класса требуется указать два параметра. Первый – имя файла или файловую переменную, второй – строку с модой доступа к файлу. Имеются следующие варианты:

  • "r"- от read,- “только читать”
  • "rw"- от read and write,- “читать и писать”
  • "rws"- от read and write synchronously,- “читать и писать с поддержкой синхронизации” (см. далее раздел про потоки, Threads)
  • "rwd"- от read and write to device,- “читать и писать с поддержкой синхронизации устройства” (см. далее раздел про потоки, Threads)

Например:

java.io.RandomAccessFile rf1=new java.io.RandomAccessFile("q.txt","r");

java.io.RandomAccessFile rf2=new java.io.RandomAccessFile(file,"rw");

Рассмотрим примеры, иллюстрирующие работу с потоками.

Пример чтения текста из файла:

File file;

javax.swing.JFileChooser fileChooser=new javax.swing.JFileChooser();

javax.swing.filechooser.FileFilter fileFilter=new SimpleFileFilter(".txt");

private void openMenuItemActionPerformed(java.awt.event.ActionEvent evt) {

fileChooser.addChoosableFileFilter(fileFilter);

if(fileChooser.showOpenDialog(null)!=fileChooser.APPROVE_OPTION){

return;//Нажали Cancel

};

file = fileChooser.getSelectedFile();

try{

InputStream fileInpStream=new FileInputStream(file);

int size=fileInpStream.available();

fileInpStream.close();

char[] buff=new char[size];

Reader fileReadStream=new FileReader(file);

int count=fileReadStream.read(buff);

jTextArea1.setText(String.copyValueOf(buff));

javax.swing.JOptionPane.showMessageDialog(null,

"Прочитано "+ count+" байт");

fileReadStream.close();

} catch(Exception e){

javax.swing.JOptionPane.showMessageDialog(null,

"Ошибка чтения из файла \n"+file.getAbsolutePath());

}

}

Переменной fileInpStream , которая будет использована для работы потока FileInputStream , мы задаём тип InputStream . Это очень характерный приём при работе с потоками, позволяющий при необходимости заменять в дальнейшем входной поток с FileInputStream на любой другой без изменения последующего кода. После выбора имени текстового файла с помощью файлового диалога мы создаём файловый поток:

fileInpStream=new FileInputStream(file);

Функция fileInpStream.available()возвращает число байт, которые можно считать из файла. После её использования поток fileInpStream нам больше не нужен, и мы его закрываем. Поток FileReader не поддерживает метод available() , поэтому нам пришлось использовать поток типа FileInputStream.

Массив buff используется в качестве буфера, куда мы считываем весь файл.

Если требуется читать файлы большого размера, используют буфер фиксированной длины и в цикле считывают данные из файла блоками, равными длине буфера, до тех пор, пока число считанных байт не окажется меньше размера буфера. Это означает, что мы дошли до конца файла. В таком случае выполнение цикла следует прекратить. При такой организации программы нет необходимости вызывать метод available() и использовать поток типа FileInputStream.

В операторе

Reader fileReadStream=new FileReader(file);

используется тип Reader, а не FileReader, по той же причине, что до этого мы использовали InputStream , а не FileInputStream.

строки правильно работает только для ANSI

Построчное чтение из файла осуществляется аналогично, но содержимое блока try следует заменить на следующий код:

FileReader filReadStream=new FileReader(file);

BufferedReader bufferedIn=new BufferedReader(filReadStream);

String s="",tmpS="";

while((tmpS=bufferedIn.readLine())!=null)

s+=tmpS+"\n";

jTextArea1.setText(s);

bufferedIn.close();

Пример записи текста в файл очень похож на пример чтения, но гораздо проще, так как не требуется вводить промежуточные буферы и потоки:

private void saveAsMenuItemActionPerformed(java.awt.event.ActionEvent evt) {

fileChooser.addChoosableFileFilter(fileFilter);

if(fileChooser.showSaveDialog(null)!=fileChooser.APPROVE_OPTION){

return;//Нажали Cancel

};

file = fileChooser.getSelectedFile();

try{

Writer filWriteStream=new FileWriter(file);

filWriteStream.write(jTextArea1.getText() );

filWriteStream.close();

} catch(Exception e){

javax.swing.JOptionPane.showMessageDialog(null,

"Ошибка записи в файл \n"+file.getAbsolutePath());

}

}

Краткие итоги по главе 7

- В Java массивы являются объектами, но особого рода – их объявление отличается от объявления других видов объектов. Переменная типа массив является ссылочной. Массивы Java являются динамическими - в любой момент им можно задать новую длину.

- Двумерный массив представляет собой массив ячеек, каждая из которых имеет тип “одномерный массив”. Трёхмерный – массив двумерных массивов. Соответствующим образом они и задаются.

- Для копирования массивов лучше использовать метод System.arraycopy. Быстрое заполнение массива одинаковыми значениями может осуществляться методом Arrays.fill - класс Arrays расположен в пакете java.util Поэлементное сравнение массивов следует выполнять с помощью метода Arrays.equals (сравнение на равенство содержимого массивов) либо Arrays.deepEquals (глубокое сравнение, то есть на равенство содержимого, а не ссылок – на произвольном уровне вложенности). Сортировка (упорядочение по значениям) массива производится методом Arrays.sort.

- Коллекции (Collections) – “умные” массивы с динамически изменяемой длиной, поддерживающие ряд важных дополнительных операций по сравнению с массивами. Доступ к элементам коллекции в общем случае не может осуществляться по индексу, так как не все коллекции поддерживают индексацию элементов. Эту функцию осуществляют с помощью специального объекта – итератора (iterator). У каждой коллекции имеется свой итератор который умеет с ней работать.

- Класс String инкапсулирует действия со строками. Объект типа String – строка, состоящая из произвольного числа символов, от 0 до 2*109. Литерные константы типа String представляют собой последовательности символов, заключённые в двойные кавычки. В классе Object имеется метод toString(), обеспечивающий строковое представление любого объекта.

- Строки типа String являются неизменяемыми объектами – при каждом изменении содержимого строки создаётся новый объект-строка. Для того чтобы сделать работу с многочисленными присваиваниями более эффективной, используются классы StringBuffer и StringBuilder.

- Вывод графики осуществляется с помощью методов объекта типа java.awt.Graphics. Для того, чтобы результаты вывода не пропадали, в классе приложения требуется переопределить метод paint, вызываемый при отрисовке. А также обработчик события ComponentResized.

- Исключительные ситуации в Java являются объектами. Их типы являются классами-потомками объектного типа Throwable .От Throwable наследуются классы Error (“Ошибка”) и Exception (“Исключение”). Экземплярами класса Error являются непроверяемые исключительные ситуации, которые невозможно перехватить в блоках catch. Экземплярами класса Exception и его потомков являются проверяемые исключительные ситуации. Кроме одного потомка – класса RuntimeException (и его потомков).

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

- Объекты типа File обеспечивают работу с именами файлов и папок (проверка существования файла или папки с заданным именем, нахождение абсолютного пути по относительному и наоборот, проверка и установка атрибутов файлов и папок).

- При работе с файлами в подавляющем большинстве приложений требуется вызов файлового диалога JFileChooser (пакет javax.swing).

- Потоки ввода-вывода обеспечивают работу не только с файлами, но и с памятью, а также различными устройствами ввода-вывода. Соответствующие классы расположены в пакете java.io. Абстрактный класс InputStream (“входной поток”) инкапсулирует модель входных потоков, позволяющих считывать из них данные. Абстрактный класс OutputStream (“выходной поток”) - модель выходных потоков, позволяющих записывать в них данные.

- Для чтения строк (в виде массива символов) используются потомки абстрактного класса Reader (“читатель”). В частности, для чтения из файла – класс FileReader. Аналогично, для записи строк используются классы- потомки абстрактного класса Writer (“писатель”). В частности, для записи массива символов в файл– класс FileWriter.

- Имеется ещё один важный класс для работы с файлами - RandomAccessFile (“файл с произвольным доступом”), предназначенный для чтения и записи данных в произвольном месте файла. Такой файл с точки зрения класса RandomAccessFile представляет массив байт, сохранённых на внешнем носителе. Класс RandomAccessFile не является абстрактным, поэтому можно создавать его экземпляры.

-

Задания

  • Написать пример с графическим пользовательским интерфейсом для записи численных данных в файл и считывания их из файла с помощью классов FileInputStream/FileOutputStream (потомков InputStream/OutputStream). Использовать диалоги выбора файлов.
  • Написать пример с графическим пользовательским интерфейсом для записи численных данных в файл и считывания их из файла с помощью класса RandomAccessFile. Использовать диалоги выбора файлов.
  • Написать пример с графическим пользовательским интерфейсом для записи строковых данных в файл из компонента JTextArea и считывания их из файла с помощью класса RandomAccessFile. Использовать диалоги выбора файлов. Проверить работу с русским языком при записи и чтении текста в различных кодировках (ANSI, UNICODE,UTF-8).
  • Написать пример сложения, вычитания, умножения матриц задаваемых пользователем размеров. Для визуального представления матриц использовать компоненты JTable. Действия проводить с помощью массивов чисел типа double.
  • Усложнить пример, добавив возможность сохранения каждой из трёх матриц в текстовый файл, и загрузки первых двух матриц из текстового файла.

Глава 8. Наследование: проблемы и альтернативы. Интерфейсы. Композиция