Si vous savez comment le faire en Java, vous pouvez utiliser la même chose dans Scala. Votre question concerne spécifiquement la bibliothèque standard Scala?
Wheaties
1
@wheaties oui meilleure façon de faire cela à scala
Le projet cadre Scala IO se compose de quelques sous-projets pour différents aspects et extensions de l'IO.
Il existe deux composants principaux de Scala IO:
Core - Core traite principalement de la lecture et de l'écriture de données depuis et vers des sources et des récepteurs arbitraires. Les traits de pierre angulaire sont Input, Outputet Seekablequi fournissent l'API de base.
D'autres classes d'importance sont Resource, ReadCharsetWriteChars .
File - File est une API File(appelée Path) basée sur une combinaison du système de fichiers Java 7 NIO et des API SBT PathFinder. Pathet FileSystemsont les principaux points d'entrée dans l'API Scala IO File.
import scalax.io._
val output:Output=Resource.fromFile("someFile")// Note: each write will open a new connection to file and // each write is executed at the begining of the file,// so in this case the last write will be the contents of the file.// See Seekable for append and patching files// Also See openOutput for performing several writes with a single connection
output.writeIntsAsBytes(1,2,3)
output.write("hello")(Codec.UTF8)
output.writeStrings(List("hello","world")," ")(Codec.UTF8)
Réponse originale (janvier 2011), avec l'ancien endroit pour scala-io:
{// several examples of writing dataimport scalax.io.{FileOps,Path,Codec,OpenOption}// the codec must be defined either as a parameter of ops methods or as an implicitimplicitval codec = scalax.io.Codec.UTF8
val file:FileOps=Path("file")// write bytes// By default the file write will replace// an existing file with the new data
file.write (Array(1,2,3) map ( _.toByte))// another option for write is openOptions which allows the caller// to specify in detail how the write should take place// the openOptions parameter takes a collections of OpenOptions objects// which are filesystem specific in general but the standard options// are defined in the OpenOption object// in addition to the definition common collections are also defined// WriteAppend for example is a List(Create, Append, Write)
file.write (List(1,2,3) map (_.toByte))// write a string to the file
file.write("Hello my dear file")// with all options (these are the default options explicitely declared)
file.write("Hello my dear file")(codec =Codec.UTF8)// Convert several strings to the file// same options apply as for write
file.writeStrings("It costs"::"one"::"dollar"::Nil)// Now all options
file.writeStrings("It costs"::"one"::"dollar"::Nil,
separator="||\n||")(codec =Codec.UTF8)}
Le projet scalax semble mort (aucun commit depuis juin 2009). Est-ce correct? scalax commit history
Rick-777
@Eduardo: J'ai complété ma réponse avec le nouvel emplacement pour la bibliothèque scala-io (qui a été mis à jour pour Scala2.9: github.com/jesseeichar/scala-io/issues/20 )
VonC
10
Est-ce vraiment la suggestion actuelle pour Scala 2.10? Utiliser Scala IO? Il n'y a encore rien dans le noyau de Scala?
Phil
2
Je n'ai jamais utilisé scalax.io, mais à en juger par ces exemples, il semble que la conception de son API soit assez mauvaise. Le mélange de méthodes pour les caractères et les données binaires dans une seule interface n'a pas de sens et conduira très probablement à des bogues de codage difficiles à trouver. La conception de java.io (Reader / Writer vs InputStream / OutputStream) semble bien meilleure.
jcsahnwaldt Reinstate Monica le
211
C'est l'une des fonctionnalités manquantes de Scala standard que j'ai trouvée si utile que je l'ajoute à ma bibliothèque personnelle. (Vous devriez probablement aussi avoir une bibliothèque personnelle.) Le code va comme ceci:
def printToFile(f: java.io.File)(op: java.io.PrintWriter=>Unit){val p =new java.io.PrintWriter(f)try{ op(p)}finally{ p.close()}}
et il est utilisé comme ceci:
import java.io._
val data =Array("Five","strings","in","a","file!")
printToFile(newFile("example.txt")){ p =>
data.foreach(p.println)}
new java.io.PrintWriter () utilise le codage par défaut de la plate-forme, ce qui signifie probablement que le fichier de résultat n'est pas très portable. Par exemple, si vous souhaitez produire un fichier que vous pourrez ensuite envoyer par courrier électronique, vous devriez probablement utiliser le constructeur PrintWriter qui vous permet de spécifier un encodage.
jcsahnwaldt Reinstate Monica le
@JonaChristopherSahnwaldt - Bien sûr, dans des cas particuliers, vous voudrez peut-être spécifier l'encodage. La valeur par défaut de la plate-forme est la valeur par défaut la plus raisonnable en moyenne. Identique à avec Source(encodage par défaut par défaut). Vous pouvez bien sûr ajouter par exemple un enc: Option[String] = Noneparamètre après fsi vous trouvez cela un besoin commun.
Rex Kerr
6
@RexKerr - Je ne suis pas d'accord. Il faut spécifier l'encodage dans presque tous les cas. La plupart des erreurs d'encodage que je rencontre se produisent parce que les gens ne comprennent pas ou ne pensent pas à l'encodage. Ils utilisent la valeur par défaut et ne la connaissent même pas, car trop d'API leur permettent de s'en tirer. De nos jours, la valeur par défaut la plus judicieuse serait probablement UTF-8. Peut-être que vous ne travaillez qu'avec l'anglais et d'autres langues qui peuvent être écrites en ASCII. Quel chanceux êtes-vous. Je vis en Allemagne et j'ai dû réparer plus de trémas brisés que je ne m'en souviens.
jcsahnwaldt Réintègre Monica le
3
@JonaChristopherSahnwaldt - C'est une raison d'avoir un encodage par défaut raisonnable, de ne pas forcer tout le monde à le spécifier tout le temps. Mais si vous êtes sur un Mac et que vos fichiers écrits par Java sont gobbledygook parce qu'ils ne sont pas encodés Mac OS Roman, je ne suis pas sûr que cela fasse plus de bien que de mal. Je pense que c'est la faute des plates-formes de ne pas se mettre d'accord sur un jeu de caractères. En tant que développeur individuel, taper une chaîne ne résoudra vraiment pas le problème. (Tous les développeurs d'accord sur UTF-8 le feraient, mais cela peut simplement entrer par défaut.)
Rex Kerr
@JonaChristopherSahnwaldt +10 pour réparer tout le tréma cassé. Vous ne pouvez pas utiliser un marteau, peut-être une perforatrice? Ou sont-ils déjà des trous à combler, peut-être que ce type peut aider youtube.com/watch?v=E-eBBzWEpwE Mais sérieusement, l'influence de l'ASCII est si dommageable dans le monde, d'accord qu'il devrait être spécifié, et par défaut comme UTF- 8
Davos
50
Similaire à la réponse de Rex Kerr, mais plus générique. J'utilise d'abord une fonction d'assistance:
/**
* Used for reading/writing to database, files, etc.
* Code From the book "Beginning Scala"
* http://www.amazon.com/Beginning-Scala-David-Pollak/dp/1430219890
*/def using[A <:{def close():Unit}, B](param: A)(f: A => B): B =try{ f(param)}finally{ param.close()}
Ensuite, j'utilise ceci comme:
def writeToFile(fileName:String, data:String)=
using (newFileWriter(fileName)){
fileWriter => fileWriter.write(data)}
et
def appendToFile(fileName:String, textData:String)=
using (newFileWriter(fileName,true)){
fileWriter => using (newPrintWriter(fileWriter)){
printWriter => printWriter.println(textData)}}
Ne vous méprenez pas, j'aime votre code et il est très éducatif, mais plus je vois de telles constructions pour des problèmes simples, plus cela me rappelle une vieille blague "bonjour le monde": ariel.com.au/jokes/The_Evolution_of_a_Programmer .html :-) (+1 vote de ma part).
greenoldman
4
Si vous écrivez des one-liners, rien du tout n'a d'importance. Si vous écrivez des programmes importants (volumineux avec un besoin continu de maintenance et d'évolution), ce type de réflexion conduit au type de dégradation de la qualité du logiciel le plus rapide et le plus pernicieux.
Randall Schulz
3
Tout le monde n'aura pas des «yeux scala» avant un certain niveau de pratique - il est amusant de voir que cet exemple de code provient de «Beginning» Scala
asyncwait
asyncwait "commencement" scala ... le titre le plus ironique jamais, note: j'ai le livre ... et je commence à peine à le comprendre..Je suppose que j'étais un pas avant "débutant" lol: D ........
user1050817
1
Le problème est moins les trucs de Scala ici, mais la verbosité et le style médiocre. J'ai édité ceci de manière beaucoup plus lisible. Après mon refactor, il n'y a que 4 lignes (enfin, 4 avec des longueurs de ligne IDE, 6 utilisées ici pour tenir dans l'écran). IMHO, c'est maintenant une très belle réponse.
@samthebest pourriez-vous ajouter les bibliothèques dont vous disposez import?
Daniel
1
À partir de java 7, utilisez plutôt java.nio.file: def writeToFile (file: String, stringToWrite: String): Unit = {val writer = Files.newBufferedWriter (Paths.get (file)) essayez writer.write (stringToWrite) enfin writer.close ()}
E Shindler
20
Donner une autre réponse, car mes modifications des autres réponses ont été rejetées.
C'est la réponse la plus concise et la plus simple (similaire à celle de Garret Hall)
File("filename").writeAll("hello world")
Ceci est similaire à Jus12, mais sans la verbosité et avec un style de code correct
def using[A <:{def close():Unit}, B](resource: A)(f: A => B): B =try f(resource)finally resource.close()def writeToFile(path:String, data:String):Unit=
using(newFileWriter(path))(_.write(data))def appendToFile(path:String, data:String):Unit=
using(newPrintWriter(newFileWriter(path,true)))(_.println(data))
Notez que vous n'avez PAS besoin d'accolades pour try finally, ni de lambdas, et notez l'utilisation de la syntaxe d'espace réservé. Notez également une meilleure dénomination.
Désolé, mais votre code est imaginable, il ne remplit pas le implementedprérequis. Vous ne pouvez pas utiliser le code qui n'est pas implémenté. Je veux dire que vous devez dire comment le trouver car il n'est pas disponible par défaut et n'est pas bien connu.
Val
15
Voici un concis one-liner utilisant la bibliothèque du compilateur Scala:
@ChetanBhasin Probablement parce writequ'il copiera contentsdans un nouveau tableau d'octets au lieu de le diffuser dans le fichier, ce qui à son apogée utilise deux fois plus de mémoire que contentsseul.
Daniel Werner
10
Malheureusement pour la meilleure réponse, Scala-IO est mort. Si cela ne vous dérange pas d'utiliser une dépendance tierce, envisagez d'utiliser ma bibliothèque OS-Lib . Cela rend le travail avec les fichiers, les chemins et le système de fichiers très facile:
// Make sure working directory exists and is emptyval wd = os.pwd/"out"/"splash"
os.remove.all(wd)
os.makeDir.all(wd)// Read/write files
os.write(wd/"file.txt","hello")
os.read(wd/"file.txt")==>"hello"// Perform filesystem operations
os.copy(wd/"file.txt", wd/"copied.txt")
os.list(wd)==>Seq(wd/"copied.txt", wd/"file.txt")
Ici aussi - Cette question est l'un des meilleurs résultats lorsque vous recherchez sur Google comment écrire un fichier avec scala - maintenant que votre projet s'est agrandi, vous voudrez peut-être élargir un peu votre réponse?
asac
6
Au départ Scala 2.13, la bibliothèque standard fournit un utilitaire de gestion des ressources dédié:Using .
Il peut être utilisé dans ce cas avec des ressources telles que PrintWriterou BufferedWriterqui s'étend AutoCloseablepour écrire dans un fichier et, quoi qu'il en soit, fermer la ressource par la suite:
À partir de Scala 2.13, préférez utiliser scala.util.
Correction d'un bug où finallyavalerait l'original Exceptionjeté par trysi le finallycode jetait unException
Après avoir examiné toutes ces réponses sur la façon d'écrire facilement un fichier dans Scala, et certaines d'entre elles sont assez sympas, j'ai eu trois problèmes:
Dans la réponse de Jus12 , l'utilisation du curry pour la méthode d'aide à l'utilisation n'est pas évidente pour les débutants Scala / FP
Doit encapsuler les erreurs de niveau inférieur avec scala.util.Try
Doit montrer aux développeurs Java novices dans Scala / FP comment imbriquer correctement les ressources dépendantes afin que la closeméthode soit exécutée sur chaque ressource dépendante dans l'ordre inverse - Remarque: la fermeture des ressources dépendantes dans l'ordre inverse SURTOUT EN CAS D'ÉCHEC est une exigence rarement comprise de la java.lang.AutoCloseablespécification qui a tendance à conduire à des bogues très pernicieux et difficiles à trouver et à des échecs d'exécution
Avant de commencer, mon objectif n'est pas la concision. C'est pour faciliter la compréhension pour les débutants Scala / FP, généralement ceux venant de Java. À la toute fin, je vais rassembler tous les éléments, puis augmenter la concision.
Tout d'abord, la usingméthode doit être mise à jour pour être utilisée Try(encore une fois, la concision n'est pas le but ici). Il sera renommé en tryUsingAutoCloseable:
def tryUsingAutoCloseable[A <:AutoCloseable, R](instantiateAutoCloseable:()=> A)//parameter list 1(transfer: A => scala.util.Try[R])//parameter list 2: scala.util.Try[R]=Try(instantiateAutoCloseable()).flatMap(
autoCloseable =>{var optionExceptionTry:Option[Exception]=Nonetry
transfer(autoCloseable)catch{case exceptionTry:Exception=>
optionExceptionTry =Some(exceptionTry)throw exceptionTry
}finallytry
autoCloseable.close()catch{case exceptionFinally:Exception=>
optionExceptionTry match{caseSome(exceptionTry)=>
exceptionTry.addSuppressed(exceptionFinally)caseNone=>throw exceptionFinally
}}})
Le début de la tryUsingAutoCloseableméthode ci-dessus peut prêter à confusion car elle semble avoir deux listes de paramètres au lieu de la liste de paramètres unique habituelle. C'est ce qu'on appelle le curry. Et je n'entrerai pas dans les détails du fonctionnement du curry ou de son emplacement occasionnel utile. Il s'avère que pour cet espace de problème particulier, c'est le bon outil pour le travail.
Ensuite, nous devons créer une méthode, tryPrintToFilequi créera un (ou écrasera un existant) Fileet écrira un fichier List[String]. Il utilise un FileWriterqui est encapsulé par un BufferedWriterqui est à son tour encapsulé par un PrintWriter. Et pour améliorer les performances, une taille de tampon par défaut beaucoup plus grande que la valeur par défaut pour BufferedWriterest définie,defaultBufferSize et affectée à la valeur 65536.
Voici le code (et encore une fois, la concision n'est pas le but ici):
val defaultBufferSize:Int=65536def tryPrintToFile(
lines:List[String],
location: java.io.File,
bufferSize:Int= defaultBufferSize
): scala.util.Try[Unit]={
tryUsingAutoCloseable(()=>new java.io.FileWriter(location)){//this open brace is the start of the second curried parameter to the tryUsingAutoCloseable method
fileWriter =>
tryUsingAutoCloseable(()=>new java.io.BufferedWriter(fileWriter, bufferSize)){//this open brace is the start of the second curried parameter to the tryUsingAutoCloseable method
bufferedWriter =>
tryUsingAutoCloseable(()=>new java.io.PrintWriter(bufferedWriter)){//this open brace is the start of the second curried parameter to the tryUsingAutoCloseable method
printWriter =>
scala.util.Try(
lines.foreach(line => printWriter.println(line)))}}}}
La tryPrintToFileméthode ci-dessus est utile en ce qu'elle prend un List[String]comme entrée et l'envoie à un File. Créons maintenant une tryWriteToFileméthode qui prend a Stringet l'écrit dans un File.
Voici le code (et je vous laisse deviner ici la priorité de la concision):
def tryWriteToFile(
content:String,
location: java.io.File,
bufferSize:Int= defaultBufferSize
): scala.util.Try[Unit]={
tryUsingAutoCloseable(()=>new java.io.FileWriter(location)){//this open brace is the start of the second curried parameter to the tryUsingAutoCloseable method
fileWriter =>
tryUsingAutoCloseable(()=>new java.io.BufferedWriter(fileWriter, bufferSize)){//this open brace is the start of the second curried parameter to the tryUsingAutoCloseable method
bufferedWriter =>Try(bufferedWriter.write(content))}}}
Enfin, il est utile de pouvoir récupérer le contenu d'un fichier en Filetant que fichier String. Bien qu'elle scala.io.Sourcefournisse une méthode pratique pour obtenir facilement le contenu de a File, la closeméthode doit être utilisée sur le Sourcepour libérer les descripteurs de la JVM et du système de fichiers sous-jacents. Si cela n'est pas fait, la ressource n'est pas libérée tant que le JVM GC (Garbage Collector) ne parvient pas à libérer l' Sourceinstance elle-même. Et même dans ce cas, il n'y a qu'une faible garantie JVM que la finalizeméthode sera appelée par le GC à closela ressource. Cela signifie qu'il est de la responsabilité du client d'appeler explicitement la closeméthode, tout comme il est de la responsabilité d'un client de calculer closeune instance dejava.lang.AutoCloseable. Pour cela, nous avons besoin d'une deuxième définition de la méthode using qui gère scala.io.Source.
Et voici un exemple d'utilisation de celui-ci dans un lecteur de fichiers en ligne super simple (actuellement utilisé pour lire des fichiers délimités par des tabulations à partir de la sortie de la base de données):
def tryProcessSource(
file: java.io.File, parseLine:(String,Int)=>List[String]=(line, index)=>List(line), filterLine:(List[String],Int)=>Boolean=(values, index)=>true, retainValues:(List[String],Int)=>List[String]=(values, index)=> values
, isFirstLineNotHeader:Boolean=false): scala.util.Try[List[List[String]]]=
tryUsingSource(scala.io.Source.fromFile(file)){
source =>
scala.util.Try((for{(line, index)<-
source.getLines().buffered.zipWithIndex
values =
parseLine(line, index)if(index ==0&&!isFirstLineNotHeader)|| filterLine(values, index)
retainedValues =
retainValues(values, index)}yield retainedValues
).toList //must explicitly use toList due to the source.close which will//occur immediately following execution of this anonymous function))
Maintenant, en réunissant tout cela avec les importations extraites (ce qui facilite beaucoup le collage dans la feuille de travail Scala présente dans les plugins Eclipse ScalaIDE et IntelliJ Scala pour faciliter le vidage de la sortie sur le bureau pour être plus facilement examinée avec un éditeur de texte), voici à quoi ressemble le code (avec une concision accrue):
En tant que débutant Scala / FP, j'ai brûlé de nombreuses heures (surtout dans une frustration éraflée) pour gagner les connaissances et les solutions ci-dessus. J'espère que cela aidera les autres débutants Scala / FP à surmonter plus rapidement cette bosse d'apprentissage particulière.
Incroyable mise à jour. Le seul problème est que maintenant vous avez environ 100 lignes de code qui pourraient être remplacées par try-catch-finally. Aimez toujours votre passion.
Observer le
1
@Observer Je dirais que c'est une déclaration inexacte. Le modèle que je décris réduit en fait la quantité de passe-partout qu'un client doit écrire pour assurer une gestion correcte de la fermeture des AutoCloseables tout en activant le modèle FP idiomatique Scala d'utilisation de scala.util.Try. Si vous essayez d'obtenir les mêmes effets que moi en écrivant manuellement les blocs try / catch / finally, je pense que vous vous retrouverez avec un peu plus de passe-partout que vous ne l'imaginez. Ainsi, il y a une valeur de lisibilité significative en poussant tout le passe-partout dans les 100 lignes de la fonction Scala.
chaotic3quilibrium
1
Désolé si cela semblait offensant de quelque manière que ce soit. Pourtant, mon point est qu'il n'y a pas besoin d'une telle quantité de code, car la même chose pourrait être obtenue grâce à une approche non fonctionnelle avec beaucoup plus de simplicité. Personnellement, j'écrirais try-finally avec quelques vérifications supplémentaires. C'est juste plus court. Si je voulais utiliser des wrappers, ApacheUtils est là pour utiliser tout le sale boulot. De plus, tous les lecteurs / enregistreurs standard ferment les flux sous-jacents, de sorte que votre multipwrap n'est pas nécessaire. PS: J'ai changé mon vote de moins un à plus un pour soutenir vos efforts. Alors, s'il vous plaît, ne me soupçonnez pas de mauvaises intentions.
Observer le
Aucune offense prise.
chaotic3quilibrium
1
Je comprends votre point de vue. Merci pour la discussion, je dois y réfléchir un peu. Bonne journée!
Observer le
3
Voici un exemple d'écriture de quelques lignes dans un fichier à l'aide de scalaz-stream .
import scalaz._
import scalaz.stream._
def writeLinesToFile(lines:Seq[String], file:String):Task[Unit]=Process(lines: _*)// Process that enumerates the lines.flatMap(Process(_,"\n"))// Add a newline after each line.pipe(text.utf8Encode)// Encode as UTF-8.to(io.fileChunkW(fileName))// Buffered write to the file.runLog[Task,Unit]// Get this computation as a Task.map(_ =>())// Discard the result
writeLinesToFile(Seq("one","two"),"file.txt").run
def write(destinationFile:Path, fileContent:String):Either[Exception,Path]=
write(destinationFile, fileContent.getBytes(StandardCharsets.UTF_8))def write(destinationFile:Path, fileContent:Array[Byte]):Either[Exception,Path]=try{Files.createDirectories(destinationFile.getParent)// Return the path to the destinationFile if the write is successfulRight(Files.write(destinationFile, fileContent))}catch{case exception:Exception=>Left(exception)}
Usage
val filePath =Paths.get("./testDir/file.txt")
write(filePath ,"A test")match{caseRight(pathToWrittenFile)=> println(s"Successfully wrote to $pathToWrittenFile")caseLeft(exception)=> println(s"Could not write to $filePath. Exception: $exception")}
Résumé - Java NIO (ou NIO.2 pour async) est toujours la solution de traitement de fichiers la plus complète prise en charge par Scala. Le code suivant crée et écrit du texte dans un nouveau fichier:
import java.io.{BufferedOutputStream,OutputStream}import java.nio.file.{Files,Paths}val testFile1 =Paths.get("yourNewFile.txt")val s1 ="text to insert in file".getBytes()val out1:OutputStream=newBufferedOutputStream(Files.newOutputStream(testFile1))try{
out1.write(s1,0, s1.length)}catch{case _ => println("Exception thrown during file writing")}finally{
out1.close()}
Importer des bibliothèques Java: IO et NIO
Créez un Pathobjet avec le nom de fichier choisi
Convertissez votre texte que vous souhaitez insérer dans un fichier en un tableau d'octets
Obtenez votre fichier sous forme de flux: OutputStream
Passez votre tableau d'octets dans la writefonction de votre flux de sortie
Réponses:
Edit 2019 (8 ans plus tard), Scala-IO n'étant pas très actif, le cas échéant, Li Haoyi propose sa propre bibliothèque
lihaoyi/os-lib
, qu'il présente ci-dessous .Juin 2019, Xavier Guihot évoque dans sa réponse la bibliothèque
Using
, un utilitaire de gestion automatique des ressources.Edit (septembre 2011): depuis qu'Eduardo Costa pose des questions sur Scala2.9, et depuis que Rick-777 commente que l' historique des commit scalax.IO est quasiment inexistant depuis mi-2009 ...
Scala-IO a changé de place: voir son repo GitHub , de Jesse Eichar (également sur SO ):
Réponse originale (janvier 2011), avec l'ancien endroit pour scala-io:
Si vous ne voulez pas attendre Scala2.9, vous pouvez utiliser la bibliothèque scala-incubator / scala-io .
(comme mentionné dans « Pourquoi Scala Source ne ferme-t-il pas le InputStream sous-jacent? ")
Voir les échantillons
la source
C'est l'une des fonctionnalités manquantes de Scala standard que j'ai trouvée si utile que je l'ajoute à ma bibliothèque personnelle. (Vous devriez probablement aussi avoir une bibliothèque personnelle.) Le code va comme ceci:
et il est utilisé comme ceci:
la source
Source
(encodage par défaut par défaut). Vous pouvez bien sûr ajouter par exemple unenc: Option[String] = None
paramètre aprèsf
si vous trouvez cela un besoin commun.Similaire à la réponse de Rex Kerr, mais plus générique. J'utilise d'abord une fonction d'assistance:
Ensuite, j'utilise ceci comme:
et
etc.
la source
Une réponse simple:
la source
import
?Donner une autre réponse, car mes modifications des autres réponses ont été rejetées.
C'est la réponse la plus concise et la plus simple (similaire à celle de Garret Hall)
Ceci est similaire à Jus12, mais sans la verbosité et avec un style de code correct
Notez que vous n'avez PAS besoin d'accolades pour
try finally
, ni de lambdas, et notez l'utilisation de la syntaxe d'espace réservé. Notez également une meilleure dénomination.la source
implemented
prérequis. Vous ne pouvez pas utiliser le code qui n'est pas implémenté. Je veux dire que vous devez dire comment le trouver car il n'est pas disponible par défaut et n'est pas bien connu.Voici un concis one-liner utilisant la bibliothèque du compilateur Scala:
Alternativement, si vous souhaitez utiliser les bibliothèques Java, vous pouvez faire ce hack:
la source
scala.tools.nsc.io.File("/tmp/myFile.txt")
fonctionne dans Scala 2.11.8.Un liners pour enregistrer / lire vers / depuis
String
, en utilisantjava.nio
.Cela ne convient pas aux fichiers volumineux, mais fera l'affaire.
Quelques liens:
java.nio.file.Files.write
java.lang.String.getBytes
scala.collection.JavaConverters
scala.collection.immutable.List.mkString
la source
write
qu'il copieracontents
dans un nouveau tableau d'octets au lieu de le diffuser dans le fichier, ce qui à son apogée utilise deux fois plus de mémoire quecontents
seul.Malheureusement pour la meilleure réponse, Scala-IO est mort. Si cela ne vous dérange pas d'utiliser une dépendance tierce, envisagez d'utiliser ma bibliothèque OS-Lib . Cela rend le travail avec les fichiers, les chemins et le système de fichiers très facile:
Il a des lignes uniques pour écrire dans des fichiers , ajouter des fichiers , écraser des fichiers et de nombreuses autres opérations utiles / courantes
la source
Une micro bibliothèque que j'ai écrite: https://github.com/pathikrit/better-files
ou
la source
Au départ
Scala 2.13
, la bibliothèque standard fournit un utilitaire de gestion des ressources dédié:Using
.Il peut être utilisé dans ce cas avec des ressources telles que
PrintWriter
ouBufferedWriter
qui s'étendAutoCloseable
pour écrire dans un fichier et, quoi qu'il en soit, fermer la ressource par la suite:Par exemple, avec
java.io
api:Ou avec
java.nio
api:la source
MISE À JOUR le 2019 / Sep / 01:
finally
avalerait l'originalException
jeté partry
si lefinally
code jetait unException
Après avoir examiné toutes ces réponses sur la façon d'écrire facilement un fichier dans Scala, et certaines d'entre elles sont assez sympas, j'ai eu trois problèmes:
scala.util.Try
close
méthode soit exécutée sur chaque ressource dépendante dans l'ordre inverse - Remarque: la fermeture des ressources dépendantes dans l'ordre inverse SURTOUT EN CAS D'ÉCHEC est une exigence rarement comprise de lajava.lang.AutoCloseable
spécification qui a tendance à conduire à des bogues très pernicieux et difficiles à trouver et à des échecs d'exécutionAvant de commencer, mon objectif n'est pas la concision. C'est pour faciliter la compréhension pour les débutants Scala / FP, généralement ceux venant de Java. À la toute fin, je vais rassembler tous les éléments, puis augmenter la concision.
Tout d'abord, la
using
méthode doit être mise à jour pour être utiliséeTry
(encore une fois, la concision n'est pas le but ici). Il sera renommé entryUsingAutoCloseable
:Le début de la
tryUsingAutoCloseable
méthode ci-dessus peut prêter à confusion car elle semble avoir deux listes de paramètres au lieu de la liste de paramètres unique habituelle. C'est ce qu'on appelle le curry. Et je n'entrerai pas dans les détails du fonctionnement du curry ou de son emplacement occasionnel utile. Il s'avère que pour cet espace de problème particulier, c'est le bon outil pour le travail.Ensuite, nous devons créer une méthode,
tryPrintToFile
qui créera un (ou écrasera un existant)File
et écrira un fichierList[String]
. Il utilise unFileWriter
qui est encapsulé par unBufferedWriter
qui est à son tour encapsulé par unPrintWriter
. Et pour améliorer les performances, une taille de tampon par défaut beaucoup plus grande que la valeur par défaut pourBufferedWriter
est définie,defaultBufferSize
et affectée à la valeur 65536.Voici le code (et encore une fois, la concision n'est pas le but ici):
La
tryPrintToFile
méthode ci-dessus est utile en ce qu'elle prend unList[String]
comme entrée et l'envoie à unFile
. Créons maintenant unetryWriteToFile
méthode qui prend aString
et l'écrit dans unFile
.Voici le code (et je vous laisse deviner ici la priorité de la concision):
Enfin, il est utile de pouvoir récupérer le contenu d'un fichier en
File
tant que fichierString
. Bien qu'ellescala.io.Source
fournisse une méthode pratique pour obtenir facilement le contenu de aFile
, laclose
méthode doit être utilisée sur leSource
pour libérer les descripteurs de la JVM et du système de fichiers sous-jacents. Si cela n'est pas fait, la ressource n'est pas libérée tant que le JVM GC (Garbage Collector) ne parvient pas à libérer l'Source
instance elle-même. Et même dans ce cas, il n'y a qu'une faible garantie JVM que lafinalize
méthode sera appelée par le GC àclose
la ressource. Cela signifie qu'il est de la responsabilité du client d'appeler explicitement laclose
méthode, tout comme il est de la responsabilité d'un client de calculerclose
une instance dejava.lang.AutoCloseable
. Pour cela, nous avons besoin d'une deuxième définition de la méthode using qui gèrescala.io.Source
.Voici le code pour cela (toujours pas concis):
Et voici un exemple d'utilisation de celui-ci dans un lecteur de fichiers en ligne super simple (actuellement utilisé pour lire des fichiers délimités par des tabulations à partir de la sortie de la base de données):
Une version mise à jour de la fonction ci-dessus a été fournie comme réponse à une question StackOverflow différente mais liée .
Maintenant, en réunissant tout cela avec les importations extraites (ce qui facilite beaucoup le collage dans la feuille de travail Scala présente dans les plugins Eclipse ScalaIDE et IntelliJ Scala pour faciliter le vidage de la sortie sur le bureau pour être plus facilement examinée avec un éditeur de texte), voici à quoi ressemble le code (avec une concision accrue):
En tant que débutant Scala / FP, j'ai brûlé de nombreuses heures (surtout dans une frustration éraflée) pour gagner les connaissances et les solutions ci-dessus. J'espère que cela aidera les autres débutants Scala / FP à surmonter plus rapidement cette bosse d'apprentissage particulière.
la source
try-catch-finally
. Aimez toujours votre passion.Voici un exemple d'écriture de quelques lignes dans un fichier à l'aide de scalaz-stream .
la source
Pour surpasser samthebest et les contributeurs avant lui, j'ai amélioré la dénomination et la concision:
la source
Pas de dépendances, avec gestion des erreurs
Either
pour la gestion des erreursCode
Usage
la source
Mise à jour 2019:
Résumé - Java NIO (ou NIO.2 pour async) est toujours la solution de traitement de fichiers la plus complète prise en charge par Scala. Le code suivant crée et écrit du texte dans un nouveau fichier:
Path
objet avec le nom de fichier choisiOutputStream
write
fonction de votre flux de sortiela source
Semblable à cette réponse , voici un exemple avec
fs2
(version 1.0.4):la source
Cette ligne permet d'écrire un fichier à partir d'un tableau ou d'une chaîne.
la source
Si vous avez de toute façon Akka Streams dans votre projet, il fournit une ligne unique:
Documentation Akka> E / S de fichiers en streaming
la source