Scalaでファイルを読み取るには、
Source.fromFile("file.txt").mkString
文字列をファイルに書き込むための同等の簡潔な方法はありますか?
ほとんどの言語はそのようなものをサポートしています。私のお気に入りはGroovyです:
def f = new File("file.txt")
// Read
def s = f.text
// Write
f.text = "file contents"
コードを1行から短いページの範囲のプログラムに使用したいと思います。ここでは、独自のライブラリを使用する必要はありません。現代の言語では、ファイルに何かを便利に書き込むことができると期待しています。
これに似た投稿がありますが、私の正確な質問に答えていないか、古いScalaバージョンに焦点を合わせています。
例えば:
簡潔な1行:
import Java.io.PrintWriter
new PrintWriter("filename") { write("file contents"); close }
誰もNIO.2操作を提案しなかったことは奇妙です(Java 7以降で利用可能):
import Java.nio.file.{Paths, Files}
import Java.nio.charset.StandardCharsets
Files.write(Paths.get("file.txt"), "file contents".getBytes(StandardCharsets.UTF_8))
これは断然最も簡単で簡単で慣用的な方法であり、Java自体の依存関係は必要ないと思います。
次に、reflect.io.fileを使用した簡潔なワンライナーを示します。これはScala 2.12で機能します。
reflect.io.File("filename").writeAll("hello world")
または、Javaライブラリを使用する場合は、次のハックを実行できます。
Some(new PrintWriter("filename")).foreach{p => p.write("hello world"); p.close}
Groovy構文が好きな場合は、Pimp-My-Libraryデザインパターンを使用してScalaに取り込むことができます。
import Java.io._
import scala.io._
class RichFile( file: File ) {
def text = Source.fromFile( file )(Codec.UTF8).mkString
def text_=( s: String ) {
val out = new PrintWriter( file , "UTF-8")
try{ out.print( s ) }
finally{ out.close }
}
}
object RichFile {
implicit def enrichFile( file: File ) = new RichFile( file )
}
期待どおりに動作します:
scala> import RichFile.enrichFile
import RichFile.enrichFile
scala> val f = new File("/tmp/example.txt")
f: Java.io.File = /tmp/example.txt
scala> f.text = "hello world"
scala> f.text
res1: String =
"hello world
import sys.process._
"echo hello world" #> new Java.io.File("/tmp/example.txt") !
Apache File Utils を簡単に使用できます。関数writeStringToFile
を見てください。このライブラリをプロジェクトで使用します。
これは十分に簡潔です、私は推測します:
scala> import Java.io._
import Java.io._
scala> val w = new BufferedWriter(new FileWriter("output.txt"))
w: Java.io.BufferedWriter = Java.io.BufferedWriter@44ba4f
scala> w.write("Alice\r\nBob\r\nCharlie\r\n")
scala> w.close()
また、この形式があります。これは簡潔であり、基礎となるライブラリが美しく書かれています(ソースコードを参照)。
import scalax.io.Codec
import scalax.io.JavaConverters._
implicit val codec = Codec.UTF8
new Java.io.File("hi-file.txt").asOutput.write("I'm a hi file! ... Really!")
1行ではないことは知っていますが、私が知る限り、安全性の問題は解決しています。
// This possibly creates a FileWriter, but maybe not
val writer = Try(new FileWriter(new File("filename")))
// If it did, we use it to write the data and return it again
// If it didn't we skip the map and print the exception and return the original, just in-case it was actually .write() that failed
// Then we close the file
writer.map(w => {w.write("data"); w}).recoverWith{case e => {e.printStackTrace(); writer}}.map(_.close)
例外処理を気にしなかった場合は、次のように書くことができます
writer.map(w => {w.writer("data"); w}).recoverWith{case _ => writer}.map(_.close)
JavaライブラリとScalaライブラリを組み合わせてこれを行うことができます。文字エンコードを完全に制御できます。しかし、残念ながら、ファイルハンドルは適切に閉じられません。
scala> import Java.io.ByteArrayInputStream
import Java.io.ByteArrayInputStream
scala> import Java.io.FileOutputStream
import Java.io.FileOutputStream
scala> BasicIO.transferFully(new ByteArrayInputStream("test".getBytes("UTF-8")), new FileOutputStream("test.txt"))
更新:私はここで詳しく説明したより効果的なソリューションを作成しました: https://stackoverflow.com/a/34277491/50111
EclipseのScala Scala内のIDE Worksheetでますます動作していることがわかります(IntelliJ IDEAに同等のものがあると思います)。とにかく、「出力がカットオフ制限を超えています」というメッセージが表示されたら、ワンライナーを実行してコンテンツの一部を出力できる必要があります。特にScalaコレクションを使用して重要なことをしている場合は、メッセージ。
これを簡素化するために、各新しいScalaワークシートの上部に挿入する1ライナーを思い付きました(したがって、非常に単純な必要性のために外部ライブラリのインポート全体を実行する必要はありません)。あなたがステッカーであり、それが技術的に2行であることに気づいた場合、それはこのフォーラムでそれをより読みやすくすることです。 Scala Worksheetの1行です。
def printToFile(content: String, location: String = "C:/Users/jtdoe/Desktop/WorkSheet.txt") =
Some(new Java.io.PrintWriter(location)).foreach{f => try{f.write(content)}finally{f.close}}
そして、使い方は単純です:
printToFile("A fancy test string\ncontaining newlines\nOMG!\n")
これにより、デフォルト以外のファイルを追加したい場合に、オプションでファイル名を指定できます(メソッドが呼び出されるたびにファイルが完全に上書きされます)。
したがって、2番目の使用法は単純です。
printToFile("A fancy test string\ncontaining newlines\nOMG!\n", "C:/Users/jtdoe/Desktop/WorkSheet.txt")
楽しい!
セミコロンの魔法を通して、ワンライナーのようなものを作ることができます。
import Java.io.PrintWriter
import Java.nio.file.Files
import Java.nio.file.Paths
import Java.nio.charset.StandardCharsets
import Java.nio.file.StandardOpenOption
val outfile = Java.io.File.createTempFile("", "").getPath
val outstream = new PrintWriter(Files.newBufferedWriter(Paths.get(outfile)
, StandardCharsets.UTF_8
, StandardOpenOption.WRITE)); outstream.println("content"); outstream.flush(); outstream.close()