System.out.println('Read data from file: ' + fileName); // Считывать данные, отображая на экран while((s=br.readLine())!=null) System.out.println('row ' + ++count + ' read:' + s); br.close(); } catch(Exception e) { e.printStackTrace(); } Пример 15.15.
Классы-мосты InputStreamReader и OutputStreamWriter при преобразовании символов также используют некоторую кодировку. Ее можно задать, передав в конструктор в качестве аргумента ее название. Если оно не будет соответствовать никакой из известных кодировок, будет брошено исключение UnsupportedEncodingException. Вот некоторые из корректных значений этого аргумента (чувствительного к регистру!) для распространенных кодировок: 'Cp1251', 'UTF-8', '8859_1' и т.д.
Класс StreamTokenizer
Экземпляр StreamTokenizer создается поверх существующего объекта, либо InputStream, либо Reader. Как и java.util.StringTokenizer, этот класс позволяет разбивать данные на лексемы (token), выделяемые из потока по определенным свойствам. Поскольку работа ведется со словами, конструктор, принимающий InputStream, объявлен как deprecated (предлагается оборачивать байтовый поток классом InputStreamReader и вызывать второй конструктор). Общий принцип работы такой же, как и у StringTokenizer, – задаются параметры разбиения, после чего вызывается метод nextToken(), пока не будет достигнут конец потока. Способы задания разбиения у StreamTokenizer довольно разнообразны, но просты, и поэтому здесь не рассматриваются.
Работа с файловой системой
Класс File
Если классы потоков осуществляют реальную запись и чтение данных, то класс File – это вспомогательный инструмент, призванный обеспечить работу с файлами и каталогами.
Объект класса File является абстрактным представлением файла и пути к нему. Он устанавливает только соответствие с ним, при этом для создания объекта неважно, существует ли такой файл на диске. После создания можно выполнить проверку, вызвав метод exists, который возвращает значение true, если файл существует. Создание или удаление объекта класса File никоим образом не отображается на реальных файлах. Для работы с содержимым файла можно получить экземпляры FileI/OStream.
Объект File может указывать на каталог (узнать это можно путем вызова метода isDirectory ). Метод list возвращает список имен (массив String ) содержащихся в нем файлов (если объект File не указывает на каталог – будет возвращен null ).
Следующий пример демонстрирует использование объектов класса File:
import java.io.*; public class FileDemo { public static void findFiles(File file, FileFilter filter, PrintStream output) throws IOException{ if (file.isDirectory()) { File[] list = file.listFiles(); for (int i=list.length; --i>=0;) { findFiles(list[i], filter, output); } } else { if (filter.accept(file)) output.println(' ' + file.getCanonicalPath()); } } public static void main(String[] args) { class NameFilter implements FileFilter { private String mask; NameFilter(String mask) { this.mask = mask; } public boolean accept(File file){ return (file.getName().indexOf(mask)!=-1)?true:false; } } File pathFile = new File('.'); String filterString = '.java'; try { FileFilter filter = new NameFilter(filterString); findFiles(pathFile, filter, System.out); } catch(Exception e) { e.printStackTrace(); } System.out.println('work finished'); } } Пример 15.16.
При выполнении этой программы на экран будут выведены названия (в каноническом виде) всех файлов, с расширением .java, содержащихся в текущем каталоге и всех его подкаталогах.
Для определения того, что файл имеет расширение .java, использовался интерфейс FileFilter с реализацией в виде внутреннего класса NameFilter. Интерфейс FileFilter определяет только один метод accept, возвращающий значение, определяющее, попадает ли переданный файл в условия фильтрации. Помимо этого интерфейса, существует еще одна разновидность интерфейса фильтра – FilenameFilter, где метод accept определен несколько иначе: он принимает не объект файла к проверке, а объект File, указывающий на каталог, где находится файл для проверки, и строку его названия. Для проверки совпадения, с учетом регулярных выражений, нужно соответствующим образом реализовать метод accept. В конкретном приведенном примере можно было обойтись и без использования интерфейсов FileFilter или FilenameFilter. На практике их можно использовать