Quelle est une manière simple et canonique de lire un fichier entier en mémoire dans Scala? (Idéalement, avec contrôle de l'encodage des caractères.)
Le mieux que je puisse trouver est:
scala.io.Source.fromPath("file.txt").getLines.reduceLeft(_+_)
ou suis-je censé utiliser l'un des idiomes les plus horribles de Java , dont le meilleur (sans utiliser de bibliothèque externe) semble être:
import java.util.Scanner
import java.io.File
new Scanner(new File("file.txt")).useDelimiter("\\Z").next()
De la lecture des discussions de la liste de diffusion, il n'est pas clair pour moi que scala.io.Source est même censé être la bibliothèque d'E / S canonique. Je ne comprends pas quel est son objectif, exactement.
... Je voudrais quelque chose de simple et facile à retenir. Par exemple, dans ces langues, il est très difficile d'oublier l'idiome ...
Ruby open("file.txt").read
Ruby File.read("file.txt")
Python open("file.txt").read()
Réponses:
Soit dit en passant, "
scala.
" n'est pas vraiment nécessaire, car il est toujours de toute façon, et vous pouvez, bien sûr, importer le contenu d'io, entièrement ou partiellement, et éviter d'avoir à ajouter "io". aussi.Ce qui précède laisse cependant le fichier ouvert. Pour éviter les problèmes, vous devez le fermer comme ceci:
Un autre problème avec le code ci-dessus est qu'il est horriblement lent en raison de sa nature de mise en œuvre. Pour les fichiers plus volumineux, il faut utiliser:
la source
Juste pour développer la solution de Daniel, vous pouvez considérablement raccourcir les choses en insérant l'importation suivante dans n'importe quel fichier qui nécessite une manipulation de fichier:
Avec cela, vous pouvez maintenant faire:
Je me méfierais de lire un fichier entier en un seul
String
. C'est une très mauvaise habitude, qui vous mordra plus tôt et plus fort que vous ne le pensez. LagetLines
méthode renvoie une valeur de typeIterator[String]
. Il s'agit en fait d'un curseur paresseux dans le fichier, vous permettant d'examiner uniquement les données dont vous avez besoin sans risquer de saturer la mémoire.Oh, et pour répondre à votre question implicite sur
Source
: oui, c'est la bibliothèque d'E / S canonique. La plupart du code finit par être utilisé enjava.io
raison de son interface de bas niveau et de sa meilleure compatibilité avec les frameworks existants, mais tout code qui a le choix devrait être utiliséSource
, en particulier pour une simple manipulation de fichiers.la source
la source
(EDIT: Cela ne fonctionne pas dans scala 2.9 et peut-être pas 2.8 non plus)
Utilisez le coffre:
la source
slurp
"? Avons-nous vraiment abandonné le nom évident et intuitif? Le problèmeslurp
est que cela pourrait avoir du sens après coup, pour quelqu'un avec l'anglais comme première langue, au moins, mais vous n'y penseriez jamais pour commencer!File
n'est plus en 2.8.0, n'est-ce pas?slurp
est fantastique! :) C'était fantastique? Je ne le trouve pas. ; (Contrôle de l'encodage des caractères et aucune ressource à nettoyer. Également, éventuellement optimisé (par exemple en
Files.readAllBytes
allouant un tableau d'octets approprié à la taille du fichier).la source
On m'a dit que Source.fromFile est problématique. Personnellement, j'ai eu des problèmes pour ouvrir de gros fichiers avec Source.fromFile et j'ai dû recourir à Java InputStreams.
Une autre solution intéressante consiste à utiliser scalax. Voici un exemple de code bien commenté qui ouvre un fichier journal à l'aide de ManagedResource pour ouvrir un fichier avec des assistants scalax: http://pastie.org/pastes/420714
la source
L'utilisation de getLines () sur scala.io.Source supprime les caractères utilisés pour les terminateurs de ligne (\ n, \ r, \ r \ n, etc.)
Les éléments suivants doivent le conserver caractère par caractère et ne font pas de concaténation excessive de chaînes (problèmes de performances):
la source
Un de plus: https://github.com/pathikrit/better-files#streams-and-codecs
Différentes façons de récupérer un fichier sans charger le contenu en mémoire:
Vous pouvez également fournir votre propre codec pour tout ce qui fait une lecture / écriture (cela suppose scala.io.Codec.default si vous n'en fournissez pas):
la source
Tout comme en Java, en utilisant la bibliothèque CommonsIO:
De plus, de nombreuses réponses ici oublient Charset. Il est préférable de toujours le fournir explicitement, sinon il arrivera un jour.
la source
Pour émuler la syntaxe Ruby (et transmettre la sémantique) d'ouverture et de lecture d'un fichier, considérez cette classe implicite (Scala 2.10 et supérieure),
De cette façon,
la source
comme quelques personnes l'ont mentionné scala.io.Source est préférable d'éviter en raison de fuites de connexion.
Les bibliothèques scalax et java pur comme commons-io sont probablement les meilleures options jusqu'à ce que le nouveau projet d'incubateur (c'est-à-dire scala-io) soit fusionné.
la source
vous pouvez également utiliser Path from scala io pour lire et traiter les fichiers.
Maintenant, vous pouvez obtenir le chemin du fichier en utilisant ceci: -
Vous pouvez également inclure des terminateurs mais par défaut, il est défini sur false.
la source
Pour une lecture / téléchargement global plus rapide d'un (gros) fichier, envisagez d'augmenter la taille de
bufferSize
(Source.DefaultBufSize
défini sur2048
), par exemple comme suit,Remarque Source.scala . Pour plus de détails, voir le fichier texte rapide Scala lu et téléchargé en mémoire .
la source
Vous n'avez pas besoin d'analyser chaque ligne, puis de les concaténer à nouveau ...
Je préfère utiliser ceci:
la source
val content = source.mkString
Codec
. J'ai obtenu l'échec du testsbt test
car je ne peux pas le définir, tandis que la commande test d'Intellij réussit tous les tests. Et vous pouvez utiliser àdef using
partir de celaSi cela ne vous dérange pas une dépendance tierce, vous devriez envisager d'utiliser ma bibliothèque OS-Lib . Cela rend la lecture / écriture de fichiers et l'utilisation du système de fichiers très pratiques:
avec des aides d'une ligne pour la lecture d'octets , la lecture de morceaux , la lecture de lignes et de nombreuses autres opérations utiles / courantes
la source
La question évidente étant "pourquoi voulez-vous lire tout le fichier?" Ce n'est évidemment pas une solution évolutive si vos fichiers deviennent très volumineux. Le
scala.io.Source
vous donne un retourIterator[String]
de lagetLines
méthode, qui est très utile et concis.Ce n'est pas vraiment un boulot de trouver une conversion implicite en utilisant les utilitaires Java IO sous-jacents pour convertir un
File
, unReader
ou unInputStream
en unString
. Je pense que le manque d'évolutivité signifie qu'ils sont corrects de ne pas ajouter cela à l'API standard.la source
imprimez chaque ligne, comme utilisez Java BufferedReader pour lire chaque ligne, et imprimez-la:
équivalent:
la source
dans les arguments, vous pouvez donner le chemin du fichier et il retournera toutes les lignes
la source