स्काला में फाइल कैसे लिखें?


157

पढ़ने के लिए, उपयोगी अमूर्तता है Source। मैं टेक्स्ट फ़ाइल में लाइनें कैसे लिख सकता हूं?


1
यदि आप जानते हैं कि जावा में ऐसा कैसे किया जाता है तो आप स्काला में इसका उपयोग कर सकते हैं। क्या आपका प्रश्न विशेष रूप से स्काला मानक पुस्तकालय के साथ है?
गेहूँ

1
@ जब यह scala में ऐसा करने के लिए सबसे अच्छा तरीका है
yura

यह पुस्तकालय वास्तव में अच्छा है: github.com/pathikrit/better-files
रॉबिन

Lihaoyi का OS-Lib लाइब्रेरी github.com/lihaoyi/os-lib
WeiChing 清

जवाबों:


71

2019 (8 साल बाद) को संपादित करें, स्काला-आईओ बहुत सक्रिय नहीं है, यदि कोई हो, तो ली हैय अपने स्वयं के पुस्तकालय का सुझाव देता है lihaoyi/os-lib, जिसे वह नीचे प्रस्तुत करता है

जून 2019, ज़ेवियर गुइहोट ने अपने जवाब में पुस्तकालय का उल्लेख किया Using, स्वचालित संसाधन प्रबंधन करने के लिए एक उपयोगिता।


संपादित करें (सितंबर 2011): चूंकि एडुआर्डो कोस्टा Scala2.9 के बारे में पूछते हैं, और रिक -777 टिप्पणी के बाद से कि scalax.IO कमिटमेंट हिस्ट्री 2009 के मध्य से बहुत ज्यादा गैर-मौजूद है ...

स्काला-आईओ ने जगह बदल ली है: जेथ ईशर ( एसओ पर भी)सेइसकी गिटहब रेपो देखें:

स्काला IO अंब्रेला प्रोजेक्ट में IO के विभिन्न पहलुओं और विस्तार के लिए कुछ उप परियोजनाएं शामिल हैं।
स्काला IO के दो मुख्य घटक हैं:

  • कोर - कोर मुख्य रूप से मनमाने स्रोतों और सिंक से पढ़ने और लिखने के डेटा से संबंधित है। कोने के पत्थर के लक्षण हैं Input, Outputऔर Seekableजो कोर एपीआई प्रदान करते हैं।
    महत्व के अन्य वर्ग हैं Resource, ReadCharsऔर WriteChars
  • फ़ाइल - फाइल एक File(बुलाया Path) एपीआई है जो जावा 7 एनआईओ फाइल सिस्टम और एसबीटी पाथफाइंडर एपीआई के संयोजन पर आधारित है।
    Pathऔर FileSystemस्काला आईओ फाइल एपीआई में मुख्य प्रवेश बिंदु हैं।
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), स्काला-आईओ के लिए पुराने स्थान के साथ:

यदि आप Scala2.9 की प्रतीक्षा नहीं करना चाहते हैं, तो आप scala-incubator / scala-io लाइब्रेरी का उपयोग कर सकते हैं ।
(जैसा कि " क्यों स्काला स्रोत अंतर्निहित इनपुटस्ट्रीम बंद नहीं करता है? "

नमूने देखें

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

15
एक स्केल 2.9 संस्करण के बारे में क्या? :)
एडुआर्डो कोस्टा

स्केलैक्स प्रोजेक्ट मृत प्रतीत होता है (जून 2009 से कोई कमिट नहीं है)। क्या यह सही है? स्केलक्स कमिट हिस्ट्री
रिक -777

@Eduardo:: मैं स्केला-कब पुस्तकालय के लिए नई जगह (Scala2.9 के लिए अद्यतन किया गया है, जिसके साथ मेरा उत्तर पूरा कर लिया है github.com/jesseeichar/scala-io/issues/20 )
VonC

10
क्या यह वास्तव में स्कैला 2.10 के लिए वर्तमान सुझाव है? Scala IO का उपयोग करें? कोर स्काला में अभी तक कुछ नहीं है?
फिल

