Jika Anda tahu bagaimana melakukannya di Jawa maka Anda dapat menggunakan yang sama di Scala. Apakah pertanyaan Anda khusus dengan perpustakaan standar Scala?
ketika
1
@watiati ya cara terbaik untuk melakukan ini di scala
Proyek payung IO Scala terdiri dari beberapa sub proyek untuk berbagai aspek dan ekstensi IO.
Ada dua komponen utama Scala IO:
Core - Core terutama berkaitan dengan Membaca dan menulis data ke dan dari sumber yang sewenang-wenang dan tenggelam. Ciri-ciri batu sudut adalah Input, Outputdan Seekableyang menyediakan API inti.
Kelas penting lainnya adalah Resource, ReadCharsdan WriteChars.
File - File adalah File(disebut Path) API yang didasarkan pada kombinasi sistem file Java 7 NIO dan SBT PathFinder API. Pathdan FileSystemmerupakan titik masuk utama ke dalam 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)
Jawaban asli (Januari 2011), dengan tempat lama untuk scala-io:
{// several examples of writing dataimport scalax.io.{FileOps,Path,Codec,OpenOption}// the codec must be defined either as a parameter of ops methods or as an implicitimplicitval 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)}
Proyek scalax tampaknya sudah mati (tidak ada komitmen sejak Juni 2009). Apakah ini benar? scalax commit history
Rick-777
@Eduardo: Saya telah menyelesaikan jawaban saya dengan tempat baru untuk perpustakaan scala-io (yang telah diperbarui untuk Scala2.9: github.com/jesseeichar/scala-io/issues/20 )
VonC
10
Apakah ini benar-benar saran saat ini untuk Scala 2.10? Gunakan Scala IO? Belum ada apa-apa di inti Scala?
Phil
2
Saya tidak pernah menggunakan scalax.io, tetapi kalau dilihat dari contoh-contoh ini, sepertinya desain API-nya sangat buruk. Mencampur metode untuk data karakter dan biner dalam satu antarmuka sedikit masuk akal dan kemungkinan besar akan mengarah ke bug pengkodean yang sulit ditemukan. Desain java.io (Reader / Writer vs. InputStream / OutputStream) tampaknya jauh lebih baik.
jcsahnwaldt Reinstate Monica
211
Ini adalah salah satu fitur yang hilang dari Scala standar yang saya temukan sangat berguna sehingga saya menambahkannya ke perpustakaan pribadi saya. (Anda mungkin harus memiliki perpustakaan pribadi juga.) Kode seperti ini:
def printToFile(f: java.io.File)(op: java.io.PrintWriter=>Unit){val p =new java.io.PrintWriter(f)try{ op(p)}finally{ p.close()}}
dan digunakan seperti ini:
import java.io._
val data =Array("Five","strings","in","a","file!")
printToFile(newFile("example.txt")){ p =>
data.foreach(p.println)}
java.io.PrintWriter () baru menggunakan pengkodean platform default, yang mungkin berarti bahwa file hasil tidak terlalu portabel. Misalnya, jika Anda ingin menghasilkan file yang nantinya dapat Anda kirim melalui email, Anda mungkin harus menggunakan konstruktor PrintWriter yang memungkinkan Anda untuk menentukan pengkodean.
jcsahnwaldt Reinstate Monica
@JonaChristopherSahnwaldt - Tentu, dalam kasus khusus Anda mungkin ingin menentukan pengkodean. Default untuk platform adalah standar yang paling masuk akal. Sama seperti dengan Source(penyandian standar secara default). Anda tentu saja dapat menambahkan misalnya enc: Option[String] = Noneparameter setelah fjika Anda menemukan ini sebagai kebutuhan umum.
Rex Kerr
6
@RexKerr - Saya tidak setuju. Seseorang harus menentukan pengkodean di hampir semua kasus. Kebanyakan kesalahan penyandian yang saya temui terjadi karena orang tidak mengerti atau tidak berpikir tentang penyandian. Mereka menggunakan default dan bahkan tidak mengetahuinya karena terlalu banyak API membiarkan mereka melakukannya. Saat ini, standar yang paling masuk akal mungkin adalah UTF-8. Mungkin Anda hanya bekerja dengan bahasa Inggris dan bahasa lain yang dapat ditulis dalam ASCII. Beruntunglah anda. Saya tinggal di Jerman dan harus memperbaiki lebih banyak umlaut yang rusak daripada yang saya ingat.
jcsahnwaldt Reinstate Monica
3
@JonaChristopherSahnwaldt - Ini adalah alasan untuk memiliki penyandian default yang masuk akal, bukan untuk memaksa semua orang untuk menentukannya setiap saat. Tetapi jika Anda menggunakan Mac dan file Anda yang ditulis oleh Java adalah gobbledygook karena mereka bukan Mac OS Roman yang dikodekan, saya tidak yakin itu lebih baik daripada membahayakan. Saya pikir itu kesalahan platform bahwa mereka belum menyetujui charset. Sebagai pengembang individu, mengetikkan string benar-benar tidak akan menyelesaikan masalah. (Semua pengembang setuju pada UTF-8 akan, tapi kemudian itu bisa masuk sebagai default.)
Rex Kerr
@JonaChristopherSahnwaldt +10 untuk memperbaiki semua umlaut yang rusak. Tidak bisa menggunakan palu, mungkin membuat lubang? Atau apakah mereka sudah lubang yang perlu diisi, mungkin orang ini dapat membantu youtube.com/watch?v=E-eBBzWEpwE Tapi serius, pengaruh ASCII sangat merusak di dunia, setuju itu harus ditentukan, dan default sebagai UTF- 8
Davos
50
Serupa dengan jawaban oleh Rex Kerr, tetapi lebih umum. Pertama saya menggunakan fungsi pembantu:
/**
* 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()}
Maka saya menggunakan ini sebagai:
def writeToFile(fileName:String, data:String)=
using (newFileWriter(fileName)){
fileWriter => fileWriter.write(data)}
dan
def appendToFile(fileName:String, textData:String)=
using (newFileWriter(fileName,true)){
fileWriter => using (newPrintWriter(fileWriter)){
printWriter => printWriter.println(textData)}}
Jangan salah paham, saya suka kode Anda dan ini sangat mendidik, tetapi semakin saya melihat konstruksi seperti itu untuk masalah sederhana, semakin mengingatkan saya tentang lelucon "hello world" lama: ariel.com.au/jokes/The_Evolution_of_a_Programmer .html :-) (+1 memberi suara dari saya).
greenoldman
4
Jika Anda menulis satu kalimat, tidak ada masalah sama sekali. Jika Anda menulis program penting (besar dengan kebutuhan pemeliharaan dan evolusi yang berkelanjutan), pemikiran seperti ini mengarah pada jenis penurunan kualitas perangkat lunak yang paling cepat dan merusak.
Randall Schulz
3
Tidak semua orang akan memiliki "mata scala" sampai beberapa tingkat latihan - lucu melihat contoh kode ini berasal dari "Awal" Scala
asyncwait
asyncunggu scala "permulaan" ... judul yang paling ironis, catatan: Saya sudah bukunya ... dan baru saja saya mulai memahaminya .. Saya kira daripada saya selangkah sebelum "pemula" lol: D ........
user1050817
1
Masalahnya bukan trik Scala di sini, tetapi verbositas dan gaya yang buruk. Saya telah mengedit ini agar lebih mudah dibaca. Setelah refactor saya itu hanya 4 baris (yah, 4 dengan panjang garis IDE, digunakan 6 di sini agar sesuai dengan layar). IMHO itu sekarang jawaban yang sangat bagus.
@samthebest dapatkah Anda menambahkan perpustakaan tempat Anda importberasal?
Daniel
1
Pada java 7, gunakan java.nio.file sebagai gantinya: def writeToFile (file: String, stringToWrite: String): Unit = {val writer = Files.newBufferedWriter (Paths.get (file)) coba writer.write (stringToWrite) akhirnya writer.close ()}
E Shindler
20
Memberikan jawaban lain, karena hasil edit saya dari jawaban lain ditolak.
Ini adalah jawaban yang paling ringkas dan sederhana (mirip dengan Garret Hall)
File("filename").writeAll("hello world")
Ini mirip dengan Jus12, tetapi tanpa verbosity dan dengan gaya kode yang benar
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(newFileWriter(path))(_.write(data))def appendToFile(path:String, data:String):Unit=
using(newPrintWriter(newFileWriter(path,true)))(_.println(data))
Perhatikan bahwa Anda TIDAK membutuhkan kurung kurawal untuk try finally, atau lambda, dan perhatikan penggunaan sintaksis tempat penampung. Perhatikan juga penamaan yang lebih baik.
Maaf, tetapi kode Anda bisa dibayangkan, itu tidak memenuhi implementedprasyarat. Anda tidak dapat menggunakan kode yang tidak diterapkan. Maksud saya, Anda harus memberi tahu cara menemukannya karena tidak tersedia secara default dan tidak terkenal.
Val
15
Berikut ini adalah kalimat singkat yang menggunakan pustaka kompiler Scala:
@ ChetanBhasin Mungkin karena writeakan menyalin contentske array byte baru alih-alih streaming ke file, sehingga pada puncaknya menggunakan memori dua kali lebih banyak daripada contentssendirian.
Daniel Werner
10
Sayangnya untuk jawaban teratas, Scala-IO sudah mati. Jika Anda tidak keberatan menggunakan ketergantungan pihak ketiga, pertimbangkan untuk menggunakan perpustakaan OS-Lib saya . Ini membuat bekerja dengan file, jalur dan sistem file sangat mudah:
// Make sure working directory exists and is emptyval 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")
Di sini juga - Pertanyaan ini adalah salah satu hits teratas ketika googling bagaimana menulis file dengan scala - sekarang proyek Anda telah menjadi lebih besar, Anda mungkin ingin sedikit memperluas jawaban Anda?
asac
6
Mulai Scala 2.13, perpustakaan standar menyediakan utilitas manajemen sumber daya khusus: Using.
Ini dapat digunakan dalam kasus ini dengan sumber daya seperti PrintWriteratau BufferedWriteryang meluas AutoCloseableuntuk menulis ke file dan, apa pun yang terjadi, tutup sumber daya setelahnya:
Fixed bug di mana finallyakan menelan asli Exceptiondilemparkan oleh tryjika finallykode melemparkanException
Setelah meninjau semua jawaban ini tentang cara mudah menulis file di Scala, dan beberapa di antaranya cukup bagus, saya punya tiga masalah:
Dalam jawaban Jus12 , penggunaan currying untuk metode helper tidak jelas bagi pemula Scala / FP
Perlu merangkum kesalahan tingkat yang lebih rendah dengan scala.util.Try
Perlu memperlihatkan pengembang Java yang baru ke Scala / FP bagaimana cara menyarangkan sumber daya dependen dengan benar sehingga closemetode ini dilakukan pada setiap sumber daya dependen dalam urutan terbalik - Catatan: menutup sumber daya dependen dalam urutan terbalik. TERUTAMA DALAM ACARA KEGAGALAN adalah persyaratan yang jarang dipahami oleh yang java.lang.AutoCloseablespesifikasi yang cenderung menyebabkan sangat merusak dan sulit untuk menemukan bug dan kegagalan jangka waktu
Sebelum memulai, tujuan saya bukanlah keringkasan. Ini untuk memfasilitasi pemahaman yang lebih mudah bagi pemula Scala / FP, biasanya yang berasal dari Jawa. Pada akhirnya, saya akan mengumpulkan semua bit, dan kemudian meningkatkan keringkasannya.
Pertama, usingmetode ini perlu diperbarui untuk digunakan Try(sekali lagi, keringkasan bukanlah tujuan di sini). Itu akan diubah namanya menjadi 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]=Nonetry
transfer(autoCloseable)catch{case exceptionTry:Exception=>
optionExceptionTry =Some(exceptionTry)throw exceptionTry
}finallytry
autoCloseable.close()catch{case exceptionFinally:Exception=>
optionExceptionTry match{caseSome(exceptionTry)=>
exceptionTry.addSuppressed(exceptionFinally)caseNone=>throw exceptionFinally
}}})
Awal tryUsingAutoCloseablemetode di atas mungkin membingungkan karena tampaknya memiliki dua daftar parameter, bukan daftar parameter tunggal biasa. Ini disebut kari. Dan saya tidak akan menjelaskan secara terperinci bagaimana kari bekerja atau di mana kadang berguna. Ternyata untuk ruang masalah khusus ini, ini adalah alat yang tepat untuk pekerjaan itu.
Selanjutnya, kita perlu membuat metode,, tryPrintToFileyang akan membuat (atau menimpa yang sudah ada) Filedan menulis a List[String]. Ini menggunakan FileWriteryang dienkapsulasi oleh BufferedWriteryang pada gilirannya dienkapsulasi oleh a PrintWriter. Dan untuk meningkatkan kinerja, ukuran buffer standar jauh lebih besar dari standar untuk BufferedWriterdidefinisikan,defaultBufferSize ,, dan diberi nilai 65536.
Inilah kodenya (dan sekali lagi, keringkasan bukanlah tujuan di sini):
val defaultBufferSize:Int=65536def 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)))}}}}
tryPrintToFileMetode di atas berguna karena dibutuhkan List[String]input sebagai dan mengirimkannya ke a File. Sekarang mari kita membuat tryWriteToFilemetode yang mengambil Stringdan menulisnya ke File.
Berikut kodenya (dan saya akan membiarkan Anda menebak prioritas keringkasan di sini):
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))}}}
Akhirnya, berguna untuk dapat mengambil konten Filesebagai String. Meskipun scala.io.Sourcemenyediakan metode yang mudah untuk mendapatkan konten a File, closemetode tersebut harus digunakan pada Sourceuntuk melepaskan JVM dan sistem file yang menangani. Jika ini tidak dilakukan, maka sumber daya tidak dirilis sampai JVM GC (Pengumpul Sampah) sempat merilis Sourceinstance itu sendiri. Dan bahkan kemudian, hanya ada jaminan JVM yang lemah bahwa finalizemetode tersebut akan dipanggil oleh GC ke closesumber daya. Ini berarti bahwa itu adalah tanggung jawab klien untuk secara eksplisit memanggil closemetode, sama seperti itu adalah tanggung jawab klien untuk menilai closepada contoh darijava.lang.AutoCloseable. Untuk ini, kita memerlukan definisi kedua dari metode using yang menangani scala.io.Source.
Dan berikut ini adalah contoh penggunaannya dalam pembaca file streaming baris super sederhana (saat ini digunakan untuk membaca file yang dibatasi-tab dari output basis data):
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))
Sekarang, menggabungkan semua itu dengan impor yang diekstraksi (membuatnya lebih mudah untuk ditempelkan ke lembar kerja Scala yang ada di plugin Eclipse ScalaIDE dan IntelliJ Scala untuk membuatnya lebih mudah untuk membuang output ke desktop agar lebih mudah diperiksa dengan editor teks), seperti inilah bentuk kode (dengan peningkatan keringkasan):
Sebagai pemula Scala / FP, saya telah menghabiskan banyak waktu (sebagian besar frustrasi kepala-menggaruk) mendapatkan pengetahuan dan solusi di atas. Saya harap ini membantu pemula Scala / FP lainnya mengatasi hump belajar ini lebih cepat.
Pembaruan luar biasa. Satu-satunya masalah adalah bahwa sekarang Anda memiliki 100 baris kode yang dapat diganti try-catch-finally. Cintailah gairah Anda.
Pengamat
1
@ Observer Saya akan menegaskan bahwa ini adalah pernyataan yang tidak akurat. Pola yang saya jelaskan sebenarnya mengurangi jumlah boilerplate yang harus ditulis klien untuk memastikan penanganan penutupan AutoCloseables yang tepat sambil juga mengaktifkan pola FP idiomatik Scala menggunakan scala.util.Try. Jika Anda mencoba untuk mencapai efek yang sama saya miliki dengan secara manual menuliskan blok coba / tangkap / akhirnya, saya pikir Anda akan menemukan Anda berakhir dengan boilerplate sedikit lebih banyak daripada yang Anda bayangkan. Jadi, ada nilai keterbacaan yang signifikan dalam mendorong semua boilerplate ke dalam 100 baris fungsi Scala.
chaotic3quilibrium
1
Maaf jika itu terdengar tidak sopan. Namun, maksud saya adalah bahwa tidak perlu dalam jumlah kode seperti itu, karena hal yang sama dapat dicapai melalui pendekatan non-fungsional dengan lebih banyak kesederhanaan. Secara pribadi, saya akan menulis coba-akhirnya dengan beberapa cek tambahan. Itu lebih pendek. Jika saya ingin menggunakan pembungkus, ApacheUtils ada di sana untuk menggunakan semua pekerjaan kotor. Terlebih lagi, semua Pembaca / Penulis standar menutup aliran yang mendasarinya sehingga multipwrap Anda tidak diperlukan. PS: Saya sudah mengubah suara saya dari minus satu ke plus satu untuk mendukung upaya Anda. Jadi, tolong, jangan mencurigai saya dengan niat buruk.
Pengamat
Jangan tersinggung.
chaotic3quilibrium
1
Saya mengerti sudut pandang Anda. Terima kasih untuk diskusi, saya harus memikirkannya sedikit. Semoga harimu menyenangkan!
Pengamat
3
Berikut adalah contoh penulisan beberapa baris ke file menggunakan 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
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 successfulRight(Files.write(destinationFile, fileContent))}catch{case exception:Exception=>Left(exception)}
Pemakaian
val filePath =Paths.get("./testDir/file.txt")
write(filePath ,"A test")match{caseRight(pathToWrittenFile)=> println(s"Successfully wrote to $pathToWrittenFile")caseLeft(exception)=> println(s"Could not write to $filePath. Exception: $exception")}
Ringkasan - Java NIO (atau NIO.2 untuk async) masih merupakan solusi pemrosesan file paling komprehensif yang didukung oleh Scala. Kode berikut membuat dan menulis beberapa teks ke file baru:
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=newBufferedOutputStream(Files.newOutputStream(testFile1))try{
out1.write(s1,0, s1.length)}catch{case _ => println("Exception thrown during file writing")}finally{
out1.close()}
Impor perpustakaan Java: IO dan NIO
Buat Pathobjek dengan nama file yang Anda pilih
Konversikan teks Anda yang ingin Anda masukkan ke file menjadi array byte
Dapatkan file Anda sebagai aliran: OutputStream
Pass array byte Anda ke writefungsi aliran output Anda
Jawaban:
Sunting 2019 (8 tahun kemudian), Scala-IO menjadi sangat tidak aktif, jika ada, Li Haoyi menyarankan perpustakaannya sendiri
lihaoyi/os-lib
, yang dia sajikan di bawah ini .Juni 2019, Xavier Guihot menyebutkan dalam jawabannya perpustakaan
Using
, sebuah utilitas untuk melakukan manajemen sumber daya otomatis.Sunting (September 2011): sejak Eduardo Costa bertanya tentang Scala2.9, dan sejak Rick-777 berkomentar bahwa scalax.IO mencatat sejarah hampir tidak ada sejak pertengahan 2009 ...
Scala-IO telah berubah tempat: lihat repo GitHub -nya, dari Jesse Eichar (juga di SO ):
Jawaban asli (Januari 2011), dengan tempat lama untuk scala-io:
Jika Anda tidak ingin menunggu Scala2.9, Anda dapat menggunakan perpustakaan scala-incubator / scala-io .
(seperti yang disebutkan dalam " Mengapa Sumber Scala tidak menutup InputStream yang mendasarinya? ")
Lihat sampel
sumber
Ini adalah salah satu fitur yang hilang dari Scala standar yang saya temukan sangat berguna sehingga saya menambahkannya ke perpustakaan pribadi saya. (Anda mungkin harus memiliki perpustakaan pribadi juga.) Kode seperti ini:
dan digunakan seperti ini:
sumber
Source
(penyandian standar secara default). Anda tentu saja dapat menambahkan misalnyaenc: Option[String] = None
parameter setelahf
jika Anda menemukan ini sebagai kebutuhan umum.Serupa dengan jawaban oleh Rex Kerr, tetapi lebih umum. Pertama saya menggunakan fungsi pembantu:
Maka saya menggunakan ini sebagai:
dan
dll.
sumber
Jawaban sederhana:
sumber
import
berasal?Memberikan jawaban lain, karena hasil edit saya dari jawaban lain ditolak.
Ini adalah jawaban yang paling ringkas dan sederhana (mirip dengan Garret Hall)
Ini mirip dengan Jus12, tetapi tanpa verbosity dan dengan gaya kode yang benar
Perhatikan bahwa Anda TIDAK membutuhkan kurung kurawal untuk
try finally
, atau lambda, dan perhatikan penggunaan sintaksis tempat penampung. Perhatikan juga penamaan yang lebih baik.sumber
implemented
prasyarat. Anda tidak dapat menggunakan kode yang tidak diterapkan. Maksud saya, Anda harus memberi tahu cara menemukannya karena tidak tersedia secara default dan tidak terkenal.Berikut ini adalah kalimat singkat yang menggunakan pustaka kompiler Scala:
Atau, jika Anda ingin menggunakan perpustakaan Java Anda bisa melakukan hack ini:
sumber
scala.tools.nsc.io.File("/tmp/myFile.txt")
bekerja di Scala 2.11.8.Satu liner untuk menyimpan / membaca ke / dari
String
, menggunakanjava.nio
.Ini tidak cocok untuk file besar, tetapi akan melakukan pekerjaan.
Beberapa tautan:
java.nio.file.Files.write
java.lang.String.getBytes
scala.collection.JavaConverters
scala.collection.immutable.List.mkString
sumber
write
akan menyalincontents
ke array byte baru alih-alih streaming ke file, sehingga pada puncaknya menggunakan memori dua kali lebih banyak daripadacontents
sendirian.Sayangnya untuk jawaban teratas, Scala-IO sudah mati. Jika Anda tidak keberatan menggunakan ketergantungan pihak ketiga, pertimbangkan untuk menggunakan perpustakaan OS-Lib saya . Ini membuat bekerja dengan file, jalur dan sistem file sangat mudah:
Ini memiliki satu-baris untuk menulis ke file , menambahkan file , menimpa file , dan banyak operasi lain yang berguna / umum
sumber
Perpustakaan mikro yang saya tulis: https://github.com/pathikrit/better-files
atau
sumber
Mulai
Scala 2.13
, perpustakaan standar menyediakan utilitas manajemen sumber daya khusus:Using
.Ini dapat digunakan dalam kasus ini dengan sumber daya seperti
PrintWriter
atauBufferedWriter
yang meluasAutoCloseable
untuk menulis ke file dan, apa pun yang terjadi, tutup sumber daya setelahnya:Misalnya, dengan
java.io
api:Atau dengan
java.nio
api:sumber
DIPERBARUI pada 2019 / Sep / 01:
finally
akan menelan asliException
dilemparkan olehtry
jikafinally
kode melemparkanException
Setelah meninjau semua jawaban ini tentang cara mudah menulis file di Scala, dan beberapa di antaranya cukup bagus, saya punya tiga masalah:
scala.util.Try
close
metode ini dilakukan pada setiap sumber daya dependen dalam urutan terbalik - Catatan: menutup sumber daya dependen dalam urutan terbalik. TERUTAMA DALAM ACARA KEGAGALAN adalah persyaratan yang jarang dipahami oleh yangjava.lang.AutoCloseable
spesifikasi yang cenderung menyebabkan sangat merusak dan sulit untuk menemukan bug dan kegagalan jangka waktuSebelum memulai, tujuan saya bukanlah keringkasan. Ini untuk memfasilitasi pemahaman yang lebih mudah bagi pemula Scala / FP, biasanya yang berasal dari Jawa. Pada akhirnya, saya akan mengumpulkan semua bit, dan kemudian meningkatkan keringkasannya.
Pertama,
using
metode ini perlu diperbarui untuk digunakanTry
(sekali lagi, keringkasan bukanlah tujuan di sini). Itu akan diubah namanya menjaditryUsingAutoCloseable
:Awal
tryUsingAutoCloseable
metode di atas mungkin membingungkan karena tampaknya memiliki dua daftar parameter, bukan daftar parameter tunggal biasa. Ini disebut kari. Dan saya tidak akan menjelaskan secara terperinci bagaimana kari bekerja atau di mana kadang berguna. Ternyata untuk ruang masalah khusus ini, ini adalah alat yang tepat untuk pekerjaan itu.Selanjutnya, kita perlu membuat metode,,
tryPrintToFile
yang akan membuat (atau menimpa yang sudah ada)File
dan menulis aList[String]
. Ini menggunakanFileWriter
yang dienkapsulasi olehBufferedWriter
yang pada gilirannya dienkapsulasi oleh aPrintWriter
. Dan untuk meningkatkan kinerja, ukuran buffer standar jauh lebih besar dari standar untukBufferedWriter
didefinisikan,defaultBufferSize
,, dan diberi nilai 65536.Inilah kodenya (dan sekali lagi, keringkasan bukanlah tujuan di sini):
tryPrintToFile
Metode di atas berguna karena dibutuhkanList[String]
input sebagai dan mengirimkannya ke aFile
. Sekarang mari kita membuattryWriteToFile
metode yang mengambilString
dan menulisnya keFile
.Berikut kodenya (dan saya akan membiarkan Anda menebak prioritas keringkasan di sini):
Akhirnya, berguna untuk dapat mengambil konten
File
sebagaiString
. Meskipunscala.io.Source
menyediakan metode yang mudah untuk mendapatkan konten aFile
,close
metode tersebut harus digunakan padaSource
untuk melepaskan JVM dan sistem file yang menangani. Jika ini tidak dilakukan, maka sumber daya tidak dirilis sampai JVM GC (Pengumpul Sampah) sempat merilisSource
instance itu sendiri. Dan bahkan kemudian, hanya ada jaminan JVM yang lemah bahwafinalize
metode tersebut akan dipanggil oleh GC keclose
sumber daya. Ini berarti bahwa itu adalah tanggung jawab klien untuk secara eksplisit memanggilclose
metode, sama seperti itu adalah tanggung jawab klien untuk menilaiclose
pada contoh darijava.lang.AutoCloseable
. Untuk ini, kita memerlukan definisi kedua dari metode using yang menanganiscala.io.Source
.Berikut kode untuk ini (masih belum ringkas):
Dan berikut ini adalah contoh penggunaannya dalam pembaca file streaming baris super sederhana (saat ini digunakan untuk membaca file yang dibatasi-tab dari output basis data):
Versi terbaru dari fungsi di atas telah disediakan sebagai jawaban untuk pertanyaan StackOverflow yang berbeda namun terkait .
Sekarang, menggabungkan semua itu dengan impor yang diekstraksi (membuatnya lebih mudah untuk ditempelkan ke lembar kerja Scala yang ada di plugin Eclipse ScalaIDE dan IntelliJ Scala untuk membuatnya lebih mudah untuk membuang output ke desktop agar lebih mudah diperiksa dengan editor teks), seperti inilah bentuk kode (dengan peningkatan keringkasan):
Sebagai pemula Scala / FP, saya telah menghabiskan banyak waktu (sebagian besar frustrasi kepala-menggaruk) mendapatkan pengetahuan dan solusi di atas. Saya harap ini membantu pemula Scala / FP lainnya mengatasi hump belajar ini lebih cepat.
sumber
try-catch-finally
. Cintailah gairah Anda.Berikut adalah contoh penulisan beberapa baris ke file menggunakan scalaz-stream .
sumber
Untuk melampaui samthebest dan kontributor di depannya, saya telah meningkatkan penamaan dan keringkasan:
sumber
Tidak ada ketergantungan, dengan penanganan kesalahan
Either
untuk penanganan kesalahanKode
Pemakaian
sumber
Pembaruan 2019:
Ringkasan - Java NIO (atau NIO.2 untuk async) masih merupakan solusi pemrosesan file paling komprehensif yang didukung oleh Scala. Kode berikut membuat dan menulis beberapa teks ke file baru:
Path
objek dengan nama file yang Anda pilihOutputStream
write
fungsi aliran output Andasumber
Mirip dengan jawaban ini , berikut adalah contoh dengan
fs2
(versi 1.0.4):sumber
Baris ini membantu untuk menulis file dari Array atau String.
sumber
Jika Anda memiliki Akka Streams di proyek Anda, itu menyediakan satu-liner:
Akka docs> Streaming File IO
sumber