Статьи
Утилиты Telegram YouTube Отзывы

Как сохранить текстовый файл

Видеогайд

8 мая 2022

Тэги: Java, файлы.

Содержание

  1. Генерируем большую случайную строку
  2. Запись с помощью FileWriter
  3. Добавляем буферизацию
  4. Неблокирующая запись файла
  5. Выводы

Давайте сгенерируем строку из случайных символов на Java и затем сохраним её в текстовый файл. На этом примере рассмотрим несколько вариантов сохранения. Строка должна быть очень большой (более 100 миллионов символов), чтобы мы могли легко заметить разницу во времени, которое требуется на сохранение файла.

Генерируем большую случайную строку

Приведу код метода, который в цикле генерирует случайные UUID и формирует результирующую строку, в которой эти UUID разделены символом перевода строки.

public String prepareData(int count) {
    var data = new StringBuilder();
    for (int i = 0; i < count; i++) {
        data.append(UUID.randomUUID()).append(System.lineSeparator());
    }
    return data.toString();
}

Для формирования результирующей строки используем StringBuilder, который не вызовет накладных расходов при большом количестве конкатенаций строк в цикле. Чтобы ставить правильный символ перевода строки, который зависит от вашей ОС, используем метод lineSeparator(). Каждый UUID имеет фиксированную длину, равную 36 символам.

Запись с помощью FileWriter

Один из самых простых способов записать данные в текстовый файл – это использовать класс FileWriter. Метод принимает на вход экземпляр класса File и сами данные в виде строки. Данные пишем с помощью метода write().

public void writeFileSimple(File file, String content) {
    try (var fw = new FileWriter(file)) {
        fw.write(content);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Обратите внимание, что FileWriter нужно обязательно инициализировать в конструкции try-with-resources, который автоматически освободит ресурс, связанный с этим файлом, при выходе из этого блока. Иначе пришлось бы явно вызывать метод close(). Для удобства перехватываем все исключения и оборачиваем их в RuntimeException, чтобы не прописывать их в сигнатуре метода.

Данный метод сохраняет текстовый файл размером 111 МБ на моём ноуте с SSD примерно за 300 миллисекунд.

Добавляем буферизацию

Этот метод можно значительно ускорить, добавив буферизацию потока. Для этого «обернём» FileWriter в BufferedWriter. Он также должен быть в секции инициализации try-with-resources.

public void writeFileBuffered(File file, String content) {
    try (
            var fw = new FileWriter(file);
            var bw = new BufferedWriter(fw)
    ) {
        bw.write(content);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Метод write() будем вызывать уже у буферизованного потока. Когда выйдем из блока try, JVM автоматически закроет BufferedWriter, а заодно с ним и FileWriter, поскольку один «обёрнут» в другой.

Данный метод сохраняет тот же файл размером 111 МБ примерно за 170 миллисекунд. То есть буферизация потока ускоряет запись файла почти в 2 раза!

Неблокирующая запись файла

Запись можно ещё немного ускорить, если использовать статический класс Files из пакета nio (неблокирующий ввод-вывод). В нём есть метод writeString(), который принимает экземпляр класса Path (его получаем из File), саму строку для записи и параметры открытия файла (мы здесь всегда создаём файл заново, поэтому CREATE).

public void writeFileNio(File file, String content) {
    try {
        Files.writeString(Paths.get(file.toURI()), content, StandardOpenOption.CREATE);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Данный метод сохраняет файл размером в 111 МБ в среднем за 145 миллисекунд, то есть ещё чуть быстрее.

Выводы

Как видите, даже огромные текстовые файлы по 100 МБ Java сохраняет менее, чем за секунду. Если вы работаете с маленькими файлами, разницы между рассмотренными реализациями почти нет. Однако быстрее всех оказался неблокирующий Files.writeString(). Если он вам по каким-то причинам не подходит, то обязательно используйте BufferedWriter.



Комментарии

Добавить комментарий

×

devmark.ru