Scala में एक InputStream को String में बदलने का मुहावरेदार तरीका


111

मेरे पास एक आसान कार्य है जो मैंने जावा में उपयोग किया है एक इनपुटस्ट्रीम को एक स्ट्रिंग में परिवर्तित करने के लिए। यहाँ स्काला का सीधा अनुवाद है:

  def inputStreamToString(is: InputStream) = {
    val rd: BufferedReader = new BufferedReader(new InputStreamReader(is, "UTF-8")) 
    val builder = new StringBuilder()    
    try {
      var line = rd.readLine 
      while (line != null) { 
        builder.append(line + "\n")
        line = rd.readLine
      }
    } finally {
      rd.close
    }
    builder.toString
  }

क्या स्कैला में ऐसा करना एक मुहावरेदार तरीका है?

जवाबों:


197

स्काला के लिए = = 2.11

scala.io.Source.fromInputStream(is).mkString

स्काला के लिए <2.11:

scala.io.Source.fromInputStream(is).getLines().mkString("\n")

बहुत ज्यादा एक ही बात करता है। निश्चित नहीं है कि आप लाइनें क्यों प्राप्त करना चाहते हैं और फिर उन सभी को वापस एक साथ गोंद करें, हालांकि। यदि आप स्ट्रीम के नॉनब्लॉकिंग को मान सकते हैं, तो आप बस उपयोग कर सकते .availableहैं, पूरी चीज़ को बाइट सरणी में पढ़ सकते हैं, और इसके बाद सीधे एक स्ट्रिंग बना सकते हैं।


2
एक संभावित कारण, कि मैंने खुद का उपयोग किया है, विभिन्न ऑपरेटिंग सिस्टम पर लाइन अंत को सामान्य करना है।
केविन राइट

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

समाधान बहुत सुरक्षित नहीं है क्योंकि यह गेटलाइन () का उपयोग करता है; क्या होगा यदि इनपुट स्ट्रीम में कोई "नई लाइन" वर्ण नहीं है? तब सारी बात ब्लॉक हो जाती है
पॉल सबौ

काफी बुरा समाधान। क्या होगा यदि इनपुटस्ट्रीम में डॉस लाइन-एंडिंग (\ r \ n) शामिल हो। इस विधि द्वारा इन्हें हटा दिया जाएगा। इसके अलावा, हालांकि mkString एक बफर का उपयोग करता है, यह सबसे निश्चित रूप से वर्णों के ब्लॉक को पढ़ने के लिए तेज़ होगा।
दिब्बीकेन

1
@RexKerr क्या आप "प्रदर्शन बग" को इंगित कर सकते हैं जिसका आपने अपने उत्तर में उल्लेख किया है। मैंने कुछ बुनियादी टेस्टकेस के साथ दोनों संस्करणों का परीक्षण किया और किसी भी मुद्दे पर नहीं मारा।
साहिल सरीन

74

Source.fromInputStream(is).mkString("") विलेख भी करेंगे .....


अच्छी बात; स्रोत कुछ ऐसा बनाता है जो विस्तारित होता है Iterator[Char]
रेक्स केर

8
इस तरह की बात करते समय चरित्र एन्कोडिंग को निर्दिष्ट करना भी आम तौर पर अच्छा अभ्यास है। उस अंत तक: Source.fromInputStream(is)(Codec.UTF8).mkString
कॉनर डॉयल

यह क्रिया है, लेकिन यह धारा को बंद नहीं करता है, जबकि मूल जावा कोड ने किया था।
रिच

@ रीच, fromInputStream()धारा को बंद करने के लिए प्रकट होता है, कम से कम स्काला 2.11 में।
jaco0646

2
@ jaco0646 - यह धारा को बंद नहीं करता है। मैंने अभी-अभी परीक्षण किया है। यहाँ डेमो कोड है जो इसे साबित करता है: gist.github.com/RichardBradley/bcd1a5e61fcc83e4e59f8b9b0bc2301c
रिच

13

ऐसा करने का तेज़ तरीका:

    private def inputStreamToString(is: InputStream) = {
        val inputStreamReader = new InputStreamReader(is)
        val bufferedReader = new BufferedReader(inputStreamReader)
        Iterator continually bufferedReader.readLine takeWhile (_ != null) mkString
    }

"और तेज"? लेकिन इसने मुझे यह उत्तर प्रदान किया कि कैसे करना है जब मेरे पास सिर्फ एक है Readerऔर एक नहीं है InputStream
बीपडॉग

3
बस पहली पंक्ति को छोड़ें, और inputStreamReaderविधि को पास करें।
कामिल लेलोनेक

1
यह संभवतः स्कैला 2.io.7 से स्कैला से अधिक परिमाण का एक क्रम है। 2.11.7। मैंने इसके बारे में वास्तव में एक बुनियादी बेंचमार्क लिखा था और ज्यादातर समय, यह बड़ी फ़ाइलों के लिए लगभग 5% तेज था (परीक्षण ~ ~ 35 एमबी पाठ फ़ाइल था) सभी तरह से छोटी फ़ाइलों के लिए 2,800% तेजी से (परीक्षण ~ 30 KB) था ।
कॉलिन डीन

2
सुंदर। एक सुंदर समाधान के लिए संघर्ष कर रहा है जिसमें से बड़े इनपुट पढ़ रहे हैं Runtime.exec()। यह यह नाखून।
पावेल लेचेव

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