Đối với việc đọc, có sự trừu tượng hữu ích Source
. Làm thế nào tôi có thể viết các dòng vào một tập tin văn bản?
Đối với việc đọc, có sự trừu tượng hữu ích Source
. Làm thế nào tôi có thể viết các dòng vào một tập tin văn bản?
Câu trả lời:
Chỉnh sửa 2019 (8 năm sau), Scala-IO không hoạt động nhiều, nếu có, Li Haoyi gợi ý thư viện của riêng mình lihaoyi/os-lib
, mà anh trình bày dưới đây .
Tháng 6 năm 2019, Xavier Guihot đề cập đến câu trả lời của ông về thư viện Using
, một tiện ích để thực hiện quản lý tài nguyên tự động.
Chỉnh sửa (tháng 9 năm 2011): kể từ khi Eduardo Costa hỏi về Scala2.9, và vì Rick-777 nhận xét rằng scalax.IO cam kết lịch sử không tồn tại nhiều kể từ giữa năm 2009 ...
Scala-IO đã thay đổi địa điểm: xem repo GitHub của nó, từ Jesse Eichar (cũng trên SO ):
Dự án ô Scala IO bao gồm một vài dự án phụ cho các khía cạnh và phần mở rộng khác nhau của IO.
Có hai thành phần chính của Scala IO:
- Core - Core chủ yếu liên quan đến việc đọc và ghi dữ liệu đến và từ các nguồn và mức tùy ý. Các đặc điểm đá góc là
Input
,Output
vàSeekable
cung cấp các API lõi.
Các lớp quan trọng khác làResource
,ReadChars
vàWriteChars
.- Tệp - Tệp là API
File
(được gọiPath
) dựa trên sự kết hợp của hệ thống tệp NIO Java 7 và API SBT Path Downloader.
Path
vàFileSystem
là các điểm nhập chính vào API tệp Scala IO.
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)
Câu trả lời gốc (tháng 1 năm 2011), với vị trí cũ cho scala-io:
Nếu bạn không muốn đợi Scala2.9, bạn có thể sử dụng thư viện scala-incubator / scala-io .
(như đã đề cập trong " Tại sao Nguồn Scala không đóng InputStream bên dưới? ")
Xem các mẫu
{ // 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)
}
Đây là một trong những tính năng còn thiếu từ Scala tiêu chuẩn mà tôi thấy hữu ích đến mức tôi thêm nó vào thư viện cá nhân của mình. (Có lẽ bạn cũng nên có một thư viện cá nhân.) Đoạn mã giống như vậy:
def printToFile(f: java.io.File)(op: java.io.PrintWriter => Unit) {
val p = new java.io.PrintWriter(f)
try { op(p) } finally { p.close() }
}
và nó được sử dụng như thế này:
import java.io._
val data = Array("Five","strings","in","a","file!")
printToFile(new File("example.txt")) { p =>
data.foreach(p.println)
}
Source
(mã hóa mặc định theo mặc định). Tất nhiên bạn có thể thêm ví dụ như một enc: Option[String] = None
tham số sau f
nếu bạn thấy đây là một nhu cầu chung.
Tương tự như câu trả lời của Rex Kerr, nhưng chung chung hơn. Đầu tiên tôi sử dụng chức năng trợ giúp:
/**
* 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() }
Sau đó, tôi sử dụng như:
def writeToFile(fileName:String, data:String) =
using (new FileWriter(fileName)) {
fileWriter => fileWriter.write(data)
}
và
def appendToFile(fileName:String, textData:String) =
using (new FileWriter(fileName, true)){
fileWriter => using (new PrintWriter(fileWriter)) {
printWriter => printWriter.println(textData)
}
}
Vân vân.
Một câu trả lời đơn giản:
import java.io.File
import java.io.PrintWriter
def writeToFile(p: String, s: String): Unit = {
val pw = new PrintWriter(new File(p))
try pw.write(s) finally pw.close()
}
import
từ?
Đưa ra một câu trả lời khác, bởi vì những chỉnh sửa của tôi về những câu trả lời khác bị từ chối.
Đây là câu trả lời ngắn gọn và đơn giản nhất (tương tự như Garret Hall)
File("filename").writeAll("hello world")
Điều này tương tự với Jus12, nhưng không có độ dài và với kiểu mã chính xác
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(new FileWriter(path))(_.write(data))
def appendToFile(path: String, data: String): Unit =
using(new PrintWriter(new FileWriter(path, true)))(_.println(data))
Lưu ý rằng bạn KHÔNG cần các dấu ngoặc nhọn cho try finally
, cũng như lambdas và lưu ý sử dụng cú pháp giữ chỗ. Cũng lưu ý đặt tên tốt hơn.
implemented
điều kiện tiên quyết. Bạn không thể sử dụng mã không được thực hiện. Tôi có nghĩa là bạn phải cho biết làm thế nào để tìm thấy nó vì nó không có sẵn theo mặc định và không nổi tiếng.
Dưới đây là một lớp lót ngắn gọn bằng thư viện trình biên dịch Scala:
scala.tools.nsc.io.File("filename").writeAll("hello world")
Ngoài ra, nếu bạn muốn sử dụng các thư viện Java, bạn có thể thực hiện việc hack này:
Some(new PrintWriter("filename")).foreach{p => p.write("hello world"); p.close}
scala.tools.nsc.io.File("/tmp/myFile.txt")
hoạt động trong Scala 2.11.8.
Một lớp lót để lưu / đọc đến / từ String
, sử dụng 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
}
Điều này không phù hợp với các tệp lớn, nhưng sẽ thực hiện công việc.
Một số liên kết:
java.nio.file.Files.write
java.lang.String.getBytes
scala.collection.JavaConverters
scala.collection.immutable.List.mkString
write
sẽ sao chép contents
vào một mảng byte mới thay vì truyền nó vào tệp, do đó, ở mức cao nhất của nó sử dụng bộ nhớ nhiều gấp đôi so với contents
một mình.
Thật không may cho câu trả lời hàng đầu, Scala-IO đã chết. Nếu bạn không phiền khi sử dụng phụ thuộc của bên thứ ba, hãy xem xét sử dụng thư viện OS-Lib của tôi . Điều này làm cho việc làm việc với các tệp, đường dẫn và hệ thống tệp rất dễ dàng:
// 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")
Nó có một lớp để ghi vào tập tin , nối thêm vào tệp , ghi đè tệp và nhiều hoạt động hữu ích / phổ biến khác
Một thư viện vi mô tôi đã viết: https://github.com/pathikrit/better-files
file.appendLine("Hello", "World")
hoặc là
file << "Hello" << "\n" << "World"
Bắt đầu Scala 2.13
, thư viện chuẩn cung cấp tiện ích quản lý tài nguyên chuyên dụng : Using
.
Nó có thể được sử dụng trong trường hợp này với các tài nguyên như PrintWriter
hoặc BufferedWriter
mở rộng AutoCloseable
để ghi vào một tệp và, bất kể là gì, hãy đóng tài nguyên sau đó:
Chẳng hạn, với java.io
api:
import scala.util.Using, java.io.{PrintWriter, File}
// val lines = List("hello", "world")
Using(new PrintWriter(new File("file.txt"))) {
writer => lines.foreach(writer.println)
}
Hoặc với java.nio
api:
import scala.util.Using, java.nio.file.{Files, Paths}, java.nio.charset.Charset
// val lines = List("hello", "world")
Using(Files.newBufferedWriter(Paths.get("file.txt"), Charset.forName("UTF-8"))) {
writer => lines.foreach(line => writer.write(line + "\n"))
}
CẬP NHẬT vào năm 2019 / tháng 9/01:
finally
sẽ nuốt gốc Exception
ném bởi try
nếu finally
đang ném mộtException
Sau khi xem xét tất cả các câu trả lời về cách dễ dàng viết một tệp trong Scala và một số trong số chúng khá hay, tôi có ba vấn đề:
scala.util.Try
close
phương pháp được thực hiện trên mỗi tài nguyên phụ thuộc vào thứ tự ngược lại - Lưu ý: đóng nguồn lực phụ thuộc vào thứ tự ngược lại đặc biệt là trong trường hợp mất là một yêu cầu hiếm khi hiểu của các java.lang.AutoCloseable
đặc điểm kỹ thuật mà có xu hướng dẫn đến rất nguy hại và khó khăn để tìm lỗi và thất bại thời gian chạyTrước khi bắt đầu, mục tiêu của tôi không phải là sự đồng nhất. Đó là để tạo điều kiện dễ hiểu hơn cho người mới bắt đầu Scala / FP, điển hình là những người đến từ Java. Cuối cùng, tôi sẽ kéo tất cả các bit lại với nhau, và sau đó tăng độ đồng nhất.
Đầu tiên, using
phương pháp cần được cập nhật để sử dụng Try
(một lần nữa, tính đồng nhất không phải là mục tiêu ở đây). Nó sẽ được đổi tên thành 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] = None
try
transfer(autoCloseable)
catch {
case exceptionTry: Exception =>
optionExceptionTry = Some(exceptionTry)
throw exceptionTry
}
finally
try
autoCloseable.close()
catch {
case exceptionFinally: Exception =>
optionExceptionTry match {
case Some(exceptionTry) =>
exceptionTry.addSuppressed(exceptionFinally)
case None =>
throw exceptionFinally
}
}
}
)
Sự khởi đầu của tryUsingAutoCloseable
phương thức trên có thể gây nhầm lẫn bởi vì nó dường như có hai danh sách tham số thay vì danh sách tham số duy nhất tùy chỉnh. Điều này được gọi là cà ri. Và tôi sẽ không đi vào chi tiết cách thức hoạt động của cà ri hoặc nơi đôi khi nó hữu ích. Nó chỉ ra rằng đối với không gian vấn đề cụ thể này, nó là công cụ phù hợp cho công việc.
Tiếp theo, chúng ta cần tạo phương thức, tryPrintToFile
sẽ tạo một (hoặc ghi đè lên một cái hiện có) File
và viết a List[String]
. Nó sử dụng một FileWriter
cái được gói gọn bởi cái BufferedWriter
mà lần lượt được gói gọn bởi a PrintWriter
. Và để nâng cao hiệu suất, kích thước bộ đệm mặc định lớn hơn nhiều so với mặc định BufferedWriter
được xác định,defaultBufferSize
và được gán giá trị 65536.
Đây là mã (và một lần nữa, sự đồng nhất không phải là mục tiêu ở đây):
val defaultBufferSize: Int = 65536
def 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))
)
}
}
}
}
tryPrintToFile
Phương thức trên hữu ích ở chỗ nó lấy một List[String]
đầu vào và gửi nó đến a File
. Bây giờ chúng ta hãy tạo một tryWriteToFile
phương thức lấy String
và ghi nó vàoFile
.
Đây là mã (và tôi sẽ cho phép bạn đoán mức độ ưu tiên của sự đồng nhất ở đây):
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))
}
}
}
Cuối cùng, rất hữu ích khi có thể tìm nạp nội dung của a File
dưới dạng a String
. Mặc dù scala.io.Source
cung cấp một phương thức thuận tiện để dễ dàng lấy nội dung của a File
, nhưng close
phương thức này phải được sử dụng trên Source
để giải phóng JVM cơ bản và xử lý hệ thống tệp. Nếu điều này không được thực hiện, thì tài nguyên sẽ không được giải phóng cho đến khi JVM GC (Garbage Collector) có mặt để phát hành Source
cá thể. Và thậm chí sau đó, chỉ có một JVM yếu đảm bảo finalize
phương thức sẽ được gọi bởi GC tới close
tài nguyên. Điều này có nghĩa là trách nhiệm của khách hàng là gọi một cách rõ ràngclose
phương thức , giống như trách nhiệm của khách hàng đối với người caoclose
trong trường hợpjava.lang.AutoCloseable
. Đối với điều này, chúng ta cần một định nghĩa thứ hai về phương thức sử dụng xử lý scala.io.Source
.
Đây là mã cho việc này (vẫn chưa được súc tích):
def tryUsingSource[S <: scala.io.Source, R]
(instantiateSource: () => S)
(transfer: S => scala.util.Try[R])
: scala.util.Try[R] =
Try(instantiateSource())
.flatMap(
source => {
var optionExceptionTry: Option[Exception] = None
try
transfer(source)
catch {
case exceptionTry: Exception =>
optionExceptionTry = Some(exceptionTry)
throw exceptionTry
}
finally
try
source.close()
catch {
case exceptionFinally: Exception =>
optionExceptionTry match {
case Some(exceptionTry) =>
exceptionTry.addSuppressed(exceptionFinally)
case None =>
throw exceptionFinally
}
}
}
)
Và đây là một ví dụ sử dụng nó trong một trình đọc tệp phát trực tuyến siêu đơn giản (hiện đang sử dụng để đọc các tệp được phân định bằng tab từ đầu ra cơ sở dữ liệu):
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
)
)
Một phiên bản cập nhật của chức năng trên đã được cung cấp dưới dạng câu trả lời cho câu hỏi StackOverflow khác nhưng có liên quan .
Bây giờ, kết hợp tất cả cùng với các bản nhập được trích xuất (giúp dễ dàng dán vào Bảng tính Scala hơn trong cả plugin Eclipse ScalaIDE và IntelliJ Scala để dễ dàng chuyển đầu ra sang máy tính để bàn dễ dàng kiểm tra hơn bằng trình soạn thảo văn bản), đây là mã trông như thế nào (với độ đồng nhất tăng):
import scala.io.Source
import scala.util.Try
import java.io.{BufferedWriter, FileWriter, File, PrintWriter}
val defaultBufferSize: Int = 65536
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] = None
try
transfer(autoCloseable)
catch {
case exceptionTry: Exception =>
optionExceptionTry = Some(exceptionTry)
throw exceptionTry
}
finally
try
autoCloseable.close()
catch {
case exceptionFinally: Exception =>
optionExceptionTry match {
case Some(exceptionTry) =>
exceptionTry.addSuppressed(exceptionFinally)
case None =>
throw exceptionFinally
}
}
}
)
def tryUsingSource[S <: scala.io.Source, R]
(instantiateSource: () => S)
(transfer: S => scala.util.Try[R])
: scala.util.Try[R] =
Try(instantiateSource())
.flatMap(
source => {
var optionExceptionTry: Option[Exception] = None
try
transfer(source)
catch {
case exceptionTry: Exception =>
optionExceptionTry = Some(exceptionTry)
throw exceptionTry
}
finally
try
source.close()
catch {
case exceptionFinally: Exception =>
optionExceptionTry match {
case Some(exceptionTry) =>
exceptionTry.addSuppressed(exceptionFinally)
case None =>
throw exceptionFinally
}
}
}
)
def tryPrintToFile(
lines: List[String],
location: File,
bufferSize: Int = defaultBufferSize
): Try[Unit] =
tryUsingAutoCloseable(() => new FileWriter(location)) { fileWriter =>
tryUsingAutoCloseable(() => new BufferedWriter(fileWriter, bufferSize)) { bufferedWriter =>
tryUsingAutoCloseable(() => new PrintWriter(bufferedWriter)) { printWriter =>
Try(lines.foreach(line => printWriter.println(line)))
}
}
}
def tryWriteToFile(
content: String,
location: File,
bufferSize: Int = defaultBufferSize
): Try[Unit] =
tryUsingAutoCloseable(() => new FileWriter(location)) { fileWriter =>
tryUsingAutoCloseable(() => new BufferedWriter(fileWriter, bufferSize)) { bufferedWriter =>
Try(bufferedWriter.write(content))
}
}
def tryProcessSource(
file: 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
): Try[List[List[String]]] =
tryUsingSource(() => Source.fromFile(file)) { source =>
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
)
}
Là một người mới chơi Scala / FP, tôi đã đốt cháy nhiều giờ (trong sự thất vọng chủ yếu là đau đầu) để kiếm được kiến thức và giải pháp trên. Tôi hy vọng điều này sẽ giúp những người mới Scala / FP khác vượt qua được khối học tập đặc biệt này nhanh hơn.
try-catch-finally
. Vẫn yêu đam mê của bạn.
Đây là một ví dụ về việc viết một số dòng vào một tệp bằng cách sử dụng 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
Để vượt qua samthebest và những người đóng góp trước anh ấy, tôi đã cải thiện việc đặt tên và sự đồng nhất:
def using[A <: {def close() : Unit}, B](resource: A)(f: A => B): B =
try f(resource) finally resource.close()
def writeStringToFile(file: File, data: String, appending: Boolean = false) =
using(new FileWriter(file, appending))(_.write(data))
Either
để xử lý lỗidef 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 successful
Right(Files.write(destinationFile, fileContent))
} catch {
case exception: Exception => Left(exception)
}
val filePath = Paths.get("./testDir/file.txt")
write(filePath , "A test") match {
case Right(pathToWrittenFile) => println(s"Successfully wrote to $pathToWrittenFile")
case Left(exception) => println(s"Could not write to $filePath. Exception: $exception")
}
Cập nhật 2019:
Tóm tắt - Java NIO (hoặc NIO.2 cho async) vẫn là giải pháp xử lý tệp toàn diện nhất được hỗ trợ trong Scala. Đoạn mã sau tạo và ghi một số văn bản vào một tệp mới:
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()
}
Path
đối tượng với tên tệp bạn đã chọnOutputStream
write
chức năng của luồng đầu ra của bạnTương tự như câu trả lời này , đây là một ví dụ với fs2
(phiên bản 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)
}
}
Nếu bạn đang có các luồng Akka trong dự án của mình, nó sẽ cung cấp một lớp lót:
def writeToFile(p: Path, s: String)(implicit mat: Materializer): Unit = {
Source.single(ByteString(s)).runWith(FileIO.toPath(p))
}
Tài liệu Akka> Truyền tệp IO