Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЭУМК_ИТИРОД(Часть 1).docx
Скачиваний:
34
Добавлен:
11.05.2015
Размер:
1.17 Mб
Скачать

7.4 Класс Properties

Класс Properties расширяет класс Hashtabie . Он предназначен в основном для ввода и вывода пар свойств системы и их значений. Пары хранятся в виде строк типа String . В классе Properties два конструктора:

Properties () — создает пустой объект;

Properties (Properties default) — создает объект с заданными парами свойств default .

Кроме унаследованных от класса Hashtabie методов в классе Properties есть еще следующие методы.

Два метода, возвращающих значение ключа-строки в виде строки:

String getProperty (String key) — возвращает значение по ключу key ;

String getProperty(String.key, String defaultValue) — возвращает значение по ключу key ; если такого ключа нет, возвращается defaultValue .

Метод setProperty(String key, String value) добавляет новую пару, если ключа key нет, и меняет значение, если ключ key есть.

Метод load(Inputstream in ) загружает свойства из входного потока in .

Методы list(PrintStream out) И list (PrintWriter out) выводят свойства в выходной поток out.

Метод store (OutputStream out, String header) выводит свойства в выходной поток out с заголовком header .

Очень простой листинг 23 и рис. 17 демонстрируют вывод всех системных свойств Java.

Листинг 23. Вывод системных свойств

class Prop {

public static void main(String[] args) {

System.getProperties().list(System.out);

}

}

Примеры классов Vector, Stack, Hashtabie, Properties показывают удобство классов-коллекций. Поэтому в Java 2 разработана целая иерархия коллекций. Она показана на рис. 18. Курсивом 'записаны имена интерфейсов. Пунктирные линии указывают классы, реализующие эти интерфейсы. Все коллекции разбиты; на три группы, описанные в интерфейсах List, Set и Map.  

Рис. 17. Системные свойства

Рис. 18. Иерархия классов и интерфейсов-коллекций

Примером реализации интерфейса List может служить класс Vector , примером реализации интерфейса мар — класс Hashtable .

8. Система ввода/вывода в Java

8.1 Класс File

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

Класс File имеет обманчивое имя — вы можете подумать, что он ссылается на файл, но это не так. Он может представлять либоимяопределенного файла, либоимянабора файлов в директории. Если это набор файлов, вы можете опросить набор с помощью метода list( ), который вернет массив String. Есть смысл возвращать массив, а не гибкий класс контейнера, потому что число элементов фиксировано, и если вам нужен список другого директория, вы просто создаете другой объект File. Фактически, “FilePath” был бы лучшим именем для класса. Этот раздел покажет пример использования этого класса, включая ассоциированный FilenameFilter interface.

Список директории

Предположим, вы хотите получить список директории. Объект Fileможет выдать его двумя способами. Если вы вызовитеlist( )без аргументов, вы получите полный список, содержащийся в объектеFile. Однако если вы хотите ограничить список, например, если вы хотите получить все файлы с расширением.java, то вам нужно использовать “фильтр директории”, который является классом, который определяет, как использовать объектFileдля отображения.

Здесь приведен код примера. Обратите внимание, что результат без труда будет храниться (в алфавитном порядке) при использовании метода java.utils.Array.sort( ).

import java.io.*;

import java.util.*;

public class DirList {

public static void main(String[] args) {

File path = new File(".");

String[] list;

if(args.length == 0)

list = path.list();

else

list = path.list(new DirFilter(args[0]));

Arrays.sort(list,

new AlphabeticComparator());

for(int i = 0; i < list.length; i++)

System.out.println(list[i]);

}

}

class DirFilter implements FilenameFilter {

String afn;

DirFilter(String afn) { this.afn = afn; }

public boolean accept(File dir, String name) {

// Получение информации о пути:

String f = new File(name).getName();

return f.indexOf(afn) != -1;

}

}

Класс DirFilter “реализует” interface FilenameFilter. Полезно посмотреть, насколько прост FilenameFilter interface:

public interface FilenameFilter {

boolean accept(File dir, String name);

}

