Какой простой и канонический способ чтения всего файла в память в Scala? (В идеале, с контролем над кодировкой символов.)
Лучшее, что я могу придумать, это:
scala.io.Source.fromPath("file.txt").getLines.reduceLeft(_+_)
или я должен использовать один из ужасных идиом Java , лучший из которых (без использования внешней библиотеки):
import java.util.Scanner
import java.io.File
new Scanner(new File("file.txt")).useDelimiter("\\Z").next()
Из чтения обсуждений в списке рассылки мне не ясно, что scala.io.Source даже предполагается, что это каноническая библиотека ввода / вывода. Я не понимаю, какова его цель, точно.
... Я хотел бы что-то чертовски простое и легко запоминающееся. Например, в этих языках очень трудно забыть идиому ...
Ruby open("file.txt").read
Ruby File.read("file.txt")
Python open("file.txt").read()
Ответы:
Кстати, "
scala.
» на самом деле не является необходимым, так как в любом случае он всегда находится в области видимости, и вы, конечно, можете импортировать содержимое io полностью или частично, и избежать необходимости добавлять «io». слишком.Однако вышеизложенное оставляет файл открытым. Чтобы избежать проблем, вы должны закрыть его так:
Другая проблема с приведенным выше кодом заключается в том, что он ужасно медленный из-за характера его реализации. Для больших файлов следует использовать:
источник
Просто чтобы расширить решение Daniel, вы можете значительно сократить время, вставив следующий импорт в любой файл, который требует манипулирования файлами:
С этим теперь вы можете сделать:
Я бы с осторожностью прочитал весь файл в один
String
. Это очень плохая привычка, которая будет кусать вас раньше и сильнее, чем вы думаете.getLines
Метод возвращает значение типаIterator[String]
. Это фактически ленивый курсор в файл, позволяющий вам просматривать только те данные, которые вам нужны, не рискуя переполнением памяти.Да, и чтобы ответить на ваш подразумеваемый вопрос о
Source
: да, это каноническая библиотека ввода / вывода. Большая часть кода заканчивается использованиемjava.io
из-за его интерфейса более низкого уровня и лучшей совместимости с существующими платформами, но любой код, который имеет выбор, должен использоватьсяSource
, особенно для простой манипуляции с файлами.источник
источник
(РЕДАКТИРОВАТЬ: Это не работает в Scala 2.9 и, возможно, не 2.8)
Используйте ствол:
источник
slurp
"? Действительно ли мы отказались от очевидного, интуитивного названия? Проблема вslurp
том, что это может иметь смысл после того, как кто-то с английским языком по крайней мере, по крайней мере, но вы никогда не подумали бы об этом с самого начала!File
больше не в 2.8.0, не так ли?slurp
Это фантастично! :) Было фантастически? Я не нахожу это. ; (Контроль над кодировкой символов, и нет ресурсов для очистки. Также возможно оптимизация (например,
Files.readAllBytes
выделение байтового массива, соответствующего размеру файла).источник
Files.readString(Path.of("file.txt"), StandardCharsets.UTF_8)
.Мне сказали, что Source.fromFile проблематичен. Лично у меня были проблемы с открытием больших файлов с помощью Source.fromFile, и мне пришлось прибегнуть к Java InputStreams.
Еще одно интересное решение - использование скалакса. Вот пример некоторого хорошо прокомментированного кода, который открывает файл журнала с помощью ManagedResource, чтобы открыть файл с помощью помощников скалякса: http://pastie.org/pastes/420714
источник
Использование getLines () для scala.io.Source отменяет, какие символы использовались для разделителей строк (\ n, \ r, \ r \ n и т. Д.)
Следующее должно сохранять его символ за символом и не выполнять чрезмерную конкатенацию строк (проблемы с производительностью):
источник
Еще один: https://github.com/pathikrit/better-files#streams-and-codecs
Различные способы сохранить файл без загрузки содержимого в память:
Вы также можете предоставить свой собственный кодек для всего, что выполняет чтение / запись (предполагается, что scala.io.Codec.default, если вы его не предоставляете):
источник
Как и в Java, используя библиотеку CommonsIO:
Кроме того, многие ответы здесь забывают Charset. Лучше всегда указывать это явно, иначе это произойдет однажды.
источник
Для эмуляции синтаксиса Ruby (и передачи семантики) открытия и чтения файла рассмотрим этот неявный класс (Scala 2.10 и выше),
В этом случае,
источник
как упоминали несколько человек, scala.io.Source следует избегать из-за утечек соединения.
Вероятно, наилучшим вариантом будут скалярные и чистые Java-библиотеки, такие как commons-io, пока новый проект инкубатора (т.е. scala-io) не будет объединен.
источник
Вы также можете использовать Path из scala io для чтения и обработки файлов.
Теперь вы можете получить путь к файлу, используя это: -
Вы также можете включить терминаторы, но по умолчанию установлено значение false.
источник
Для более быстрого общего чтения / загрузки (большого) файла рассмотрите возможность увеличения размера
bufferSize
(Source.DefaultBufSize
установленного в2048
), например, следующим образом:Примечание Source.scala . Для дальнейшего обсуждения читайте и загружайте в память быстрый текстовый файл Scala .
источник
Вам не нужно анализировать каждую строку, а затем объединять их снова ...
Я предпочитаю использовать это:
источник
val content = source.mkString
Codec
. Я получил неудачный тест,sbt test
потому что не могу его установить, в то время как тестовая команда Intellij прошла все тесты. И вы можете использоватьdef using
от этогоЕсли вы не возражаете против сторонней зависимости, вам следует рассмотреть возможность использования моей библиотеки OS-Lib . Это делает чтение / запись файлов и работу с файловой системой очень удобной:
с однострочными помощниками для чтения байтов , чтения фрагментов , чтения строк и многих других полезных / общих операций
источник
Очевидный вопрос: «Почему вы хотите прочитать весь файл?» Это явно не масштабируемое решение, если ваши файлы становятся очень большими. The
scala.io.Source
возвращает вамIterator[String]
отgetLines
метода, который является очень полезным и кратким.Не так уж сложно придумать неявное преобразование, используя базовые утилиты Java IO для преобразования a
File
, aReader
или aInputStream
в aString
. Я думаю, что отсутствие масштабируемости означает, что они правильно не добавляют это в стандартный API.источник
напечатайте каждую строку, например, используйте Java BufferedReader, прочитайте каждую строку и напечатайте ее:
эквивалент:
источник
в аргументах вы можете указать путь к файлу и он будет возвращать все строки
источник