O que é uma maneira simples e canônica de ler um arquivo inteiro na memória no Scala? (Idealmente, com controle sobre a codificação de caracteres.)
O melhor que posso apresentar é:
scala.io.Source.fromPath("file.txt").getLines.reduceLeft(_+_)
ou devo usar um dos idiomas terríveis de Java , o melhor dos quais (sem usar uma biblioteca externa) parece ser:
import java.util.Scanner
import java.io.File
new Scanner(new File("file.txt")).useDelimiter("\\Z").next()
Ao ler as discussões da lista de discussão, não está claro para mim que o scala.io.Source deve ser a biblioteca de E / S canônica. Não entendo exatamente qual é o seu objetivo.
... Gostaria de algo absolutamente simples e fácil de lembrar. Por exemplo, nessas línguas é muito difícil esquecer o idioma ...
Ruby open("file.txt").read
Ruby File.read("file.txt")
Python open("file.txt").read()
Respostas:
A propósito, "
scala.
" não é realmente necessário, pois está sempre no escopo, e você pode, é claro, importar o conteúdo do io, total ou parcialmente, e evitar ter que acrescentar o "io". também.O item acima deixa o arquivo aberto, no entanto. Para evitar problemas, feche-o assim:
Outro problema com o código acima é que ele é horrivelmente lento devido à sua natureza de implementação. Para arquivos maiores, deve-se usar:
fonte
Apenas para expandir a solução de Daniel, você pode reduzir enormemente as coisas inserindo a seguinte importação em qualquer arquivo que exija manipulação de arquivos:
Com isso, agora você pode fazer:
Eu seria cauteloso ao ler um arquivo inteiro em um único
String
. É um hábito muito ruim, que o morderá mais cedo e mais difícil do que você pensa. OgetLines
método retorna um valor do tipoIterator[String]
. É efetivamente um cursor lento no arquivo, permitindo que você examine apenas os dados necessários sem arriscar o excesso de memória.Ah, e para responder à sua pergunta implícita sobre
Source
: sim, é a biblioteca de E / S canônica. A maioria dos códigos acaba sendo usadajava.io
devido à sua interface de nível inferior e melhor compatibilidade com as estruturas existentes, mas qualquer código que tenha uma opção deve ser usadoSource
, principalmente para manipulação simples de arquivos.fonte
fonte
(EDIT: Isso não funciona no scala 2.9 e talvez também não 2.8)
Use tronco:
fonte
slurp
"? Nós realmente abandonamos o nome óbvio e intuitivo? O problemaslurp
é que isso pode fazer sentido para alguém com o inglês como primeira língua, pelo menos, mas você nunca pensaria nisso antes!File
não está mais no 2.8.0, não está?slurp
é fantástico! :) Foi fantástico? Eu não acho. ; (Controle sobre a codificação de caracteres e nenhum recurso para limpeza. Além disso, possivelmente otimizado (por exemplo,
Files.readAllBytes
alocando uma matriz de bytes apropriada ao tamanho do arquivo).fonte
Foi-me dito que o Source.fromFile é problemático. Pessoalmente, tive problemas ao abrir arquivos grandes com o Source.fromFile e tive que recorrer ao Java InputStreams.
Outra solução interessante é usar scalax. Aqui está um exemplo de código bem comentado que abre um arquivo de log usando o ManagedResource para abrir um arquivo com auxiliares scalax: http://pastie.org/pastes/420714
fonte
O uso de getLines () em scala.io.Source descarta quais caracteres foram usados para terminadores de linha (\ n, \ r, \ r \ n etc.)
O seguinte deve preservá-lo caractere por caractere e não faz concatenação excessiva de cadeias (problemas de desempenho):
fonte
Mais um: https://github.com/pathikrit/better-files#streams-and-codecs
Várias maneiras de extrair um arquivo sem carregar o conteúdo na memória:
Você também pode fornecer seu próprio codec para qualquer coisa que faça uma leitura / gravação (assume o padrão scala.io.Codec.de se você não fornecer um):
fonte
Assim como em Java, usando a biblioteca CommonsIO:
Além disso, muitas respostas aqui esquecem o Charset. É melhor sempre fornecê-lo explicitamente, ou será atingido um dia.
fonte
Para emular a sintaxe Ruby (e transmitir a semântica) de abrir e ler um arquivo, considere esta classe implícita (Scala 2.10 e superior),
Nesse caminho,
fonte
como algumas pessoas mencionaram scala.io.Source, é melhor evitar isso devido a vazamentos de conexão.
Provavelmente scalax e libs java puras como commons-io são as melhores opções até que o novo projeto da incubadora (ou seja, scala-io) seja mesclado.
fonte
você também pode usar o Path do scala io para ler e processar arquivos.
Agora você pode obter o caminho do arquivo usando este: -
Você também pode incluir terminadores, mas por padrão está definido como falso.
fonte
Para uma leitura / upload geral mais rápida de um arquivo (grande), considere aumentar o tamanho de
bufferSize
(Source.DefaultBufSize
definido como2048
), por exemplo, da seguinte maneira:Nota Source.scala . Para uma discussão mais aprofundada, consulte o arquivo de texto rápido Scala lido e carregado na memória .
fonte
Você não precisa analisar todas as linhas e concatená-las novamente ...
Eu prefiro usar isso:
fonte
val content = source.mkString
Codec
. O teste falhousbt test
porque não é possível defini-lo, enquanto o comando de teste do Intellij passa em todos os testes. E você pode usardef using
a partir desteSe você não se importa com uma dependência de terceiros, considere usar minha biblioteca OS-Lib . Isso torna a leitura / gravação de arquivos e o trabalho com o sistema de arquivos muito conveniente:
com auxiliares de uma linha para ler bytes , ler blocos , ler linhas e muitas outras operações úteis / comuns
fonte
A pergunta óbvia é "por que você deseja ler o arquivo inteiro?" Obviamente, essa não é uma solução escalável se os arquivos forem muito grandes. O
scala.io.Source
devolve umIterator[String]
dogetLines
método, que é muito útil e concisa.Não é tarefa fácil criar uma conversão implícita usando os utilitários Java IO subjacentes para converter a
File
, aReader
ou aInputStream
para aString
. Eu acho que a falta de escalabilidade significa que eles estão corretos para não adicionar isso à API padrão.fonte
imprima todas as linhas, como usar o Java BufferedReader, leia todas as linhas e imprima:
equivalente:
fonte
nos argumentos você pode dar o caminho do arquivo e ele retornará todas as linhas
fonte