Scala: 在一个语句中将字符串写入文件

在 Scala 中读取文件有

Source.fromFile("file.txt").mkString

是否有一种等价的、简洁的方法将字符串写入文件?

大多数语言都支持类似的东西,我最喜欢的是 Groovy:

def f = new File("file.txt")
// Read
def s = f.text
// Write
f.text = "file contents"

我想使用程序的代码范围从一行代码到一个简短的代码页。必须使用自己的库在这里没有意义。我希望现代语言能让我方便地向文件中写入内容。

也有类似的帖子,但是它们没有回答我的问题,或者只是关注旧版本的 Scala。

例如:

142067 次浏览

如果你喜欢 Groovy 的语法,你可以使用 给我的图书馆拉皮条设计模式把它带到 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 文件工具。看看函数 writeStringToFile。我们在我们的项目中使用这个库。

下面是一个简洁的一行程序,它使用的是 refect.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}

您可以使用 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"))

其中一个还有这种格式,它既简洁,而且底层库写得很漂亮(参见源代码) :

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!")

更新: 我已经创建了一个更有效的解决方案,我在这里详细阐述了这个解决方案: https://stackoverflow.com/a/34277491/501113

我发现自己越来越多地使用 Scala IDE for Eclipse 中的 Scala Worksheet (我相信在 IntelliJ IDEA 中也有类似的东西)。无论如何,我需要能够做一行程序输出一些内容,因为我得到了“输出超过截止限制。”如果我正在做任何重要的事情,特别是对于 Scala 集合。

为了简化这个过程,我在每个新的 Scala 工作表的顶部插入了一行程序(这样我就不必为了一个非常简单的需要而做整个外部库导入练习)。如果你是一个固执己见的人,并注意到它在技术上是两行,这只是为了使它在这个论坛更容易阅读。这是我的 Scala 工作表中的一行。

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")

这使我可以选择性地提供文件名,如果我希望拥有超出默认值的其他文件(每次调用该方法时都会完全覆盖该文件)。

因此,第二种用法很简单:

printToFile("A fancy test string\ncontaining newlines\nOMG!\n", "C:/Users/jtdoe/Desktop/WorkSheet.txt")

好好享受吧!

我想这已经足够简明扼要了:

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()

奇怪的是,没有人建议使用 NIO.2操作(从 Java7开始就可以使用) :

import java.nio.file.{Paths, Files}
import java.nio.charset.StandardCharsets


Files.write(Paths.get("file.txt"), "file contents".getBytes(StandardCharsets.UTF_8))

我认为这是迄今为止最简单、最容易和最惯用的方法,它不需要任何没有 Java 本身的依赖关系。

一句简明扼要的话:

import java.io.PrintWriter
new PrintWriter("filename") { write("file contents"); close }

我写的一个微型图书馆: https://github.com/pathikrit/better-files

file.write("Hi!")

或者

file << "Hi!"

我知道这不是一条线,但就我所知,它解决了安全问题;

// 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)

通过分号的魔力,您可以创建任何您喜欢的一行程序。

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()

使用 菊石行动库。虽然语法非常简单,但是库的宽度几乎和在 bash 这样的 shell 脚本语言中尝试这样的任务时所期望的一样大。

在我链接到的页面上,它显示了许多可以用库进行的操作,但是为了回答这个问题,这是一个写入文件的例子

import ammonite.ops._
write(pwd/"file.txt", "file contents")

Os-lib 是写入文件 就像这里提到的的最佳现代方式。

下面是如何向 file.txt文件写入“ hello”。

os.write(os.pwd/"file.txt", "hello")

Os-lib 隐藏了 Java 的丑陋和复杂性(它在底层使用了 Java 库,所以性能一样好)。有关使用 lib 的更多信息,请参见 给你

这是现代的,安全的一个班轮:

java.nio.file.Files.write(java.nio.file.Paths.get("/tmp/output.txt"), "Hello world".getBytes());

Nio 是 JDK9 + 默认提供的现代 IO 库,因此不需要导入或依赖关系。

import java.nio.file.{Files, Paths}


Files.writeString(
Paths.get(theFilePathString),
thePayloadString
)

(UTF-8隐含)

从 Java 11开始