Это говорит о том, что этот тип объекта должен обеспечивать метод, называемый accept( ). Главная цель создания этого класса заключается в обеспечении метода accept( ) для метода list( ), так как list( ) может выполнять “обратный вызов” accept( ) для определения, какое имя файла должно включаться в список. Эта техника часто называетсяобратным вызовомили иногдафунктором(то есть, DirFilter - это функтор, потому что он выполняет работу по поддержанию метода) илиКомандой Заполнения. Потому что list( ) принимает объект FilenameFilter в качестве аргумента, это означает, что вы можете передать объект любого класса, который реализует FilenameFilter для выбора (даже во время выполнения) поведения метода list( ). Назначение обратного вызова заключается в обеспечении гибкого поведения кода.

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

Метод accept( ) должен принимать объект File, представляющий директорий, в котором находится определенный файл, а String содержит имя этого файла. Вы можете выбрать использовать или игнорировать любой из этих аргументов, но вы, вероятно, как минимум, должны использовать имя файла. Помните, что метод list( ) вызывает метод accept( ) для каждого имени файла в директории, чтобы проверить, какой из них должен быть включен — на это указывает тип boolean результата, возвращаемого accept( ).

Чтобы убедится, что элемент, с которым вы работаете, является всего лишь именем файла и не содержит информации о пути, все, что вам нужно сделать, это получить объект String и создать из него объект File, затем вызвать getName( ), который отсекает всю информацию о пути (платформонезависимым способом). Затем accept( ) использует метод indexOf( ) класса String, чтобы убедится, что искомая строка afn присутствует в любом месте имени файла. Если afn найдено в строке, возвращаемым значением является начальный индекс afn, а если не найдено, возвращаемым значением является -1. Имейте в виду, что это простой поиск строк и не имеет “глобальных” выражений подстановочных символов, таких как fo?.b?r*”, которые являются более сложными в реализации.

Метод list( ) возвращает массив. Вы можете опросить этот массив о его длине, а затем пройтись по нему, выбирая элементы массива. Эта способность легкого прохода по массиву вне методов и в методах является значительным улучшением по сравнению с поведением C и C++.

Поиск и создание директориев

Класс File - это больше, чем просто представление существующего файла или директория. Вы также можете использовать объект File для создания новой директории или целого пути директорий, если этот путь не существует. Вы можете также взглянуть на характеристики файлов (размер, дату последней модификации, доступ на чтение/запись), посмотреть, представляет ли объект File файл или директорий, и удалить файл. Эта программа показывает некоторые методы, поддерживаемые классом File (смотрите HTML документацию наjava.sun.com чтобы увидеть полный набор):

import java.io.*;

public class MakeDirectories {

private final static String usage =

"Usage:MakeDirectories path1 ...\n" +

"Creates each path\n" +

"Usage:MakeDirectories -d path1 ...\n" +

"Deletes each path\n" +

"Usage:MakeDirectories -r path1 path2\n" +

"Renames from path1 to path2\n";

private static void usage() {

System.err.println(usage);

System.exit(1);

}

private static void fileData(File f) {

System.out.println(

"Absolute path: " + f.getAbsolutePath() +

"\n Can read: " + f.canRead() +

"\n Can write: " + f.canWrite() +

"\n getName: " + f.getName() +

"\n getParent: " + f.getParent() +

"\n getPath: " + f.getPath() +

"\n length: " + f.length() +

"\n lastModified: " + f.lastModified());

if(f.isFile())

System.out.println("it's a file");

else if(f.isDirectory())

System.out.println("it's a directory");

}

public static void main(String[] args) {

if(args.length < 1) usage();

if(args[0].equals("-r")) {

if(args.length != 3) usage();

File

old = new File(args[1]),

rname = new File(args[2]);

old.renameTo(rname);

fileData(old);

fileData(rname);

return; // Выход из main

}

int count = 0;

boolean del = false;

if(args[0].equals("-d")) {

count++;

del = true;

}

for( ; count < args.length; count++) {

File f = new File(args[count]);

if(f.exists()) {

System.out.println(f + " exists");

if(del) {

System.out.println("deleting..." + f);

f.delete();

}

}

else { // Не существует

if(!del) {

f.mkdirs();

System.out.println("created " + f);

}

}

fileData(f);

}

}

}

В fileData( ) вы можете видеть различные способы исследования файла для отображения информации о файле или о пути директории.

Первый метод, который вызывается main( ) - это renameTo( ), который позволяет вам переименовать (или переместить) файл по введенному новому путь, представленному аргументом, который является другим объектом типа File. Это так же работает с директориями любой длины.

Если вы поэкспериментируете с приведенной выше программой, вы обнаружите, что вы можете создать путь директорий любой сложности, потому что mkdirs( ) будет делать всю работу за вас.