2
मैंने कभी भी स्केलैक्स.आईओ का उपयोग नहीं किया है, लेकिन इन उदाहरण लाइनों से देखते हुए, ऐसा लगता है कि इसकी एपीआई डिजाइन बहुत खराब है। चरित्र और द्विआधारी डेटा के लिए एक इंटरफ़ेस में मिक्सिंग विधि बहुत कम समझ में आती है और इससे एन्कोडिंग कीड़े पैदा होने की संभावना होगी जो कि खोजना मुश्किल है। Java.io (रीडर / राइटर बनाम इनपुटस्ट्रीम / आउटपुटस्ट्रीम) का डिज़ाइन बहुत बेहतर लगता है।
jcsahnwaldt मोनिका

211

यह मानक स्काला से गायब होने वाली सुविधाओं में से एक है जिसे मैंने इतना उपयोगी पाया है कि मैं इसे अपने निजी पुस्तकालय में जोड़ता हूं। (आपके पास शायद एक निजी पुस्तकालय भी होना चाहिए।) कोड इस प्रकार है:

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

1
new java.io.PrintWriter () प्लेटफ़ॉर्म डिफ़ॉल्ट एन्कोडिंग का उपयोग करता है, जिसका अर्थ है कि परिणाम फ़ाइल बहुत पोर्टेबल नहीं है। उदाहरण के लिए, यदि आप एक ऐसी फ़ाइल का निर्माण करना चाहते हैं जिसे आप बाद में ईमेल द्वारा भेज सकते हैं, तो आपको संभवतः PrintWriter निर्माता का उपयोग करना चाहिए जो आपको एन्कोडिंग निर्दिष्ट करने की अनुमति देता है।
jcsahnwaldt

@JonaChristopherSahnwaldt - निश्चित रूप से, विशेष मामलों में आप एन्कोडिंग निर्दिष्ट करना चाह सकते हैं। प्लेटफ़ॉर्म के लिए डिफ़ॉल्ट औसत रूप से सबसे समझदार डिफ़ॉल्ट है। साथ ही Source(डिफ़ॉल्ट रूप से डिफ़ॉल्ट एन्कोडिंग)। यदि आप इसे एक सामान्य आवश्यकता पाते हैं, तो आप निश्चित रूप से एक enc: Option[String] = Noneपैरामीटर जोड़ सकते हैं f
रेक्स केर

6
@RexKerr - मैं असहमत हूं। एक को लगभग सभी मामलों में एन्कोडिंग निर्दिष्ट करना चाहिए। अधिकांश एन्कोडिंग त्रुटियां जो मुझे होती हैं, क्योंकि लोग एन्कोडिंग के बारे में नहीं समझते हैं या नहीं सोचते हैं। वे डिफ़ॉल्ट का उपयोग करते हैं और यह भी नहीं जानते हैं क्योंकि बहुत से एपीआई उन्हें इसके साथ दूर जाने देते हैं। आजकल, सबसे समझदार डिफ़ॉल्ट शायद UTF-8 होगा। हो सकता है कि आप केवल अंग्रेजी और अन्य भाषाओं के साथ काम करें जो ASCII में लिखी जा सकती हैं। तुम भाग्यशाली हो। मैं जर्मनी में रहता हूं और मुझे याद रखने की तुलना में अधिक टूटे हुए उम्मट को ठीक करना था।
jcsahnwaldt मोनिका

3
@JonaChristopherSahnwaldt - यह एक समझदार डिफ़ॉल्ट एन्कोडिंग का कारण है, हर किसी को हर समय इसे निर्दिष्ट करने के लिए मजबूर करने के लिए नहीं। लेकिन अगर आप मैक पर हैं और जावा द्वारा लिखी गई आपकी फाइलें gobbledygook हैं क्योंकि वे मैक ओएस रोमन एन्कोडेड नहीं हैं, तो मुझे यकीन नहीं है कि यह नुकसान से अधिक अच्छा कर रहा है। मुझे लगता है कि यह प्लेटफार्मों की गलती है कि वे एक चारसेट पर सहमत नहीं हुए हैं। एक व्यक्तिगत डेवलपर के रूप में, स्ट्रिंग में टाइप करना वास्तव में समस्या को हल करने वाला नहीं है। (सभी डेवलपर UTF-8 पर सहमत होते हैं, लेकिन तब वह केवल डिफ़ॉल्ट के रूप में जा सकता है।)
रेक्स केर

@JonaChristopherSahnwaldt +10 सभी टूटे हुए umlaut को ठीक करने के लिए। एक हथौड़ा, शायद एक छेद पंच का उपयोग नहीं कर सकते? या वे पहले से ही छेद कर रहे हैं जिन्हें भरने की आवश्यकता है, शायद यह आदमी youtube.com/watch?v=E-eBBzWEpwE की मदद कर सकता है लेकिन गंभीरता से, ASCII का प्रभाव दुनिया में बहुत हानिकारक है, सहमत होना चाहिए कि यह निर्दिष्ट किया जाना चाहिए, और UTF- के लिए डिफ़ॉल्ट होना चाहिए 8
दावोस

50

रेक्स केर द्वारा उत्तर के समान, लेकिन अधिक सामान्य। पहले मैं एक सहायक कार्य का उपयोग करता हूं:

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

आदि।


39
मुझे गलत मत समझो, मुझे आपका कोड पसंद है और यह बहुत शैक्षिक है, लेकिन जितना अधिक मैं सरल समस्याओं के लिए ऐसे निर्माण देखता हूं, उतना ही यह मुझे पुरानी "हैलो वर्ल्ड" के बारे में याद दिलाता है: ariel.com.au/jokes/The_Eolutionolution_of_a_Programmer .html :-) (मेरे से +1 वोट)।
ग्रीनल्डमैन

4
यदि आप वन-लाइनर्स लिख रहे हैं, तो सभी मामलों में कुछ भी नहीं। यदि आप महत्वपूर्ण कार्यक्रम (रखरखाव और विकास के लिए एक निरंतर आवश्यकता के साथ बड़े) लिख रहे हैं, तो इस तरह की सोच सबसे तेजी से और खतरनाक किस्म के सॉफ़्टवेयर गुणवत्ता में गिरावट की ओर ले जाती है।
Randall Schulz

3
सभी को अभ्यास के कुछ स्तर तक "स्कैला आंखें" नहीं होती हैं - इस कोड का उदाहरण "बिगिनिंग" स्काला से आ रहा है - यह देखने में मजेदार है
asyncwait

asyncwait "शुरुआत" scala ... अब तक का सबसे विडंबनापूर्ण शीर्षक, ध्यान दें: मेरे पास पुस्तक है ... और अभी मैं इसे समझने लगा हूं..मुझे लगता है कि मैं "शुरुआत" से पहले एक कदम था: lol: D ........
user1050817

1
समस्या यहाँ स्काला ट्रिक्स कम है, लेकिन वाचालता और खराब शैली। मैंने इसे बहुत अधिक पठनीय में संपादित किया है। मेरे रिफ्लेक्टर के बाद यह सिर्फ 4 लाइनों (अच्छी तरह से, 4 आईडीई लाइन की लंबाई के साथ, 6 का उपयोग यहां स्क्रीन में फिट करने के लिए किया गया है)। IMHO यह अब बहुत अच्छा जवाब है।
samthebest

38

एक सरल जवाब:

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

1
@samthebest क्या आप उन पुस्तकालयों को अपने importसे जोड़ सकते हैं ?
डैनियल

1
जावा 7 के रूप में, इसके बजाय java.nio.file का उपयोग करें: def राइट टाइप करें (फ़ाइल: स्ट्रिंग, stringToWrite: स्ट्रिंग): यूनिट = {वैल लेखक = Files.newBufferedWriter (Paths.get (file)) try लेखक.write (stringToWrite) अंत में उपयोग करें। author.close ()}
ई शिंडलर

20

दूसरा उत्तर देते हुए, क्योंकि मेरे अन्य उत्तरों के संपादन जहां अस्वीकृत हुए।

यह सबसे संक्षिप्त और सरल उत्तर है (गैरेट हॉल के समान)

File("filename").writeAll("hello world")

यह Jus12 के समान है, लेकिन वर्बोसिटी के बिना और सही कोड शैली के साथ

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, न ही लैम्ब्डा और प्लेसहोल्डर सिंटैक्स के उपयोग पर ध्यान दें। बेहतर नामकरण पर भी ध्यान दें।


2
क्षमा करें, लेकिन आपका कोड कल्पनाशील है, यह implementedशर्त पूरी नहीं करता है । आप उस कोड का उपयोग नहीं कर सकते जो कार्यान्वित नहीं किया गया है। मेरा मतलब है कि आपको यह बताना होगा कि इसे कैसे खोजना है क्योंकि यह डिफ़ॉल्ट रूप से उपलब्ध नहीं है और अच्छी तरह से ज्ञात नहीं है।
वल

15

यहाँ स्कैला संकलक पुस्तकालय का उपयोग कर एक संक्षिप्त एक लाइनर है:

scala.tools.nsc.io.File("filename").writeAll("hello world")

वैकल्पिक रूप से, यदि आप जावा पुस्तकालयों का उपयोग करना चाहते हैं तो आप यह हैक कर सकते हैं:

Some(new PrintWriter("filename")).foreach{p => p.write("hello world"); p.close}

क्या आयात करता है? यानी फाइल कहां से आ रही है?
बेन हचिसन

स्काला संकलक पुस्तकालय।
गैरेट हॉल

3
अब व्यवहार्य नहीं (स्काला 2.11 में नहीं)
ब्रेंट फॉस्ट

1
तुम्हारी किस बारे में बोलने की इच्छा थी? scala.tools.nsc.io.File("/tmp/myFile.txt")स्कला 2.11.8 में काम करता है।

1
यह अब scala.reflect.io.File में है
कीथ नॉर्डस्ट्रॉम

13

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


यह बड़ी फ़ाइलों के लिए उपयुक्त क्यों नहीं है?
चेतन भसीन

2
@ChetanBhasin संभवत: क्योंकि यह फ़ाइल को स्ट्रीमिंग करने के बजाय एक नए बाइट सरणी में writeकॉपी करेगा contents, जिससे इसके शिखर पर contentsअकेले की तुलना में दोगुनी मेमोरी का उपयोग होगा ।
डैनियल वर्नर

10

दुर्भाग्य से शीर्ष उत्तर के लिए, स्काला-आईओ मर चुका है। यदि आपको किसी तृतीय-पक्ष निर्भरता का उपयोग करने में कोई आपत्ति नहीं है, तो मेरे 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")

इसमें फाइलों को लिखने , फाइलों में अपडाउन करने , फाइलों को ओवरराइट करने और कई अन्य उपयोगी / सामान्य ऑपरेशन के लिए वन-लाइनर्स हैं


इस अद्यतन के लिए धन्यवाद। Upvoted। अधिक दृश्यता के लिए मैंने आपके उत्तर को अपने ऊपर संदर्भित किया है।
वॉनक

7

एक माइक्रो लाइब्रेरी मैंने लिखी: https://github.com/pathikrit/better-files

file.appendLine("Hello", "World")

या

file << "Hello" << "\n" << "World"

यहाँ के रूप में अच्छी तरह से - यह सवाल शीर्ष हिट में से एक है जब googling कैसे स्कैला के साथ एक फ़ाइल लिखने के लिए - अब जब आपकी परियोजना बड़ी हो गई है, तो आप अपने उत्तर को थोड़ा विस्तारित करना चाह सकते हैं?
asac

6

शुरू Scala 2.13, मानक पुस्तकालय एक समर्पित संसाधन प्रबंधन उपयोगिता प्रदान करता है:Using :।

इसका उपयोग इस मामले में संसाधनों के साथ किया जा सकता है जैसे कि PrintWriterया BufferedWriterजो AutoCloseableफ़ाइल में लिखने के लिए विस्तारित होता है और, इससे कोई फर्क नहीं पड़ता कि संसाधन को बंद करें:

  • उदाहरण के लिए, java.ioएपी के साथ :

    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आपी के साथ :

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

6

2019 / सितंबर / 01 को अद्यतन

  • Scala 2.13 से शुरू करके, उपयोग करना पसंद करते हैं scala.util.Using
  • यदि कोड फेंक दिया गया तो finallyमूल बग जहां मूल Exceptionफेंक दिया जाएगा निगल जाएगाtryfinallyException

