Удалить строку из файла kotlin
В этом кратком руководстве мы узнаем о различных способах чтения файла в Kotlin.
Мы рассмотрим оба варианта использования: чтение всего файла в виде строки, а также чтение его в виде списка отдельных строк. Также получение его из полного абсолютного пути или из ресурса проекта.
2. Чтение файла
Давайте сначала создадим входной файл, который будет читать Котлин. Мы создаем файл под названием Kotlin.in и помещаем его в каталог, к которому может получить доступ наш код.
Содержимое файла может быть:
Теперь давайте рассмотрим различные способы чтения этого файла. Мы должны передать полный путь к созданному выше файлу в качестве входных данных для начальных методов и относительный путь в наших ресурсах для последних двух.
2.1. forEachLine
Считывает файл построчно с использованием указанной кодировки (по умолчанию - UTF-8) и вызывает действие для каждой строки:
2.2. useLines
Вызывает обратный вызов заданного блока, передавая ему последовательность всех строк в файле.
После завершения обработки файл закрывается:
2.3. bufferedReader
Возвращает новый BufferedReader для чтения содержимого файла.
Когда у нас есть BufferedReader , мы можем читать все строки в нем:
2.4. readLines
Непосредственно читает содержимое файла в виде списка строк:
Этот метод не рекомендуется использовать для больших файлов.
2.5. inputStream
Создает новый FileInputStream для файла и в результате возвращает его.
Получив входной поток, мы можем преобразовать его в байты, а затем в полную строку :
2.6. readText
Читает все содержимое файла как строку с указанной кодировкой (по умолчанию - UTF-8):
Этот метод не рекомендуется для больших файлов и имеет внутреннее ограничение на размер файла 2 ГБ.
2.7. getResource
Находит ресурс с заданным именем и возвращает объект URL :
Если он найдет ресурс, он вернет URL-адрес , который можно обработать, вызвав метод readText, как показано ранее. Если он не может найти ресурс, он возвращает null . При использовании getResource переданное в fileName не абсолютное имя файла, а имя относительно ресурсов нашего проекта.
2.8. getResourceAsStream
Находит ресурс с заданным именем и возвращает экземпляр InputStream :
Если он найдет ресурс, он вернет InputStream , который можно обработать, как показано ранее, например, получив BufferedReader . Если он не может найти ресурс, он возвращает null . При использовании getResourceAsStream переданное в fileName не абсолютное имя файла, а имя относительно ресурсов нашего проекта.
3. Заключение
В этой статье мы увидели различные способы чтения файла в Kotlin. В зависимости от варианта использования, мы можем выбрать чтение файла построчно или полностью как текст. Мы можем ссылаться на файл абсолютно или найти его среди ресурсов.
Глава 9. Операции ввода-вывода файлов, регулярные выражения и многопоточность
Мы уже ввели характеристики расширений классов в Kotlin в главе 6 «Функции и свойства расширений». Используя расширенную функцию Kotlin, мы можем напрямую реализовать функцию inc () для класса String, которая добавляет 1 к каждому символьному значению в строке.
Эта функция расширения реализована следующим образом
Благодаря мощным функциям расширения мы можем расширить множество «на первый взгляд нативных методов в классах Java» на основе библиотеки классов Java. Фактически, большое количество API в стандартной библиотеке Kotlin kotlin-stdlib реализовано путем расширения классов Java.
Операции файлового ввода-вывода, регулярные выражения и многопоточность, которые мы представим в этой главе, реализованы Kotlin путем расширения существующих классов Java. Сначала давайте введем чтение и запись файлов.
9.1 Файловые операции ввода-вывода
API операций ввода-вывода Kotlin находится в пакете kotlin.io. Принцип Котлина состоит в том, чтобы использовать Java напрямую, если он уже имеет хорошее применение, и расширять его на основе исходного класса, если он плохой или нет. Например, Котлин написал функции расширения для класса File.
Kotlin расширяет класс java.io.File множеством полезных функций расширения, которые находятся в файле исходного кода kotlin / io / FileReadWrite.kt. Мы рассмотрим это ниже.
В то же время, Kotlin также сделал простые расширения для InputStream, OutputStream и Reader. В основном они находятся в следующих двух исходных файлах:
kotlin/io/IOStreams.kt |
---|
kotlin/io/ReadWrite.kt |
Сериализация Колтина напрямую использует псевдоним типа класса сериализации Java:
Давайте кратко представим операции чтения и записи файла Kotlin. Общие API чтения и записи файлов в Kotlin показаны в следующей таблице
Подпись функции | Описание функции |
---|---|
File.readText(charset: Charset = Charsets.UTF_8): String | Прочитать все содержимое файла в виде строки |
File.readLines(charset: Charset = Charsets.UTF_8): List<String> | Прочитайте каждую строку файла, сохраните ее в List <String> и верните |
File.readBytes(): ByteArray | Прочитать все содержимое файла и вернуть его как ByteArray |
File.writeText(text: String, charset: Charset = Charsets.UTF_8): Unit | Перезаписать текстовую строку в файл |
File.writeBytes(array: ByteArray): Unit | Перезаписать массив байтов потоком ByteArray |
File.appendText(text: String, charset: Charset = Charsets.UTF_8): Unit | Добавить текстовую строку в конец файла |
File.appendBytes(array: ByteArray): Unit | Добавить ByteArray в конец файла |
9.1.1 Чтение файлов
readText: получить всю строку содержимого файла
Если мы просто читаем файл, мы можем использовать метод readText (), который напрямую возвращает все содержимое файла. Пример кода выглядит следующим образом
Мы напрямую используем объект File для вызова функции readText, чтобы получить все содержимое файла, которое возвращает строку. Если вы указываете кодировку символов, вы можете указать ее, передав параметр Charset.
readLines: получить содержимое каждой строки файла
Если мы хотим получить содержимое каждой строки файла, мы можем просто использовать split ("\ n"), чтобы получить массив каждой строки. Мы также можем напрямую вызвать инкапсулированную функцию readLines Kotlin, чтобы получить содержимое каждой строки файла. Функция readLines возвращает список строк, содержащих содержимое каждой строки.
readBytes: читать массив байтов
Если мы хотим напрямую манипулировать байтовым массивом файла, мы можем использовать функцию readBytes
bufferedReader
Получить BufferedReader для файла
9.1.2 Запись файлов
Используя расширенные функции Kotlin, запись в файл также довольно проста. Это похоже на чтение файла. Мы можем записать строку или поток байтов. Мы также можем напрямую вызвать класс Java Writer или OutputStream. Запись файлов обычно делится на два типа: перезапись (однократная запись) и добавление записи.
writeText: перезаписать файл записи
Мы используем функцию writeText для записи содержимого строкового текста непосредственно в файл
Где параметр destFile - это имя целевого файла (с каталогом).
appendFile: добавить запись файла в конце
Добавить запись в конец файла, используя текст функции appendFile
appendBytes
Добавить байтовый массив в файл
bufferedWriter
Получите BufferedWriter для файла
9.1.3. Обход файлового дерева
Kotlin предоставляет удобные функции для обхода дерева файлов.
функция ходьбы: пройтись по дереву файлов
В следующем примере выполняется перебор всех файлов в указанной папке.
Приведенный выше тестовый код выведет все подкаталоги и их файлы в текущем каталоге.
Мы также можем перебрать все файлы подкаталогов ниже текущего файла и сохранить его в Итераторе <File>
Мы перебираем все файлы подкаталогов в текущем файле, а также можем фильтровать по условиям и сохранять результаты в Sequence <File>
Обход дерева файлов требует вызова метода расширения walk (). Он вернет объект FileTreeWalk, и у него есть несколько методов для установки направления и глубины обхода, подробности см. В документации по FileTreeWalk API.
Копировать файлы рекурсивно
Скопируйте файл или рекурсивно скопируйте каталог и все его вложенные файлы по указанному пути. Если файл по указанному пути не существует, он будет создан автоматически.
copyRecursively подпись функции:
9.2 Сетевой ввод-вывод
Ниже мы просто напишем несколько примеров функций.
Получить ответ URL в соответствии с HTML-функцией URL
Получить функцию массива битов ответа URL в соответствии с URL
Записать байтовый массив ответа URL в файл
Следующий пример просто возвращает исходный код домашней страницы Baidu.
В следующем примере выполняется получение потока битов изображения на основе URL-адреса, а затем вызывается метод readBytes () для чтения потока байтов и записи его в файл.
Мы можем увидеть скачанный файл «picture.jpg» в соответствующей папке проекта.
9.3 Выполнение команд оболочки
Мы используем файловые операции ввода-вывода Groovy, которые кажутся очень полезными, такие как
Файловый IO и сетевой IO-операции в Kotlin так же просты, как Groovy.
Кроме того, из приведенного выше кода мы видим, что выполнить команды терминала с помощью Groovy очень просто:
В Kotlin такие функции, как класс String и Process, еще не расширены. На самом деле, расширение такой функции очень просто. Мы можем расширить себя.
Во-первых, давайте расширим функцию execute () строки.
Затем давайте расширим текстовую функцию до класса Process.
После выполнения двух простых функций расширения, описанных выше, мы можем выполнить команды терминала, такие как Groovy, в следующем тестовом коде:
Фактически, благодаря изучению многих предыдущих примеров, мы можем видеть, что функции расширения Котлина весьма практичны. Язык API Kotlin сам по себе широко использует расширения.
9.4 Регулярные выражения
В Kotlin, в дополнение к прежнему использованию Java Pattern, Matcher и других классов, Kotlin также предоставляет класс регулярного выражения kotlin / text / regex / Regex.kt. Мы используем конструктор Regex для создания регулярного выражения ,
9.4.1. Построение выражения регулярного выражения
Используйте конструктор Regex
Параметр сопоставления RegexOption является обычным параметром сопоставления в шаблоне класса Java, который используется напрямую.
Функция расширения ToRegex с использованием String
9.4.2 Функция регулярного выражения
Regex предоставляет множество простых и практичных функций, как показано в следующей таблице
Имя функции | Описание функции |
---|---|
matches(input: CharSequence): Boolean | Все входные строки совпадают |
containsMatchIn(input: CharSequence): Boolean | У входной строки есть хотя бы одно совпадение |
matchEntire(input: CharSequence): MatchResult? | Все входные строки совпадают, возвращают соответствующий объект результата |
replace(input: CharSequence, replacement: String): String | Заменить совпадающую часть входной строки содержимым замены |
replace(input: CharSequence, transform: (MatchResult) -> CharSequence): String | Замените совпадающее значение во входной строке новым значением после преобразования преобразования функции |
find(input: CharSequence, startIndex: Int = 0): MatchResult? | Возвращает первое совпадающее значение во входной строке |
findAll(input: CharSequence, startIndex: Int = 0): Sequence<MatchResult> | Возвращает последовательность всех совпадающих значений во входной строке |
Ниже мы приведем простые примеры вышеуказанных функций соответственно.
matches
Все входные строки соответствуют регулярному выражению и возвращают true, в противном случае возвращается false.
containsMatchIn
Возвращает true, если во входной строке есть хотя бы одно совпадение, и false, если совпадения нет.
matchEntire
Все входные строки соответствуют регулярному выражению и возвращают объект MatcherMatchResult, в противном случае он возвращает ноль.
Мы можем получить доступ к значению MatcherMatchResult, чтобы получить соответствующее значение.
Поскольку возвращением функции matchEntire является объект MatchResult? Nullable, здесь мы используем символ безопасного вызова ?. 。
replace(input: CharSequence, replacement: String): String
Замените соответствующую часть входной строки содержимым замены.
Мы можем видеть это в "12345XYZ" 12345 Соответствует регулярному выражению 9+ Содержание было заменено abcd 。
replace функция
Функция замены подписи выглядит следующим образом
Его функция заключается в замене сопоставленного значения во входной строке новым значением после преобразования преобразования функции.
Мы можем видеть, что 9XYZ8 Числа 9 и 8 соответствуют регулярным выражениям 3+ Содержимое, они соответственно отображаются с помощью функции преобразования (it.value.toInt() * it.value.toInt()).toString() Замените новые значения 81 и 64.
find функция
Возвращает первый соответствующий объект MatcherMatchResult во входной строке.
findAll
Возвращает последовательность MatchResults для всех совпадающих значений во входной строке.
Мы можем перебрать все совпадающие значения через цикл forEach
9.4.3. Классы регулярных выражений с использованием Java
В дополнение к функциям, предоставляемым Kotlin выше, мы все еще можем использовать API регулярных выражений Java в Kotlin.
Приведенный выше код запускает вывод:
9.5 Многопоточное программирование
У Kotlin нет синхронизированных и изменчивых ключевых слов. Kotlin Any похож на Java Object, но не имеет методов wait (), notify () и notifyAll ().
Так как же работает параллелизм в Котлине? Будьте уверены, поскольку Kotlin стоит на плечах Java, конечно, поддержка многопоточного программирования неизбежна - Kotlin упрощает наше кодирование, инкапсулируя классы потоков в Java. В то же время мы также можем использовать некоторые конкретные аннотации и напрямую использовать ключевые слова синхронизации в Java. Давайте кратко представим соответствующий контент многопоточного программирования с Kotlin.
9.5.1 Создать тему
У нас обычно есть два метода в Java для создания потоков в Java:
- Расширение класса Thread
- Или создайте его экземпляр и передайте Runnable через конструктор
Поскольку мы легко можем использовать классы Java в Kotlin, можно использовать оба метода.
Создание с использованием выражений объекта
Этот код использует объектное выражение Kotlin для создания анонимного класса и переопределяет метод run ().
Использование лямбда-выражений
Вот как передать Runnable во вновь созданный экземпляр Thread:
Мы не видим здесь Runnable. В Kotlin мы можем легко использовать вышеприведенное лямбда-выражение для его выражения.
Есть ли более простой способ? Посмотрите на объяснение ниже.
Использование Kotlin-обернутых потоковых функций
Например, мы написали следующий код потока
Следующие четыре строки можно назвать стандартным кодом. Инкапсуляция таких операций упрощена в Kotlin.
Этот код выглядит более упорядоченным и аккуратным. Фактически функция thread () является абстрактной инкапсуляцией стандартного кода, часто используемого в нашей практике программирования.
Это просто очень удобная функция обертки, простая и практичная. Из приведенного выше примера мы видим, что Kotlin упростил шаблонный код, расширив API-интерфейс потоков Java.
9.5.2. Методы и блоки синхронизации
синхронизированный - это не ключевое слово в Kotlin, оно заменяется аннотацией @Synchronized. Объявление синхронного метода в Kotlin будет выглядеть так:
Аннотация @Synchronized имеет тот же эффект, что и синхронизация в Java: она помечает методы JVM как синхронизированные. Для синхронизированных блоков мы используем функцию synchronized (), которая принимает блокировку в качестве параметра:
В основном так же, как Java.
9.5.3 Переменное поле
Аналогично, у Kotlin нет ключевого слова volatile, но есть аннотация @Volatile.
@Volatile помечает поля резервного копирования JVM как изменяемые.
Конечно, у нас есть лучшие параллельные библиотеки сопрограмм в Котлине. В практике разработки кода мы можем свободно выбирать в соответствии с реальной ситуацией.
Краткое содержание этой главы
Kotlin - очень практичный инженерный язык: из файлового ввода-вывода, регулярных выражений и многопоточности, представленных в этой главе, мы можем понять основные принципы Kotlin: в полной мере использовать существующую экологическую библиотеку Java и опираться на На нем есть более простые и практичные расширения, которые значительно повышают производительность труда программистов. Из этого мы также поняли минималистскую концепцию программирования Kotlin - постоянно абстрагируя, инкапсулируя и расширяя, делая ее более простой и практичной
Программы, которые мы пишем, так или иначе должны взаимодействовать с пользователем и внешней средой — операционной системой, устройствами компьютера, сетью Интернет. Простейшим способом взаимодействия является ввод с консоли и вывод на консоль, но сейчас такой способ применяется крайне редко. Более совершенным способом взаимодействия являются файлы — многие программы берут из них настроечную или входную информацию, и используют их для сохранения результатов своей работы или различных настроек. Например, всевозможные редакторы позволяют открывать файлы в определённом формате, просматривать и/или изменять их, сохранять файлы на диске компьютера или в сети Интернет.
В библиотеке Java внутри пакета java.io имеется ряд типов, обеспечивающих возможность работы с файлами, а библиотека Котлина дополняет их некоторыми удобными возможностями. Как обычно, рассмотрим часть этих возможностей на примере.
* Во входном файле с именем inputName содержится некоторый текст. * Вывести его в выходной файл с именем outputName, выровняв по левому краю, * чтобы длина каждой строки не превосходила lineLength. * Слова в слишком длинных строках следует переносить на следующую строку. * Слишком короткие строки следует дополнять словами из следующей строки. * Пустые строки во входном файле обозначают конец абзаца, fun alignFile ( inputName : String , lineLength : Int , outputName : String ) <Краеугольный тип, используемый для работы с файлами в Котлине — тип java.io.File . В соответствии с названием, он предназначен для различных операций с файлами; объект этого типа соответствует какому-либо реальному файлу, чаще всего находящемуся на жёстком диске. Для создания файла используется специальная функция-конструктор: File(inputName) или File(outputName) в примере. Если в аргументе конструктора указано только имя файла — поиск файла происходит в текущей директории, а если аргумент содержим также путь к файлу — то в директории, указанной этим путём. Специфика конструктора заключается в том, что его имя совпадает с типом объекта, которую он создаёт, и он имеет результат соответствующего типа. Более подробно мы поговорим о конструкторах в следующем уроке.
В режиме записи информации, заданное имя может не соответствовать существующему файлу — в этом случае он будет создан. Для записи информации, необходимо создать один из объектов, обеспечивающих такую возможность. В примере, таким объектом является val writer = File(outputName).bufferedWriter() — то есть необходимо вызвать функцию bufferedWriter() на получателе, соответствующем исходному файлу. Как видно из текста примера, writer (писатель) имеет функции writer.newLine() (добавление в файл новой строки), writer.write(string) (добавление в файл заданной строки) и writer.close() (закрытие писателя, выполняется строго ПОСЛЕ выполнения всех остальных действий и фиксирует итоговое состояние файла).
Мы перечислили все файловые операции, присутствующие в исходном примере. Внутри цикла for , каждая из строк файла разбивается по пробелам на слова, с этой целью используется Regex("\\s+") . В currentLineLength накапливается длина текущей строки ВЫХОДНОГО файла. Если в текущей строке достаточно места для очередного слова ВХОДНОГО файла, слово добавляется в текущую строку, в противном случае в файл добавляется перевод строки и слово добавляется в новую строку. Пустые строки входного файла, как и сказано в задании, переносятся в выходной файл без изменений.
Изменяемые коллекции поддерживают операции, изменяющие её содержимое, например, операции по добавлению и удалению элементов. В этом разделе описаны операции записи, доступные для всех реализаций MutableCollection . Более конкретные операции, доступные для List и Map , описаны в разделах List: специфичные операции и Map: специфичные операции.
Добавление элементов
Чтобы добавить один элемент в список или множество ( Set ), используйте функцию add() . Указанный объект будет добавлен в конец коллекции.
Функция addAll() добавляет все элементы из переданного в качестве аргумента объекта в список или множество. Аргументом может быть Iterable , Sequence , или Array . Типы объекта-получателя и аргумента могут быть разными, например, вы можете добавить все элементы из Set в List .
При вызове к списку addAll() добавляет новые элементы в том же порядке, в котором они находятся в коллекции-аргументе. Вы также можете передать addAll() позицию, в которую будет вставлен первый элемент из коллекции-аргумента. За ним последуют другие элементы из коллекции-аргумента, сдвигая элементы коллекции-получателя в конец.
Вы также можете добавлять элементы, используя in-place версию оператора plus - plusAssign ( += ). При применении к изменяемой коллекции += добавляет второй операнд (элемент или другую коллекцию) в конец коллекции.
Удаление элементов
Чтобы удалить элемент из изменяемой коллекции, используйте функцию remove() . Она принимает значение элемента в качестве аргумента и удаляет из коллекции одно вхождение этого значения.
Для одновременного удаления нескольких элементов существуют следующие функции:
-
- удаляет все элементы, присутствующие в коллекции-аргументе. В качестве альтернативы вы можете вызвать её с предикатом; в этом случае функция удаляет все элементы, для которых предикат возвращает true . - противоположность removeAll() : удаляет все элементы кроме тех, что находятся в коллекции-аргументе. При использовании с предикатом она оставляет только те элементы, которые ему соответствуют. - удаляет все элементы из списка, оставляя его пустым.
Еще один способ для удаления элементов из коллекции - оператор minusAssign ( -= ) - это in-place версия оператора minus . Второй аргумент может быть либо одним элементом, либо другой коллекцией. Если второй аргумент - это элемент, то оператор -= удалит первое вхождение этого элемента. Если же второй аргумент - это коллекция, то будут удалены все вхождения её элементов. Например, если список содержит повторяющиеся элементы, то они все будут удалены. Второй операнд может содержать элементы, которых нет в коллекции. Такие элементы не влияют на выполнение операции.
Обновление элементов
Списки и ассоциативные списки также предоставляют операции для обновления элементов. Они описаны в разделах List: специфичные операции и Map: специфичные операции. Для Set обновление элементов не имеет смысла, поскольку фактически он удаляет элемент и добавляет другой.
Читайте также: