1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-thinking-in-java-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
10.4 File类.md 23 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 11.03.2025 09:15 d56454c

10.4 Класс File

Класс File имеет вводящее в заблуждение название — обычно можно подумать, что он работает с одним файлом, но это не совсем так. Он представляет как имя конкретного файла, так и набор имен файлов внутри директории. Если он представляет собой набор файлов, то метод list() может использоваться для получения списка этих файлов, который возвращает массив строк. Возвращается массив, а не более гибкий объект коллекции, потому что количество элементов является постоянным. Чтобы получить список файлов для другой директории, достаточно создать новый объект File. На самом деле, FilePath (путь к файлу) кажется более подходящим названием. В этом разделе мы полностью продемонстрируем использование этого класса, включая связанный интерфейс FilenameFilter (фильтр имени файла).

10.4.1 Директорий листер

Предположим, что нам нужно просмотреть список файлов в директории. Для объекта 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 представляет собой список отсортированных директорий.

Атрибуты

  • path: объект типа File, представляющий путь к текущей директории.
  • list: массив строк, содержащий названия файлов в директории.

Конструктор

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 успешно решила эту проблему.

10.4.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 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-thinking-in-java-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-thinking-in-java-zh.git
oschina-mirror
wizardforcel-thinking-in-java-zh
wizardforcel-thinking-in-java-zh
master