Source
สำหรับการอ่านมีความเป็นนามธรรมที่มีประโยชน์ ฉันจะเขียนบรรทัดลงในไฟล์ข้อความได้อย่างไร
Source
สำหรับการอ่านมีความเป็นนามธรรมที่มีประโยชน์ ฉันจะเขียนบรรทัดลงในไฟล์ข้อความได้อย่างไร
คำตอบ:
แก้ไข 2019 (8 ปีต่อมา), Scala-IOเป็นไม่ได้ใช้งานมากถ้าใด ๆLi Haoyiแสดงให้เห็นห้องสมุดของเขาเองlihaoyi/os-lib
ที่เขานำเสนอดังต่อไปนี้
มิถุนายน 2019 ซาเวียร์กุยhotกล่าวถึงคำตอบในห้องสมุดUsing
ซึ่งเป็นยูทิลิตี้สำหรับการจัดการทรัพยากรอัตโนมัติ
แก้ไข (กันยายน 2011): เนื่องจากEduardo Costaถามเกี่ยวกับ Scala2.9 และเนื่องจากความคิดเห็นของRick-777ที่scalax.IO ยืนยันประวัติค่อนข้างไม่มีอยู่จริงตั้งแต่กลางปี 2009 ...
Scala-IOเปลี่ยนสถานที่แล้ว: ดู repo GitHubจาก Jesse Eichar (บน SO ด้วย ):
โครงการ Scala IO ร่มประกอบด้วยโครงการย่อยไม่กี่สำหรับด้านที่แตกต่างและส่วนขยายของ IO
Scala IO มีสององค์ประกอบหลัก:
- แกนหลัก - หลักเกี่ยวกับการอ่านและการเขียนข้อมูลไปยังและจากแหล่งที่มาและอ่างล้างมือโดยพลการ ลักษณะหินมุม
Input
,Output
และSeekable
ที่ให้ API หลัก
ชั้นเรียนอื่น ๆ ที่มีความสำคัญเป็นResource
, และReadChars
WriteChars
- ไฟล์ - ไฟล์เป็นAPI
File
(เรียกว่าPath
) ที่ใช้การรวมกันของระบบไฟล์ Java 7 NIO และ SBT PathFinder API
Path
และFileSystem
เป็นจุดเข้าหลักใน 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)
คำตอบเดิม (มกราคม 2011) กับสถานที่เก่าแก่สำหรับ scala-io:
หากคุณไม่ต้องการรอ Scala2.9 คุณสามารถใช้ห้องสมุดscala-incubator / scala-io
(ดังที่กล่าวไว้ใน " ทำไมแหล่งสกาล่าไม่ปิด InputStream พื้นฐาน ")
ดูตัวอย่าง
{ // 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)
}
นี่เป็นหนึ่งในคุณสมบัติที่ขาดหายไปจาก Scala มาตรฐานที่ฉันพบว่ามีประโยชน์มากที่ฉันเพิ่มลงในห้องสมุดส่วนตัวของฉัน (คุณอาจมีห้องสมุดส่วนตัวด้วย) โค้ดก็เป็นเช่นนั้น:
def printToFile(f: java.io.File)(op: java.io.PrintWriter => Unit) {
val p = new java.io.PrintWriter(f)
try { op(p) } finally { p.close() }
}
และมันถูกใช้แบบนี้:
import java.io._
val data = Array("Five","strings","in","a","file!")
printToFile(new File("example.txt")) { p =>
data.foreach(p.println)
}
Source
(การเข้ารหัสเริ่มต้นโดยค่าเริ่มต้น) แน่นอนคุณสามารถเพิ่มเช่นenc: Option[String] = None
พารามิเตอร์หลังจากf
ถ้าคุณพบว่านี่เป็นความต้องการทั่วไป
คล้ายกับคำตอบของเร็กซ์เคอร์ แต่ทั่วไปมากกว่า ก่อนอื่นฉันใช้ฟังก์ชั่นตัวช่วย:
/**
* 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() }
จากนั้นฉันใช้สิ่งนี้เป็น:
def writeToFile(fileName:String, data:String) =
using (new FileWriter(fileName)) {
fileWriter => fileWriter.write(data)
}
และ
def appendToFile(fileName:String, textData:String) =
using (new FileWriter(fileName, true)){
fileWriter => using (new PrintWriter(fileWriter)) {
printWriter => printWriter.println(textData)
}
}
เป็นต้น
คำตอบง่ายๆ:
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
หรือไม่
ให้คำตอบอื่นเพราะการแก้ไขคำตอบอื่น ๆ ของฉันถูกปฏิเสธ
นี่เป็นคำตอบที่กระชับและง่ายที่สุด (คล้ายกับ Garret Hall's)
File("filename").writeAll("hello world")
สิ่งนี้คล้ายกับ Jus12 แต่ไม่มี verbosity และมีสไตล์ของรหัสที่ถูกต้อง
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))
หมายเหตุคุณไม่ต้องการวงเล็บปีกกาสำหรับtry finally
หรือ lambdas และบันทึกการใช้ไวยากรณ์ตัวยึดตำแหน่ง ยังทราบการตั้งชื่อที่ดีขึ้น
implemented
ข้อกำหนดเบื้องต้น คุณไม่สามารถใช้รหัสที่ไม่ได้ใช้งานได้ ฉันหมายความว่าคุณต้องบอกวิธีการค้นหาเนื่องจากไม่สามารถใช้งานได้ตามค่าเริ่มต้นและไม่เป็นที่รู้จัก
นี่คือซับในหนึ่งรัดกุมโดยใช้ไลบรารีคอมไพเลอร์ Scala:
scala.tools.nsc.io.File("filename").writeAll("hello world")
หรือถ้าคุณต้องการใช้ห้องสมุด Java คุณสามารถแฮ็คนี้:
Some(new PrintWriter("filename")).foreach{p => p.write("hello world"); p.close}
หนึ่งสมุทรสำหรับการบันทึก / อ่าน / จากการใช้String
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
}
ไม่เหมาะสำหรับไฟล์ขนาดใหญ่ แต่จะใช้งานได้
ลิงค์บางส่วน:
java.nio.file.Files.write
java.lang.String.getBytes
scala.collection.JavaConverters
scala.collection.immutable.List.mkString
write
จะคัดลอกcontents
ไปยังอาร์เรย์ไบต์ใหม่แทนที่จะสตรีมไปยังไฟล์ดังนั้นที่จุดสูงสุดจึงใช้หน่วยความจำมากถึงสองเท่ามากกว่าที่contents
อยู่คนเดียว
น่าเสียดายสำหรับคำตอบที่ดีที่สุด Scala-IO ก็ตายแล้ว หากคุณไม่สนใจใช้การอ้างอิงจากบุคคลที่สามให้ลองใช้ไลบรารี่ OS-Libของฉัน สิ่งนี้ทำให้การทำงานกับไฟล์พา ธ และระบบไฟล์ง่ายมาก:
// 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")
แต่ก็มีหนึ่งสมุทรสำหรับการเขียนไปยังไฟล์ , ผนวกกับไฟล์ , เขียนทับไฟล์และการดำเนินงานทั่วไปอื่น ๆ อีกมากมายที่มีประโยชน์ /
ห้องสมุดขนาดเล็กที่ฉันเขียน: https://github.com/pathikrit/better-files
file.appendLine("Hello", "World")
หรือ
file << "Hello" << "\n" << "World"
เริ่มต้นที่ห้องสมุดมาตรฐานให้ยูทิลิตี้การจัดการทรัพยากรโดยเฉพาะ:Scala 2.13
Using
มันสามารถใช้ในกรณีนี้กับทรัพยากรเช่นPrintWriter
หรือBufferedWriter
ที่ขยายAutoCloseable
เพื่อเขียนไปยังไฟล์และไม่ว่าอะไรจะปิดทรัพยากรหลังจากนั้น:
ตัวอย่างเช่นด้วย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)
}
หรือด้วย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"))
}
อัปเดตเมื่อวันที่ 2019 / Sep / 01:
finally
จะกลืนต้นฉบับException
ถูกโยนโดยtry
ถ้าfinally
รหัสโยนException
หลังจากตรวจสอบคำตอบทั้งหมดเหล่านี้เกี่ยวกับวิธีการเขียนไฟล์ใน Scala อย่างง่ายดายและบางส่วนของพวกเขาค่อนข้างดีฉันมีสามประเด็น:
scala.util.Try
close
วิธีการที่จะดำเนินการในแต่ละทรัพยากรขึ้นอยู่ในลำดับที่กลับ - หมายเหตุ:ปิดทรัพยากรขึ้นอยู่ในลำดับที่กลับโดยเฉพาะอย่างยิ่งในกรณีของความล้มเหลวเป็นความต้องการที่ไม่ค่อยเข้าใจของjava.lang.AutoCloseable
เปคซึ่งมีแนวโน้มที่จะนำไปสู่อันตรายมากและยากที่จะหาข้อบกพร่องและความล้มเหลวในเวลาทำงานก่อนที่จะเริ่มเป้าหมายของฉันไม่รัดกุม มันจะช่วยให้เข้าใจง่ายขึ้นสำหรับผู้เริ่มต้น Scala / FP โดยทั่วไปเป็นผู้ที่มาจาก Java ในตอนท้ายฉันจะดึงบิตทั้งหมดเข้าด้วยกันแล้วเพิ่มความกระชับ
ขั้นแรกusing
ต้องอัปเดตวิธีใช้Try
(อีกครั้งความรัดกุมไม่ใช่เป้าหมายที่นี่) มันจะถูกเปลี่ยนชื่อเป็น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
}
}
}
)
การเริ่มต้นของtryUsingAutoCloseable
วิธีการด้านบนอาจทำให้เกิดความสับสนเนื่องจากดูเหมือนจะมีสองรายการพารามิเตอร์แทนรายการพารามิเตอร์แบบกำหนด สิ่งนี้เรียกว่าการแกง และฉันจะไม่อธิบายรายละเอียดเกี่ยวกับการทำงานของแกงกะหรี่หรือเป็นประโยชน์ในบางครั้ง ปรากฎว่าพื้นที่ที่มีปัญหานี้เป็นเครื่องมือที่เหมาะสมสำหรับงาน
ต่อไปเราต้องสร้างวิธีการtryPrintToFile
ที่จะสร้าง (หรือเขียนทับที่มีอยู่) และการเขียนFile
List[String]
มันใช้FileWriter
ซึ่งจะห่อหุ้มด้วยซึ่งเป็นในทางกลับกันห่อหุ้มด้วยBufferedWriter
PrintWriter
และเพื่อยกระดับประสิทธิภาพขนาดบัฟเฟอร์เริ่มต้นมีขนาดใหญ่กว่าค่าเริ่มต้นที่BufferedWriter
กำหนดไว้defaultBufferSize
มากและกำหนดค่า 65536
นี่คือรหัส (และอีกครั้งความกระชับไม่ใช่เป้าหมายที่นี่):
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
เป็นวิธีที่มีประโยชน์ในการที่จะใช้เป็นข้อมูลและส่งไปยังList[String]
File
ตอนนี้ขอสร้างtryWriteToFile
วิธีการที่จะใช้เวลาและเขียนไปยังString
File
นี่คือรหัส (และฉันจะให้คุณเดาความสำคัญของความรัดกุมที่นี่):
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))
}
}
}
ในที่สุดก็เป็นประโยชน์เพื่อให้สามารถดึงข้อมูลเนื้อหาของการเป็นFile
String
ในขณะที่scala.io.Source
จัดให้มีวิธีการที่สะดวกสบายสำหรับการได้รับเนื้อหาของ a อย่างง่ายดายFile
แต่close
ต้องใช้วิธีการSource
เพื่อปล่อย JVM และระบบไฟล์ที่เกี่ยวข้อง หากสิ่งนี้ยังไม่เสร็จสิ้นทรัพยากรจะไม่ถูกปล่อยออกมาจนกว่า JVM GC (Garbage Collector) จะได้รับการปล่อยSource
อินสแตนซ์เอง และถึงแม้จะมีเพียง JVM ที่อ่อนแอเท่านั้นที่รับประกันfinalize
ว่า GC จะถูกเรียกใช้กับclose
ทรัพยากร ซึ่งหมายความว่ามันเป็นความรับผิดชอบของลูกค้าที่จะเรียกclose
วิธีการอย่างชัดเจนเช่นเดียวกับที่เป็นความรับผิดชอบของลูกค้าที่จะสูงclose
ในกรณีของjava.lang.AutoCloseable
. scala.io.Source
สำหรับเรื่องนี้เราต้องมีความหมายที่สองของการใช้วิธีการที่จับ
นี่คือรหัสสำหรับสิ่งนี้ (ยังไม่กระชับ):
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 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
)
)
รุ่นปรับปรุงของฟังก์ชั่นดังกล่าวข้างต้นได้รับให้เป็นคำตอบหนึ่งที่แตกต่างกัน แต่ที่เกี่ยวข้องกับคำถาม
ตอนนี้การนำสิ่งนั้นมารวมกับการนำเข้าที่แยกแล้ว (ทำให้ง่ายต่อการวางลงในแผ่นงาน Scala ที่มีอยู่ในทั้ง Eclipse ScalaIDE และปลั๊กอิน IntelliJ Scala เพื่อให้ง่ายต่อการถ่ายโอนข้อมูลเอาต์พุตไปยังเดสก์ท็อป นี่คือโค้ดที่ดูเหมือน (เพิ่มความกระชับ):
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
)
}
ในฐานะที่เป็นมือใหม่ของ Scala / FP ฉันได้เผาผลาญไปหลายชั่วโมง ฉันหวังว่านี่จะช่วยมือใหม่ Scala / FP คนอื่น ๆ ให้เรียนรู้เรื่องนี้ได้เร็วขึ้น
try-catch-finally
ได้ ยังคงรักความรักของคุณ
นี่คือตัวอย่างของการเขียนเส้นบางไปยังแฟ้มใช้scalaz สตรีม
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 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
สำหรับการจัดการข้อผิดพลาด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 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")
}
อัพเดต 2019:
ข้อมูลสรุป - Java NIO (หรือ NIO.2 สำหรับ async) ยังคงเป็นโซลูชันการประมวลผลไฟล์ที่ครอบคลุมที่สุดที่รองรับใน Scala รหัสต่อไปนี้สร้างและเขียนข้อความไปยังไฟล์ใหม่:
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
วัตถุด้วยชื่อไฟล์ที่คุณเลือกOutputStream
write
ฟังก์ชันเอาต์พุตสตรีมคล้ายกับคำตอบนี้นี่คือตัวอย่างของfs2
(เวอร์ชั่น 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)
}
}
บรรทัดนี้ช่วยในการเขียนไฟล์จาก Array หรือ String
new PrintWriter(outputPath) { write(ArrayName.mkString("")); close }
หากคุณยังมี Akka Streams อยู่ในโครงการของคุณ
def writeToFile(p: Path, s: String)(implicit mat: Materializer): Unit = {
Source.single(ByteString(s)).runWith(FileIO.toPath(p))
}
Akka docs> สตรีมไฟล์ IO