स्काला में आसानी से फ़ाइल लिखने के बारे में इन सभी उत्तरों की समीक्षा करने के बाद, और उनमें से कुछ काफी अच्छे हैं, मेरे पास तीन मुद्दे थे:

  1. में Jus12 के जवाब , का उपयोग करते हुए सहायक विधि के लिए currying के उपयोग स्काला / एफपी शुरुआती के लिए गैर स्पष्ट है
  2. निम्न स्तर की त्रुटियों को इनकैप्सुलेट करने की आवश्यकता है scala.util.Try
  3. जावा डेवलपर्स को स्काला / एफपी को नया दिखाने की आवश्यकता है कि कैसे निर्भर संसाधनों को ठीक से घोंसला बनाया जाए इसलिए closeविधि रिवर्स ऑर्डर में प्रत्येक आश्रित संसाधन पर की जाती है - नोट: रिवर्स ऑर्डर में निर्भर संसाधनों को बंद करना एक विफलता की घटना में शायद ही कभी समझा आवश्यकता है। java.lang.AutoCloseableविनिर्देश जो बहुत हानिकारक और मुश्किल पर आधारित होते हैं कीड़े और चलाने के समय विफलताओं को खोजने के लिए

शुरू करने से पहले, मेरा लक्ष्य निर्णायक नहीं है। यह आमतौर पर जावा से आने वाले स्काला / एफपी शुरुआती लोगों के लिए आसान समझ की सुविधा देता है। बहुत अंत में, मैं सभी बिट्स को एक साथ खींचूंगा, और फिर संक्षिप्तता बढ़ाऊंगा।

सबसे पहले, 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और इसे लिखता है a 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सामग्री को आसानी से प्राप्त करने के लिए एक सुविधाजनक विधि प्रदान करता है File, इस closeविधि का उपयोग Sourceअंतर्निहित JVM और फ़ाइल सिस्टम हैंडल को जारी करने के लिए किया जाना चाहिए । यदि ऐसा नहीं किया जाता है, तो संसाधन जारी नहीं किया जाता है जब तक कि जेवीएम जीसी (गारबेज कलेक्टर) Sourceअपने आप ही उदाहरण जारी करने के लिए चारों ओर न हो जाए । और फिर भी, केवल एक कमजोर जेवीएम गारंटी है finalizeविधि को जीसी द्वारा 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
      )
  )

उपरोक्त फ़ंक्शन का एक अद्यतन संस्करण एक अलग लेकिन संबंधित स्टैकऑवरफ़्लो प्रश्न के उत्तर के रूप में प्रदान किया गया है ।


अब, निकाले गए आयात के साथ सभी को एक साथ लाना (इतना आसान है कि दोनों एक्लिप्स 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
    )
  }

एक स्कैला / एफपी नौसिखिया के रूप में, मैंने उपरोक्त ज्ञान और समाधान अर्जित करने में कई घंटे (ज्यादातर सिर-खरोंच हताशा में) जलाए हैं। मुझे उम्मीद है कि यह अन्य स्कैला / एफपी न्यूबीज को इस विशेष सीखने की कूबड़ में तेजी से प्राप्त करने में मदद करता है।


2
अतुल्य अद्यतन। एकमात्र समस्या यह है कि अब आपके पास कोड की 100 पंक्तियाँ हैं, जिन्हें प्रतिस्थापित किया जा सकता है try-catch-finally। फिर भी अपने जुनून से प्यार करो।
ऑब्जर्वर

1
@ ऑबजर्वर मैं यह दावा करूंगा कि यह एक गलत बयान है। जिस पैटर्न का मैं वर्णन कर रहा हूं, वह वास्तव में बॉयलरप्लेट की मात्रा को कम कर रहा है, एक क्लाइंट को ऑटोक्लोसेबल्स को बंद करने के लिए उचित हैंडलिंग सुनिश्चित करने के लिए लिखना चाहिए, जबकि scala.util.Try का उपयोग करने के स्काला मुहावरेदार एफपी पैटर्न को भी सक्षम करना चाहिए। यदि आप उसी प्रभाव को प्राप्त करने का प्रयास करते हैं जो मैंने स्वयं कोशिश / कैच / अंत में ब्लॉक करके लिखा है, तो मुझे लगता है कि आप पाएंगे कि आप जितना कल्पना कर रहे हैं, उससे कहीं अधिक बॉयलरप्लेट के साथ आपको समाप्त होगा। तो, स्कैला फ़ंक्शन की 100 लाइनों में सभी बॉयलरप्लेट को आगे बढ़ाने में महत्वपूर्ण पठनीयता मूल्य है।
chaotic3quilibrium

