How to write to a file in Scala?

2020-01-22 13:55发布

For reading, there is the useful abstraction Source. How can I write lines to a text file?

18条回答
Summer. ? 凉城
2楼-- · 2020-01-22 13:57

2019 Update:

Summary - Java NIO (or NIO.2 for async) is still the most comprehensive file processing solution supported in Scala. The following code creates and writes some text to a new file:

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 = new BufferedOutputStream(
  Files.newOutputStream(testFile1))

try {
  out1.write(s1, 0, s1.length)
} catch {
  case _ => println("Exception thrown during file writing")
} finally {
  out1.close()
}
  1. Import Java libraries: IO and NIO
  2. Create a Path object with your chosen file name
  3. Convert your text that you want to insert into a file into a byte array
  4. Get your file as a stream: OutputStream
  5. Pass your byte array into your output stream's write function
  6. Close the stream
查看更多
▲ chillily
3楼-- · 2020-01-22 13:58

Similar to the answer by Rex Kerr, but more generic. First I use a helper function:

/**
 * 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() }

Then I use this as:

def writeToFile(fileName:String, data:String) = 
  using (new FileWriter(fileName)) {
    fileWriter => fileWriter.write(data)
  }

and

def appendToFile(fileName:String, textData:String) =
  using (new FileWriter(fileName, true)){ 
    fileWriter => using (new PrintWriter(fileWriter)) {
      printWriter => printWriter.println(textData)
    }
  }

etc.

查看更多
疯言疯语
4楼-- · 2020-01-22 14:05

Edit 2019 (8 years later), Scala-IO being not very active, if any, Li Haoyi suggests his own library lihaoyi/os-lib, that he presents below.

June 2019, Xavier Guihot mentions in his answer the library Using, a utility for performing automatic resource management.


Edit (September 2011): since Eduardo Costa asks about Scala2.9, and since Rick-777 comments that scalax.IO commit history is pretty much non-existent since mid-2009...

Scala-IO has changed place: see its GitHub repo, from Jesse Eichar (also on SO):

The Scala IO umbrella project consists of a few sub projects for different aspects and extensions of IO.
There are two main components of Scala IO:

  • Core - Core primarily deals with Reading and writing data to and from arbitrary sources and sinks. The corner stone traits are Input, Output and Seekable which provide the core API.
    Other classes of importance are Resource, ReadChars and WriteChars.
  • File - File is a File (called Path) API that is based on a combination of Java 7 NIO filesystem and SBT PathFinder APIs.
    Path and FileSystem are the main entry points into the Scala IO File API.
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)

Original answer (January 2011), with the old place for scala-io:

If you don't want to wait for Scala2.9, you can use the scala-incubator / scala-io library.
(as mentioned in "Why doesn't Scala Source close the underlying InputStream?")

See the samples

{ // several examples of writing data
    import scalax.io.{
      FileOps, Path, Codec, OpenOption}
    // the codec must be defined either as a parameter of ops methods or as an implicit
    implicit val 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)
  }
查看更多
欢心
5楼-- · 2020-01-22 14:05

Unfortunately for the top answer, Scala-IO is dead. If you don't mind using a third-party dependency, consider using my OS-Lib library. This makes working with files, paths and the filesystem very easy:

// Make sure working directory exists and is empty
val 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")

It has one-liners for writing to files, appending to files, overwriting files, and many other useful/common operations

查看更多
来,给爷笑一个
6楼-- · 2020-01-22 14:05

Similar to this answer, here is an example with fs2 (version 1.0.4):

import cats.effect._

import fs2._
import fs2.io

import java.nio.file._

import scala.concurrent.ExecutionContext
import scala.language.higherKinds
import cats.syntax.functor._

object ScalaApp extends IOApp {

  def write[T[_]](p: Path, s: String)
                 (implicit F: ConcurrentEffect[T], cs: ContextShift[T]): T[Unit] = {
    Stream(s)
      .covary[T]
      .through(text.utf8Encode)
      .through(
        io.file.writeAll(
          p,
          scala.concurrent.ExecutionContext.global,
          Seq(StandardOpenOption.CREATE)
        )
      )
      .compile
      .drain
  }


  def run(args: List[String]): IO[ExitCode] = {

    implicit val executionContext: ExecutionContext =
      scala.concurrent.ExecutionContext.Implicits.global

    implicit val contextShift: ContextShift[IO] =
      IO.contextShift(executionContext)

    val outputFile: Path = Paths.get("output.txt")

    write[IO](outputFile, "Hello world\n").as(ExitCode.Success)

  }
}
查看更多
劫难
7楼-- · 2020-01-22 14:08

One liners for saving/reading to/from String, using java.nio.

import java.nio.file.{Paths, Files, StandardOpenOption}
import java.nio.charset.{StandardCharsets}
import scala.collection.JavaConverters._

def write(filePath:String, contents:String) = {
  Files.write(Paths.get(filePath), contents.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE)
}

def read(filePath:String):String = {
  Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8).asScala.mkString
}

This isn't suitable for large files, but will do the job.

Some links:

java.nio.file.Files.write
java.lang.String.getBytes
scala.collection.JavaConverters
scala.collection.immutable.List.mkString

查看更多
登录 后发表回答