среда, 8 августа 2018 г.

Java IO - часть 1

Что бы программы ни делали, рано или поздно у большинства из них возникает задача сохранить результаты своей деятельности. В самом простом случае в роли такого хранилища выступает файловая система.
Популярность Java на старте не в последнюю очередь была обусловлена тем, что Java содержала развитые средства для работы с файловой системой и потоками байтов. Эти средства называют системой ввода-вывода - или Java IO (Input & Output). Если вы в полной мере овладеете Java IO, то будете не единожды чувствовать себя в роли пресловутого Ослика ИА, наблюдая, как замечательно входят и выходят потоки данных в и из вашей программы=)


Классы системы ввода-вывода находятся в пакете java.io, и первый взгляд на них ужасает - около 90 классов, некоторые из которых понять не представляется возможным - такое оттолкнет даже самые пытливые умы. Но не следует пугаться, на самом деле Java IO базируется на довольно простых концепциях, о которых я сейчас вам расскажу.
Терминология
Во-первых, нужно твердо уяснить, что файловая система, файлы, директории - все это в разных операционных системах устроено очень по-разному. Но поскольку Java - кроссплатформенный язык, то работать с различными файловыми системами она должна одинаково. Поэтому файловая система в представлении Java - это некая абстракция, позволяющая работать с теми свойствами, которые реализованы практически во всех широко распространенных файловых системах. 
Базовая сущность файловой системы - это файл. Операции с файлами делятся на 2 большие группы: те, которые работают с содержимым файла (чтение, запись и т.п.), и те, которые не затрагивают содержимое файлов (переименование, удаление, перемещение и т.п.). 
В этой статье мы рассмотрим вторую группу операций.
Работа с файлами и директориями
Итак, базовая сущность файловой системы - это файл. Для работы с этой сущностью существует класс java.io.File. Этот класс представляет собой как простые файлы, так и директории (папки). 
Допустим, у нас есть папка "C:/temp" и мы хотим работать с файлом 1.bin в этой папке. Чтобы это сделать - нужно сначала создать объект класса File. Отмечу, что создание объекта класса File не создает файл непосредственно в файловой системе, речь идет лишь об объекте в памяти. Напишем простую программу, которая демонстрирует как прочитать основные свойства файла:
import java.io.File;

public class BrowseFile {
    public static void main(String[] args) {
        //Создаем объект класса File
        File file = new File("C:/temp/1.bin");
        //exists() - проверяет, существует ли такой файл в файловой системе
        System.out.println(file.exists());
        //isFile() - указывает ли объект на простой файл
        System.out.println(file.isFile());
        //isDirectory() - указывает ли объект на на директорию
        System.out.println(file.isDirectory());
        //canRead() - есть ли права на чтение этого файла
        System.out.println(file.canRead());
        //canWrite() - есть ли права на изменение этого файла
        System.out.println(file.canWrite());
        //canExecute() - есть ли права на запуск этого файла
        System.out.println(file.canExecute());
        //getName() - возвращает имя файла (включая расширение)
        System.out.println(file.getName());
        //getAbsolutePath() - возвращает полный путь до файла
        System.out.println(file.getAbsolutePath());
        //getParent() - возвращает путь до директории, в которой лежит файла
        System.out.println(file.getParent());
        //lastModified() - время последнего изменения файла
        System.out.println(file.lastModified());
        //length() - размер файла
        System.out.println(file.length());
    }
}
Если мы хотим создать файл:
import java.io.File;
import java.io.IOException;

public class CreateFile {
    public static void main(String[] args) throws IOException {
        //Создаем объект класса File
        File file = new File("D:/1.bin");
        boolean created = file.createNewFile();
        System.out.println("created = " + created);
    }
}
created - показывает, удалось ли создать файл. Если такой файл уже существует - то метод createNewFile() вернет false.

Теперь создадим папку:
import java.io.File;
import java.io.IOException;

public class CreateDirectory {
    public static void main(String[] args) throws IOException {
        //Создаем объект класса File
        File file = new File("D:/xxx");
        boolean created = file.mkdir();
        System.out.println("created = " + created);
    }
}
Как и в случае с файлом, created показывает, удалось ли создать папку.
Нужно отметить, что если папка, в которой вы хотите создать свою папку, не существует, то метод mkdir() вернет false и папка не будет создана.
Для того, чтобы создать свою папку и все папки выше, если их нет, нужно использовать метод mkdirs():
import java.io.File;
import java.io.IOException;

public class CreateDirectory {
    public static void main(String[] args) throws IOException {
        //Создаем объект класса File
        File file = new File("D:/xxx/yyy/zzz");
        boolean created = file.mkdirs();
        System.out.println("created = " + created);
    }
}
Чтение списка файлов
Для того, чтобы получить список файлов внутри директории, класс File имеет метод listFiles(). Этот метод возвращает массив объектов типа File (файлов и директорий), которые находятся внутри первоначальной директории. При использовании этого метода всегда нужно помнить, что он может возвращать null.
Итак, напишем программу, которая распечатывает абсолютные пути файлов внутри директории "C:/TOOLS/apache-maven-3.5.2", с указанием, файл это или директория:
import java.io.File;

public class ListFiles {
    public static void main(String[] args) {
        File directory = new File("C:/TOOLS/apache-maven-3.5.2");
        File[] files = directory.listFiles();
        if(files != null) {
            for(File file: files) {
                if (file.isFile()) {
                    System.out.println("Файл: " + file.getAbsolutePath());
                } else if(file.isDirectory()) {
                    System.out.println("Директория: " + file.getAbsolutePath());
                }
            }
        }
    }
}
Результат этой работы выглядит приблизительно так:
Директория: C:\TOOLS\apache-maven-3.5.2\bin
Директория: C:\TOOLS\apache-maven-3.5.2\boot
Директория: C:\TOOLS\apache-maven-3.5.2\conf
Директория: C:\TOOLS\apache-maven-3.5.2\lib
Файл: C:\TOOLS\apache-maven-3.5.2\LICENSE
Файл: C:\TOOLS\apache-maven-3.5.2\NOTICE
Файл: C:\TOOLS\apache-maven-3.5.2\README.txt
Удаление файлов
Удаление файлов происходит довольно тривиально - вызовом метода delete() класса File. Следует помнить, что для успешного удаления папки, необходимо предварительно удалить ее содержимое. В общем случае удаление папки происходит так:
import java.io.File;

public class ListFiles {
    public static void main(String[] args) {
        File directory = new File("C:\\u01");
        boolean deleted = delete(directory);
        System.out.println("deleted = " + deleted);
    }

    private static boolean delete(File file) {
        //Если это папка - сначала удаляем все вложенные файлы и директории(рекурсивно)
        if(file.isDirectory()) {
            File[] files = file.listFiles();
            if(files != null) {
                for(File f: files) {
                    boolean deleted = delete(f);
                    if(!deleted) {
                        return deleted;
                    }
                }
            }
            return file.delete();
        }
        return file.delete();
    }
}
Заключение
Ну что ж, дорогой читатель, на этом я завершу вводную статью в Java IO. Мы научились создавать файлы и папки удалять, читать их свойства и осуществлять навигацию по файловой системе. 
В следующей статье рассмотрим более сложную и важную тему - потоки!

Комментариев нет:

Отправить комментарий