Класс File
имеет вводящее в заблуждение название — обычно можно подумать, что он работает с одним файлом, но это не совсем так. Он представляет как имя конкретного файла, так и набор имен файлов внутри директории. Если он представляет собой набор файлов, то метод list()
может использоваться для получения списка этих файлов, который возвращает массив строк. Возвращается массив, а не более гибкий объект коллекции, потому что количество элементов является постоянным. Чтобы получить список файлов для другой директории, достаточно создать новый объект File
. На самом деле, FilePath
(путь к файлу) кажется более подходящим названием. В этом разделе мы полностью продемонстрируем использование этого класса, включая связанный интерфейс FilenameFilter
(фильтр имени файла).
Предположим, что нам нужно просмотреть список файлов в директории. Для объекта File
существует два способа получения списка. Если вызвать list()
без параметров, будет получен полный список файлов, содержащихся в объекте File
. Однако, если требуется ограничить этот список, можно использовать "фильтр директории", который указывает, какие объекты File
следует выбрать для отображения.
Вот пример кода для этого (или обратитесь к разделу 3.1.2 главы 3 "Присваивание" при возникновении проблем с выполнением программы):```java //: DirList.java // Отображает список файлов в директории package c10; import java.io.*;
public class DirList { public static void main(String[] args) { try { File path = new File("."); String[] list; if(args.length == 0) list = path.list(); else list = path.list(new DirFilter(args[0])); for(int i = 0; i < list.length; i++) System.out.println(list[i]); } catch(Exception e) { e.printStackTrace(); } } }
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` реализует интерфейс `FilenameFilter` (о интерфейсах подробнее рассказано в главе 7). Давайте взглянем на простоту интерфейса `FilenameFilter`:
public interface FilenameFilter { boolean accept(файл_директория, строка_имя); }
Этот интерфейс указывает, что все объекты данного типа предоставляют метод с именем `accept()`. Создание такого класса полностью обосновано тем, чтобы предоставить метод `accept()` методу `list()`, позволяющему последнему «обратиться» к `accept()`, чтобы определить, какие имена файлов включить в список. Поэтому эту технику обычно называют «callback», а иногда — «оператором» (то есть `DirFilter` является оператором, так как его единственная цель — содержать один метод). Поскольку `list()` принимает объект типа `FilenameFilter` в качестве своего параметра, мы можем передать объект любого класса, реализующего `FilenameFilter`, который будет использоваться для определения поведения метода `list()` даже во время выполнения программы. Цель callback-механизма заключается в обеспечении большей гибкости поведения кода. С помощью `DirFilter` мы видим, что хотя "интерфейс" состоит из серии методов, он не ограничивается только этими методами (хотя обязательно должны быть определены все методы внутри этого интерфейса. В данном случае конструктор `DirFilter` также создает его).
Перевод:
public interface FilenameFilter { boolean accept(файл_директория, строка_имя); }
Этот интерфейс указывает, что все объекты данного типа предоставляют метод с именем `accept()`. Создание такого класса полностью обосновано тем, чтобы предоставить метод `accept()` методу `list()`, позволяющему последнему обратиться к `accept()`, чтобы определить, какие имена файлов включить в список. Поэтому эту технику обычно называют «callback», а иногда — «оператором» (то есть `DirFilter` является оператором, так как его единственная цель — содержать один метод). Поскольку `list()` принимает объект типа `FilenameFilter` в качестве своего параметра, мы можем передать объект любого класса, реализующего `FilenameFilter`, который будет использоваться для определения поведения метода `list()` даже во время выполнения программы. Цель callback-механизма заключается в обеспечении большей гибкости поведения кода. С помощью `DirFilter` мы видим, что хотя "интерфейс" состоит из серии методов, он не ограничивается только этими методами (хотя обязательно должны быть определены все методы внутри этого интерфейса. В данном случае конструктор `DirFilter` также создает его).Метод `accept()` должен принимать объект типа `File`, который используется для указания директории, в которой следует найти определённый файл; а также принимать строку типа `String`, содержащую имя файла, который требуется найти. Можно использовать один или оба этих параметра, но иногда хотя бы имя файла должно использоваться. Учитывайте, что метод `list()` готов вызвать `accept()` для каждого имени файла в объекте директории, чтобы проверить, какие из них следует включить — это зависит от булева результата, возвращаемого `accept()`.
Чтобы убедиться, что мы работаем только с именами файлов, не содержащими информации о пути, необходимо использовать объект типа `String` и создать объект типа `File` вне него. Затем вызывается метод `getName()`, который выполняет удаление всех данных о путях (в независимой от платформы форме). После этого метод `accept()` использует метод `indexOf()` класса `String` для проверки наличия строки `"afn"` внутри имени файла. Если строка `"afn"` найдена в строке, то возвращается начальный индекс этой строки; если же она не найдена, то возвращается значение -1. Обратите внимание, что это всего лишь простой пример поиска строки, не использующий общие шаблоны "шаблонов", такие как `"fo?.b?r*"`; реализация таких шаблонов более сложна.Метод `list()` возвращает массив. Его можно проверять по длине, а затем проходить через него, выбирая элементы массива. Это удобство перехода между внутренней и внешней средой массива представляет собой значительное улучшение по сравнению с поведением в C и C++.(1) Анонимный внутренний класс
Ниже представлен пример использования анонимного внутреннего класса (обсужденного в главе 7), который идеально подходит для переписывания. Сначала создается метод `filter()`, который возвращает ссылку на объект типа `FilenameFilter`:
```java
//: DirList2.java
// Использует анонимные внутренние классы Java 1.1
import java.io.*;
public class DirList2 {
public static FilenameFilter
filter(final String afn) {
// Создание анонимного внутреннего класса:
return new FilenameFilter() {
String fn = afn;
public boolean accept(File dir, String n) {
// Удаление информации о пути:
String f = new File(n).getName();
return f.indexOf(fn) != -1;
}
}; // Конец анонимного внутреннего класса
}
public static void main(String[] args) {
try {
File path = new File(".");
String[] list;
if(args.length == 0)
list = path.list();
else
list = path.list(filter(args[0]));
for(int i = 0; i < list.length; i++)
System.out.println(list[i]);
} catch(Exception e) {
e.printStackTrace();
}
}
}
///:~
Примечание: В данном случае используется псевдо-кодовое представление для демонстрации перевода, так как прямой перевод синтаксиса Java на русский язык невозможен. Операторы и ключевые слова остаются без изменений.
Обратите внимание, что аргумент filter()
должен быть объявлен как final
. Это требование для анонимных внутренних классов, чтобы они могли использовать объект, находящийся вне своей области видимости.Причина того, почему это считается лучшим подходом, заключается в том, что класс FilenameFilter
теперь тесно связан с классом DirList3
. Однако можно сделать ещё один шаг и определить анонимный внутренний класс как параметр метода list()
, сделав его более компактным. Вот пример:
//: DirList3.java
// Создание анонимного внутреннего класса "на месте"
import java.io.*;
public class DirList3 {
public static void main(final String[] args) {
try {
File path = new File(".");
String[] list;
if(args.length == 0)
list = path.list();
else
list = path.list(
new FilenameFilter() {
public boolean
accept(File dir, String n) {
String f = new File(n).getName();
return f.indexOf(args[0]) != -1;
}
});
for(int i = 0; i < list.length; i++)
System.out.println(list[i]);
} catch(Exception e) {
e.printStackTrace();
}
}
} ///:~
Аргументы метода main()
объявлены как final
, так как анонимный внутренний класс использует args[0]
.
Это демонстрирует, как можно быстро создать компактный класс, решив некоторые сложные задачи с помощью анонимных внутренних классов. Поскольку всё в Java является классами, это действительно полезная техника программирования. Одним из преимуществ этого подхода является возможность изолировать конкретную проблему в одном месте и решить её целиком. Однако сгенерированный таким образом код может быть трудным для чтения, поэтому следует применять этот подход осторожно.## Класс SortedDirList
Класс SortedDirList
представляет собой список отсортированных директорий.
File
, представляющий путь к текущей директории.public SortedDirList(final String afn) {
path = new File(".");
if(afn == null)
list = path.list();
else
list = path.list(new FilenameFilter() {
public boolean accept(File dir, String n) {
String f = new File(n).getName();
return f.indexOf(afn) != -1;
}
});
sort();
}
print
Метод выводит содержимое списка файлов на консоль:
void print() {
for(int i = 0; i < list.length; i++)
System.out.println(list[i]);
}
sort
Приватный метод сортирует список файлов:
private void sort() {
StrSortVector sv = new StrSortVector();
for(int i = 0; i < list.length; i++)
sv.addElement(list[i]);
// При первом вызове метода `elementAt` список будет отсортирован:
for(int i = 0; i < list.length; i++)
list[i] = sv.elementAt(i);
}
main
Основной метод для тестирования класса SortedDirList
:public static void main(String[] args) {
SortedDirList sd;
if(args.length == 0)
sd = new SortedDirList(null);
else
sd = new SortedDirList(args[0]);
sd.print();
}
Здесь были внесены небольшие улучшения. Теперь path
(путь) и list
(список) являются членами класса, а не локальными переменными метода main()
, что позволяет удобно обращаться к их значениям на протяжении всего срока жизни объекта. В действительности, main()
теперь служит лишь способом тестирования класса. Можно заметить, что после создания списка конструктор класса автоматически начинает его сортировку.
Эта сортировка не требует учета регистра символов, поэтому в результате не получится списка, где все слова начинаются с заглавной буквы, за которым следуют все слова с маленькой буквой. Однако мы замечаем, что среди групп файлов, начинающихся с одной и той же буквы, заглавные буквы располагаются перед строчными — это всё ещё недопустимое поведение для стандартной сортировки. Java 1.2 успешно решила эту проблему.
File
представляет не только существующий путь к директории, файл или группу файлов. Он также может использоваться для создания нового каталога или даже полного пути к каталогу, если он ещё не существует. Кроме того, можно использовать его для получения свойств файла (размер, последнее изменение, права доступа и прочее), проверки является ли объект типа File
файлом или директорией, а также удаления файла. Ниже приведён пример программы, демонстрирующей использование остальных методов класса File
:```java//: MakeDirectories.java // Demonstration of using the File class for creating directories and manipulating files. import java.io.*;
```markdown
публичный класс MakeDirectories {
приватный константный стринг использование =
"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";
приватный статический вункция использование() {
Систем. err. println(использование);
Систем. exit(1);
}
приватный статический вункция файлДанные(Файл f) {
Систем. out. println(
"Absolute path: " + f.getAbsolutePAth() +
"\nCan read: " + f.canRead() +
"\nCan write: " + f.canWrite() +
"\ngetName: " + f.getName() +
"\ngetParent: " + f.getParent() +
"\ngetPath: " + f.getPath() +
"\nlength: " + f.length() +
"\nlastModified: " + f.lastModified());
если(f.isFile())
Систем. out. println("This is a file");
ещё_если(f.isDirectory())
Систем. out. println("This is a directory");
}
публичный статический вункция основной(стринг[] аргументы) {
если(аргументы.length < 1) использование();
если(аргументы[0].равняется("-r")) {
если(аргументы.length != 3) использование();
Файл
старый = новый Файл(аргументы[1]),
новое_имя = новый Файл(аргументы[2]);
старый.renameTo(новое_имя);
файлДанные(старый);
файлДанные(новое_имя);
вернуть; // Exit main
}
целое счет = 0;
логическое удаление = ложь;
если(аргументы[0].равняется("-d")) {
удаление = правда;
счет++;
}
}
```равняется ("-d")) {
счет++;
удаление = true;
}
для (; счет < аргументы.length; счет++) {
Файл f = новый Файл(аргументы[счет]);
если (f.exists()) {
Систем.out.println(f + " существует");
если (удаление) {
Систем.out.println("Удаляем... " + f);
f.delete();
}
}
ещё { // Не существует
если (! удаление) {
f.mkdirs();
Систем.out.println("Создано " + f);
}
}
файлДанные(f);
}
}
```В методе fileData()
, можно заметить использование различных методов для исследования файлов, чтобы отобразить информацию, связанную с путями файлов или директорий.Метод `renameTo()` используется первым в методе `main()`. Этот метод позволяет переименовать (или переместить) файл в новую папку (путь которой задается аргументами), которая принадлежит другому объекту типа `File`. Это также применимо к любому количеству директорий.
При тестировании вышеописанной программы, вы сможете создать путь любой сложности, так как метод mkdirs()
выполняет всю необходимую работу за вас. В Java 1.0 флаг -d
указывал на то, что директория была удалена, но всё ещё существовала; однако начиная с Java 1.1 директория действительно удалялась.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )