स्केल: एक स्टेटमेंट में फाइल करने के लिए स्ट्रिंग लिखें


144

स्काला में फ़ाइलों को पढ़ने के लिए, वहाँ है

Source.fromFile("file.txt").mkString

क्या फ़ाइल लिखने के लिए स्ट्रिंग लिखने का एक समान और संक्षिप्त तरीका है?

अधिकांश भाषाएं कुछ इस तरह का समर्थन करती हैं। मेरा पसंदीदा ग्रूवी है:

def f = new File("file.txt")
// Read
def s = f.text
// Write
f.text = "file contents"

मैं प्रोग्राम के लिए कोड का उपयोग एक पंक्ति से छोटे पृष्ठ तक कर सकता हूं। अपनी खुद की लाइब्रेरी का उपयोग करने से यहाँ कोई मतलब नहीं है। मैं एक आधुनिक भाषा की उम्मीद करता हूं कि मुझे किसी फाइल को सुविधाजनक तरीके से लिखने की अनुमति मिले।

इसके समान ही पोस्ट हैं, लेकिन वे मेरे सटीक प्रश्न का उत्तर नहीं देते हैं या पुराने स्काला संस्करणों पर केंद्रित हैं।

उदाहरण के लिए:


इस प्रश्न को देखें । मैं उच्चतम मूल्यांकित उत्तर से सहमत हूं - आपकी अपनी निजी लाइब्रेरी होना बेहतर है।
दोस्त

2
इस मामले में मैं सहमत नहीं हूं कि किसी को अपनी निजी लाइब्रेरी लिखना है। आमतौर पर, जब आप तदर्थ चीजों को करने के लिए कार्यक्रमों के छोटे टुकड़े लिख रहे होते हैं (हो सकता है कि मैं इसे केवल एक पृष्ठ स्कैला लिपि के रूप में या सिर्फ REPL में लिखना चाहता हूं)। फिर एक निजी पुस्तकालय तक पहुंचना एक दर्द बन जाता है।
smartnut007

असल में, लगता है कि इस बिंदु पर इसके लिए scala 2.9 में कुछ भी नहीं है। यकीन नहीं होता कि कैसे मैं इस सवाल को खुला रखूं।
smartnut007

1
यदि आप स्केल स्रोत कोड में java.io को खोजते हैं, तो आपको कई घटनाएं नहीं मिलेंगी, और आउटपुट संचालन के लिए भी कम, विशेष रूप से PrintWriter के लिए। इसलिए, जब तक स्काला-आईओ पुस्तकालय स्काला का आधिकारिक हिस्सा नहीं बन जाता, हमें शुद्ध जावा का उपयोग करना होगा, जैसा कि प्रतिमान द्वारा दिखाया गया है।
फीलो

हाँ, प्रोब को भी jalak7 IO सुधार के साथ संगत एक scala-io thats की आवश्यकता है।
smartnut007

जवाबों:


77

संक्षिप्त एक पंक्ति:

import java.io.PrintWriter
new PrintWriter("filename") { write("file contents"); close }

14
हालांकि यह दृष्टिकोण अच्छा लग रहा है, यह न तो अपवाद-सुरक्षित है और न ही एन्कोडिंग-सुरक्षित है। यदि अपवाद होता है write(), तो closeउसे कभी भी कॉल नहीं किया जाएगा, और फ़ाइल बंद नहीं होगी। PrintWriterडिफ़ॉल्ट सिस्टम एन्कोडिंग का भी उपयोग करता है, जो पोर्टेबिलिटी के लिए बहुत खराब है। और अंत में, यह दृष्टिकोण विशेष रूप से इस लाइन के लिए एक अलग वर्ग उत्पन्न करता है (हालांकि, यह देखते हुए कि स्काला पहले से ही एक साधारण कोड के लिए भी टन वर्ग उत्पन्न करता है, यह शायद ही अपने आप में एक दोष है)।
व्लादिमीर मतावेव

उपरोक्त टिप्पणी के अनुसार, जबकि यह एक लाइनर है, यह असुरक्षित है। यदि आप स्थान के आस-पास अधिक विकल्प चाहते हैं और / या इनपुट के बफरिंग के दौरान अधिक सुरक्षा चाहते हैं, तो इसका उत्तर देखें मैं सिर्फ एक समान थ्रेड पर पोस्ट किया गया हूं: stackoverflow.com/a/34277491/501113
chaotic3quilibrium

2
अस्थायी डिबग-लॉगिंग के लिए मैंने इस्तेमाल कियाnew PrintWriter(tmpFile) { try {write(debugmsg)} finally {close} }
रान्डेल व्हिटमैन

Stylistically यह शायद उपयोग करने के लिए बेहतर है close(), मुझे लगता है
केसी

यह दो पंक्तियाँ हैं और इन्हें आसानी से एक पंक्ति में बनाया जा सकता है:new java.io.PrintWriter("/tmp/hello") { write("file contents"); close }
फिल्लूमिनाटी

163

यह अजीब है कि किसी ने NIO.2 संचालन का सुझाव नहीं दिया था (जावा 7 के बाद से उपलब्ध):

import java.nio.file.{Paths, Files}
import java.nio.charset.StandardCharsets

Files.write(Paths.get("file.txt"), "file contents".getBytes(StandardCharsets.UTF_8))

मुझे लगता है कि यह अब तक का सबसे सरल और आसान और सबसे मुहावरेदार तरीका है, और इसके लिए जावा पर निर्भर किसी भी निर्भरता की आवश्यकता नहीं है।


यह किसी कारण से न्यूलाइन चरित्र की उपेक्षा करता है।
काकाजी

@ काकाजी, क्या आप विस्तार से बता सकते हैं? मैंने इसे नए सिरे से तार के साथ परीक्षण किया है, और यह पूरी तरह से काम करता है। यह सिर्फ कुछ भी फ़िल्टर नहीं कर सकता है - Files.write () बाइट को एक बूँद के रूप में लिखता है, इसकी सामग्री का विश्लेषण किए बिना। आखिरकार, कुछ बाइनरी डेटा में 0x0d बाइट का न्यूलाइन के अलावा अन्य महत्वपूर्ण अर्थ हो सकता है।
व्लादिमीर मतावेव

4
अतिरिक्त ध्यान दें: यदि आपके पास एक फ़ाइल है, तो पहला पैरामीटर प्राप्त करने के लिए बस '.toPath'।
एकुप्पी

1
यह एक अधिक औद्योगिक ग्रेड है (स्पष्ट चारसेट पसंद के कारण) लेकिन इसमें सादगी (और एक लाइनर ..) का अभाव है reflect.io.File.writeAll(contents)। क्यों? जब आप दो आयात विवरण शामिल करते हैं तो तीन लाइनें। हो सकता है कि IDE आपके लिए यह स्वचालित रूप से करता हो, लेकिन यदि REPL में यह उतना आसान नहीं है।
जवदाबा

3
@ जजदबा हम जेवीएम में हैं, आयात बहुत ज्यादा 'लाइनों' के रूप में नहीं गिनता है, खासकर क्योंकि विकल्प लगभग हमेशा एक नया पुस्तकालय निर्भरता जोड़ रहा है। वैसे भी, दूसरे तर्क के रूप में Files.writeभी स्वीकार करता है java.lang.Iterable, और हम इसे एक Scala से प्राप्त कर सकते हैं Iterable, अर्थात किसी भी संग्रह का उपयोग करते हुए, किसी भी प्रकार का संग्रह:import java.nio.file.{Files, Paths}; import scala.collection.JavaConverters.asJavaIterableConverter; val output = List("1", "2", "3"); Files.write(Paths.get("output.txt"), output.asJava)
Yawar

83

यहाँ प्रतिबिंबित .io.file का उपयोग कर एक संक्षिप्त लाइनर है, यह स्कैला 2.12 के साथ काम करता है:

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

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

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

1
+1 बढ़िया काम करता है। Some/ foreachकॉम्बो थोड़ा अजीब है, लेकिन यह कोई ट्राई / कैच के लाभ / अंत में साथ आता है।
ब्रेंट फस्ट

3
यदि लेखन अपवाद को फेंकता है, तो यदि आप अपवाद से उबरने और फिर से फ़ाइल को पढ़ने / लिखने की योजना बनाते हैं, तो आप फ़ाइल को बंद करना चाहते हैं। सौभाग्य से स्काला ऐसा करने के लिए वन-लाइनर्स प्रदान करता है।
गैरेट हॉल

25
यह अनुशंसित नहीं है क्योंकि scala.tools.nsc.io पैकेज सार्वजनिक API का हिस्सा नहीं है, लेकिन संकलक द्वारा उपयोग किया जाता है।
गियोवन्नी बोटा

3
Some/ foreachहैक वास्तव में क्यों कई लोगों को अपठनीय कोड यह उत्पादन करने के लिए हैकर्स का कारण बनता है के लिए स्काला नफरत है।
एरिक कप्लून

3
scala.tootls.nsc.io.Fileके लिए एक उपनाम है reflect.io.File। अभी भी आंतरिक एपीआई, लेकिन कम से कम थोड़ा छोटा है।
कोस्टाजा

41

यदि आप ग्रूवी सिंटैक्स पसंद करते हैं, तो आप इसे स्काला में लाने के लिए पिंप-माय-लाइब्रेरी डिज़ाइन पैटर्न का उपयोग कर सकते हैं :

import java.io._
import scala.io._

class RichFile( file: File ) {

  def text = Source.fromFile( file )(Codec.UTF8).mkString

  def text_=( s: String ) {
    val out = new PrintWriter( file , "UTF-8")
    try{ out.print( s ) }
    finally{ out.close }
  }
}

object RichFile {

  implicit def enrichFile( file: File ) = new RichFile( file )

}

यह उम्मीद के मुताबिक काम करेगा:

scala> import RichFile.enrichFile
import RichFile.enrichFile

scala> val f = new File("/tmp/example.txt")
f: java.io.File = /tmp/example.txt

scala> f.text = "hello world"

scala> f.text
res1: String = 
"hello world

2
आप कभी भी Source.fromFile पर दिए गए इंस्टेंस को बंद न करें जिसका अर्थ है कि संसाधन बंद नहीं है जब तक कि वह GCed (कचरा एकत्र) नहीं है। और आपका PrintWriter बफ़र नहीं किया गया है, इसलिए यह 8 बाइट्स के छोटे JVM डिफ़ॉल्ट बफर का उपयोग कर रहा है, संभवतः अपने IO को धीमा कर रहा है। मैंने इन मुद्दों से निपटने वाले एक समान सूत्र पर एक उत्तर दिया है: stackoverflow.com/a/34277491/501113
chaotic3quilibrium

1
तुम सही हो। लेकिन मैंने यहां जो समाधान दिया, वह छोटे आईओ के साथ अल्पकालिक कार्यक्रमों के लिए अच्छी तरह से काम करता है। मैं इसे सर्वर प्रक्रिया या बड़े डेटा (अंगूठे के एक नियम के रूप में, 500 एमबी से अधिक) के लिए अनुशंसित नहीं करता हूं।
प्रतिमान

23
import sys.process._
"echo hello world" #> new java.io.File("/tmp/example.txt") !

यह मेरे लिए REPL में काम नहीं करता है। कोई ग़लती नहीं है, लेकिन अगर मैं /tmp/example.txt को देखता हूं तो वहाँ कोई नहीं है।
उपयोगकर्ता अज्ञात

@user अज्ञात, 'लापता' के लिए क्षमा करें! ' आदेश के अंत में, अब ठीक किया गया।
xiefei

आश्चर्यजनक! अब जब यह काम करता है, तो मैं जानना चाहूंगा कि क्यों। क्या है #>, क्या करता !है?
उपयोगकर्ता अज्ञात

10
यह समाधान पोर्टेबल नहीं है ! केवल * निक्स सिस्टम में काम करता है।
गियोवन्नी बोटा

2
यह मनमाना तार लिखने के लिए काम नहीं करेगा। यह केवल छोटे तारों के लिए काम करेगा जिसे आप कमांड लाइन echoटूल के तर्क के रूप में पारित कर सकते हैं ।
रिच

15

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

file.write("Hi!")

या

file << "Hi!"

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

12

आप Apache File Utils का उपयोग आसानी से कर सकते हैं । फ़ंक्शन को देखें writeStringToFile। हम अपनी परियोजनाओं में इस पुस्तकालय का उपयोग करते हैं।


3
मैं भी हर समय इसका इस्तेमाल करता हूं। यदि आप इस प्रश्न को ध्यान से पढ़ते हैं, तो मैं पहले ही यह जान चुका हूँ कि मैं पुस्तकालय का उपयोग क्यों नहीं करना चाहता।
smartnut007

लाइब्रेरी का उपयोग किए बिना, मैंने एक समाधान बनाया है जो पढ़ने / लिखने के दौरान अपवादों को संभालता है और जावा पुस्तकालयों द्वारा प्रदान किए गए छोटे बफर चूक से परे होने में सक्षम है: stackoverflow.com/a/34277491/501113
chaotic3quilibrium

7

एक में यह प्रारूप भी है, जो संक्षिप्त है और अंतर्निहित पुस्तकालय को खूबसूरती से लिखा गया है (स्रोत कोड देखें):

import scalax.io.Codec
import scalax.io.JavaConverters._

implicit val codec = Codec.UTF8

new java.io.File("hi-file.txt").asOutput.write("I'm a hi file! ... Really!")

7

यह संक्षिप्त है, मुझे लगता है:

scala> import java.io._
import java.io._

scala> val w = new BufferedWriter(new FileWriter("output.txt"))
w: java.io.BufferedWriter = java.io.BufferedWriter@44ba4f

scala> w.write("Alice\r\nBob\r\nCharlie\r\n")

scala> w.close()

4
पर्याप्त रूप से उचित है, लेकिन यह "संक्षिप्त रूप से" "एक कथन" के रूप में वर्गीकृत नहीं होता है: पी
एरिक कप्लून

यह कोड जावा की कथित समस्याओं के बारे में बताता है। दुर्भाग्य से स्काला IO को महत्वपूर्ण नहीं मानता, इसलिए मानक पुस्तकालय में एक भी शामिल नहीं है।
क्रिस

जवाब नए FileWriter के साथ एक अनाथ संसाधन मुद्दों को छुपाता है। यदि नया FileWriter सफल हो जाता है, लेकिन नया BufferedWriter विफल हो जाता है, तो FileWriter का उदाहरण फिर कभी नहीं देखा जाता है और GCed (गारबेज कलेक्टेड) ​​तक खुला रहता है, और तब भी बंद नहीं हो सकता (जिस तरह से JVM में काम की गारंटी देता है)। मैंने एक ऐसे ही प्रश्न का उत्तर लिखा है जो इन मुद्दों को संबोधित करता है: stackoverflow.com/a/34277491/501113
chaotic3quilibrium

2

आप इसे जावा और स्काला लाइब्रेरी के मिश्रण से कर सकते हैं। चरित्र एन्कोडिंग पर आपका पूर्ण नियंत्रण होगा। लेकिन दुर्भाग्य से, फ़ाइल हैंडल ठीक से बंद नहीं होगा।

scala> import java.io.ByteArrayInputStream
import java.io.ByteArrayInputStream

scala> import java.io.FileOutputStream
import java.io.FileOutputStream

scala> BasicIO.transferFully(new ByteArrayInputStream("test".getBytes("UTF-8")), new FileOutputStream("test.txt"))

आपके पास अपने कोड में एक अनाथ संसाधन उदाहरण समस्या है। चूँकि आप अपने कॉल से पहले के इंस्टेंस को कैप्चर नहीं कर रहे हैं, यदि या तो आपके द्वारा कॉल की जा रही विधि से पहले कोई अपवाद फेंकता है, तो पैरामीटर को पारित कर दिया गया है, जो संसाधनों को सफलतापूर्वक इंस्टेंट किया गया है, जब तक कि सभी को GCed (कचरा एकत्र) तक बंद नहीं किया जाएगा, और यहां तक ​​कि हो सकता है कि जीसी के काम करने के तरीके के कारण ऐसा न हो। मैंने एक ऐसे ही प्रश्न का उत्तर लिखा है जो इन मुद्दों को संबोधित करता है: stackoverflow.com/a/34277491/501113
chaotic3quilibrium

1
आप सही हैं और आपका समाधान काफी अच्छा है। लेकिन यहाँ आवश्यकता इसे एक पंक्ति में कर रही थी। और जब आप ध्यान से पढ़ते हैं, तो मैंने अपने उत्तर में संसाधन रिसाव का उल्लेख एक सीमा के रूप में किया है जो इस आवश्यकता के साथ और मेरे दृष्टिकोण के साथ आता है। आपका समाधान अच्छा है, लेकिन उस एक पंक्ति की आवश्यकता से मेल नहीं खाएगा।
stefan.schwetschke

2

मुझे पता है कि यह एक पंक्ति नहीं है, लेकिन यह सुरक्षा के मुद्दों को हल करता है जहां तक ​​मैं बता सकता हूं;

// This possibly creates a FileWriter, but maybe not
val writer = Try(new FileWriter(new File("filename")))
// If it did, we use it to write the data and return it again
// If it didn't we skip the map and print the exception and return the original, just in-case it was actually .write() that failed
// Then we close the file
writer.map(w => {w.write("data"); w}).recoverWith{case e => {e.printStackTrace(); writer}}.map(_.close)

यदि आप अपवाद हैंडलिंग के बारे में परवाह नहीं करते हैं तो आप लिख सकते हैं

writer.map(w => {w.writer("data"); w}).recoverWith{case _ => writer}.map(_.close)

1

अद्यतन: मैंने तब से एक अधिक प्रभावी समाधान बनाया है जिस पर मैंने यहां विस्तार किया है: https://stackoverflow.com/a/34277491/501113

मैं खुद को ग्रहण के लिए स्काला आईडीई के भीतर स्काला वर्कशीट में अधिक से अधिक काम कर रहा हूं (और मुझे विश्वास है कि इंटेलीज आईडीईए में कुछ समान है)। वैसे भी, मुझे कुछ सामग्री को आउटपुट करने के लिए एक-लाइनर करने में सक्षम होने की आवश्यकता है क्योंकि मुझे "आउटपुट सीमा कटौती सीमा से अधिक है" मिलता है। संदेश अगर मैं कुछ भी महत्वपूर्ण कर रहा हूँ, विशेष रूप से स्काला संग्रह के साथ।

मैं इसे सरल बनाने के लिए प्रत्येक नए स्काला वर्कशीट के शीर्ष में एक-लाइनर के साथ आया (और इसलिए मुझे बहुत सरल आवश्यकता के लिए पूरे बाहरी पुस्तकालय आयात अभ्यास करने की आवश्यकता नहीं है)। यदि आप एक स्टिकलर हैं और ध्यान दें कि यह तकनीकी रूप से दो लाइनें हैं, तो यह केवल इस फोरम में इसे और अधिक पठनीय बनाने के लिए है। यह मेरी स्काला वर्कशीट की एकल पंक्ति है।

def printToFile(content: String, location: String = "C:/Users/jtdoe/Desktop/WorkSheet.txt") =
  Some(new java.io.PrintWriter(location)).foreach{f => try{f.write(content)}finally{f.close}}

और उपयोग बस है:

printToFile("A fancy test string\ncontaining newlines\nOMG!\n")

यह मुझे वैकल्पिक रूप से फ़ाइल नाम प्रदान करने की अनुमति देता है जो मुझे डिफ़ॉल्ट से परे अतिरिक्त फ़ाइलों को करना चाहिए (जो कि हर बार विधि को पूरी तरह से फ़ाइल को अधिलेखित करता है)।

तो, दूसरा उपयोग बस है:

printToFile("A fancy test string\ncontaining newlines\nOMG!\n", "C:/Users/jtdoe/Desktop/WorkSheet.txt")

का आनंद लें!


1

अम्मोनाइट ऑप्स लाइब्रेरी का उपयोग करें । वाक्यविन्यास बहुत कम है, लेकिन लाइब्रेरी की चौड़ाई लगभग उतनी ही विस्तृत है, जितना कि शेल जैसी भाषा में स्क्रिप्टिंग भाषा में इस तरह के कार्य के प्रयास से किसी को क्या उम्मीद होगी।

मैं जिस पेज से जुड़ा था, वह कई ऑपरेशन दिखाता है जो लाइब्रेरी के साथ कर सकते हैं, लेकिन इस सवाल का जवाब देने के लिए, यह एक फ़ाइल लिखने का एक उदाहरण है

import ammonite.ops._
write(pwd/'"file.txt", "file contents")

-1

अर्धविराम के जादू के माध्यम से, आप एक-लाइनर की तरह कुछ भी बना सकते हैं।

import java.io.PrintWriter
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.charset.StandardCharsets
import java.nio.file.StandardOpenOption
val outfile = java.io.File.createTempFile("", "").getPath
val outstream = new PrintWriter(Files.newBufferedWriter(Paths.get(outfile)
  , StandardCharsets.UTF_8
  , StandardOpenOption.WRITE)); outstream.println("content"); outstream.flush(); outstream.close()

यहां कोई तर्क नहीं। मैंने फैसला किया कि मुझे यह याद न रखने की ज़रूरत है कि कौन से एपीआई को मुझे अपने जीवन का हिस्सा फ्लश करने की आवश्यकता है, इसलिए मैं हमेशा ऐसा करता हूं।
आयन फ्रीमैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.