7. Основы Kotlin. Файловые операции

Программы, которые мы пишем, так или иначе должны взаимодействовать с пользователем и внешней средой — операционной системой, устройствами компьютера, сетью Интернет. Простейшим способом взаимодействия является ввод с консоли и вывод на консоль, но сейчас такой способ применяется крайне редко. Более совершенным способом взаимодействия являются файлы — многие программы берут из них настроечную или входную информацию, и используют их для сохранения результатов своей работы или различных настроек. Например, всевозможные редакторы позволяют открывать файлы в определённом формате, просматривать и/или изменять их, сохранять файлы на диске компьютера или в сети Интернет.

В библиотеке Java внутри пакета java.io имеется ряд типов, обеспечивающих возможность работы с файлами, а библиотека Котлина дополняет их некоторыми удобными возможностями. Как обычно, рассмотрим часть этих возможностей на примере.

import java.io.File
/**
 * Пример
 *
 * Во входном файле с именем inputName содержится некоторый текст.
 * Вывести его в выходной файл с именем outputName, выровняв по левому краю,
 * чтобы длина каждой строки не превосходила lineLength.
 * Слова в слишком длинных строках следует переносить на следующую строку.
 * Слишком короткие строки следует дополнять словами из следующей строки.
 * Пустые строки во входном файле обозначают конец абзаца,
 * их следует сохранить и в выходном файле
 */
fun alignFile(inputName: String, lineLength: Int, outputName: String) {
    val writer = File(outputName).bufferedWriter()
    var currentLineLength = 0
    for (line in File(inputName).readLines()) {
        if (line.isEmpty()) {
            writer.newLine()
            if (currentLineLength > 0) {
                writer.newLine()
                currentLineLength = 0
            }
        }
        for (word in line.split(Regex("\\s+"))) {
            if (currentLineLength > 0) {
                if (word.length + currentLineLength >= lineLength) {
                    writer.newLine()
                    currentLineLength = 0
                }
                else {
                    writer.write(" ")
                    currentLineLength++
                }
            }
            writer.write(word)
            currentLineLength += word.length
        }
    }
    writer.close()
}

Краеугольный тип, используемый для работы с файлами в Котлине — тип java.io.File. В соответствии с названием, он предназначен для различных операций с файлами; объект этого типа соответствует какому-либо реальному файлу, чаще всего находящемуся на жёстком диске. Для создания файла используется специальная функция-конструктор: File(inputName) или File(outputName) в примере. Если в аргументе конструктора указано только имя файла — поиск файла происходит в текущей директории, а если аргумент содержим также путь к файлу — то в директории, указанной этим путём. Специфика конструктора заключается в том, что его имя совпадает с типом объекта, которую он создаёт, и он имеет результат соответствующего типа. Более подробно мы поговорим о конструкторах в следующем уроке.

Обмен данными с файлом может происходить в режиме чтения либо в режиме записи. В режиме чтения информации, заданное имя должно соответствовать уже существующему файлу. Один из способов получения информации из файла — вызов функции file.readLines(). Результат вызова — список строк, из которых состоит файл. Каждый Stringв этом списке соответствует одной строке файла, строки файла разделяются символом «возврат каретки» и / или «новая строка».

В режиме записи информации, заданное имя может не соответствовать существующему файлу — в этом случае он будет создан. Для записи информации, необходимо создать один из объектов, обеспечивающих такую возможность. В примере, таким объектом является val writer = File(outputName).bufferedWriter() — то есть необходимо вызвать функцию bufferedWriter() на получателе, соответствующем исходному файлу. Как видно из текста примера, writer(писатель) имеет функции writer.newLine() (добавление в файл новой строки), writer.write(string) (добавление в файл заданной строки) и writer.close() (закрытие писателя, выполняется строго ПОСЛЕ выполнения всех остальных действий и фиксирует итоговое состояние файла).

Мы перечислили все файловые операции, присутствующие в исходном примере. Внутри цикла for, каждая из строк файла разбивается по пробелам на слова, с этой целью используется Regex("\\s+"). В currentLineLengthнакапливается длина текущей строки ВЫХОДНОГО файла. Если в текущей строке достаточно места для очередного слова ВХОДНОГО файла, слово добавляется в текущую строку, в противном случае в файл добавляется перевод строки и слово добавляется в новую строку. Пустые строки входного файла, как и сказано в задании, переносятся в выходной файл без изменений.

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