1
खेद है कि अगर किसी भी तरह से आक्रामक लग रहा था। फिर भी, मेरा कहना यह है कि इस तरह के कोड की कोई आवश्यकता नहीं है, क्योंकि इसे बहुत अधिक सादगी के साथ गैर-कार्यात्मक दृष्टिकोण के माध्यम से प्राप्त किया जा सकता है। व्यक्तिगत रूप से, मैं कुछ अतिरिक्त जाँचों के साथ कोशिश करूँगा। यह अभी छोटा है। अगर मैं रैपर का उपयोग करना चाहता था, तो ApacheUtils सभी गंदे काम का उपयोग करने के लिए है। अधिक, सभी मानक रीडर / राइटर्स अंतर्निहित अंतर्निहित धाराओं को करते हैं ताकि आपके मल्टीपर्प की आवश्यकता न हो। पुनश्च: मैंने आपके प्रयासों को समर्थन देने के लिए अपना वोट माइनस एक से प्लस एक में बदल दिया है। तो, कृपया, मुझे एक बुरे इरादे में संदेह न करें।
ऑब्जर्वर

कोई अपराध नहीं हुआ।
chaotic3quilibrium

1
मैं आपकी बात समझता हूं। चर्चा के लिए धन्यवाद, मुझे इसके बारे में थोड़ा सोचना होगा। आपका दिन शुभ हो!
प्रेक्षक

3

यहाँ स्केलज़-स्ट्रीम का उपयोग करके फ़ाइल में कुछ पंक्तियाँ लिखने का एक उदाहरण दिया गया है

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

1

समथबेस्ट और उसके पहले योगदानकर्ताओं को पार करने के लिए, मैंने नामकरण और संक्षिप्तता में सुधार किया है:

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

यह "डक टाइपिंग" का उपयोग करता है जो प्रतिबिंब पर निर्भर करता है। कई संदर्भों के लिए, प्रतिबिंब के आधार पर एक गैर स्टार्टर है।
chaotic3quilibrium

1

कोई निर्भरता नहीं, त्रुटि से निपटने के साथ

  • मानक पुस्तकालय से विशेष रूप से विधियों का उपयोग करता है
  • यदि आवश्यक हो तो फ़ाइल के लिए निर्देशिका बनाता है
  • 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")
}

1

2019 अपडेट:

सारांश - जावा NIO (या Async के लिए NIO.2) अभी भी स्काला में समर्थित सबसे व्यापक फ़ाइल प्रसंस्करण समाधान है। निम्न कोड एक नई फ़ाइल के लिए कुछ पाठ बनाता और लिखता है:

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. जावा पुस्तकालयों को आयात करें: IO और NIO
  2. Pathअपने चुने हुए फ़ाइल नाम के साथ एक ऑब्जेक्ट बनाएं
  3. अपने पाठ को कनवर्ट करें जिसे आप किसी फ़ाइल में बाइट सरणी में सम्मिलित करना चाहते हैं
  4. एक स्ट्रीम के रूप में अपनी फ़ाइल प्राप्त करें: OutputStream
  5. अपने बाइट सरणी को अपने आउटपुट स्ट्रीम के writeफंक्शन में पास करें
  6. धारा बंद करो

1

इस उत्तर के समान , यहाँ एक उदाहरण है 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)

  }
}

0

यह लाइन किसी ऐरे या स्ट्रिंग से फाइल लिखने में मदद करती है।

 new PrintWriter(outputPath) { write(ArrayName.mkString("")); close }

0

यदि आप अपनी परियोजना में अक्का धाराएं हैं, तो यह एक लाइनर प्रदान करता है:

def writeToFile(p: Path, s: String)(implicit mat: Materializer): Unit = {
  Source.single(ByteString(s)).runWith(FileIO.toPath(p))
}

अक्का डॉक्स> फाइलिंग आईओ

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.