Kotlin में, मैंने एक इनपुट स्ट्रिंग की पूरी सामग्री को स्ट्रिंग में कैसे पढ़ा?


105

मैंने हाल ही InputStreamमें कोटलिन में एक स्ट्रिंग की पूरी सामग्री को पढ़ने के लिए कोड देखा , जैसे:

// input is of type InputStream
val baos = ByteArrayOutputStream()
input.use { it.copyTo(baos) }
val inputAsString = baos.toString()

और भी:

val reader = BufferedReader(InputStreamReader(input))
try {
    val results = StringBuilder()
    while (true) { 
        val line = reader.readLine()
        if (line == null) break
        results.append(line) 
    }
    val inputAsString = results.toString()
} finally {
    reader.close()
}

और यह भी कि यह ऑटो बंद होने के बाद से चिकना दिखता है InputStream:

val inputString = BufferedReader(InputStreamReader(input)).useLines { lines ->
    val results = StringBuilder()
    lines.forEach { results.append(it) }
    results.toString()
}

या उस पर थोड़ा बदलाव:

val results = StringBuilder()
BufferedReader(InputStreamReader(input)).forEachLine { results.append(it) }
val resultsAsString = results.toString()   

फिर यह कार्यात्मक गुना चीज़:

val inputString = input.bufferedReader().useLines { lines ->
    lines.fold(StringBuilder()) { buff, line -> buff.append(line) }.toString()
}

या एक बुरी भिन्नता जो बंद नहीं होती है InputStream:

val inputString = BufferedReader(InputStreamReader(input))
        .lineSequence()
        .fold(StringBuilder()) { buff, line -> buff.append(line) }
        .toString()

लेकिन वे सभी क्लूनी हैं और मैं उसी के नए और अलग-अलग संस्करण खोजता रहता हूं ... और उनमें से कुछ कभी बंद भी नहीं होते हैं InputStream। नॉन-क्लंकी (मुहावरेदार) तरीका क्या है पढ़ने के लिए InputStream?

नोट: यह प्रश्न जानबूझकर लिखा गया है और लेखक द्वारा ( स्व-उत्तर वाले प्रश्न ) उत्तर दिया गया है , ताकि आमतौर पर पूछे जाने वाले कोटलिन विषयों के मुहावरेदार उत्तर एसओ में मौजूद हों।

जवाबों:


216

कोटलिन के पास इस उद्देश्य के लिए एक विशिष्ट एक्सटेंशन है।

सबसे सरल:

val inputAsString = input.bufferedReader().use { it.readText() }  // defaults to UTF-8

और इस उदाहरण में आप के बीच bufferedReader()या बस तय कर सकते हैं reader()। फ़ंक्शन के लिए कॉल Closeable.use()लैम्बडा के निष्पादन के अंत में इनपुट को स्वचालित रूप से बंद कर देगा।

आगे की पढाई:

यदि आप इस प्रकार का काम करते हैं, तो आप इसे विस्तार समारोह के रूप में लिख सकते हैं:

fun InputStream.readTextAndClose(charset: Charset = Charsets.UTF_8): String {
    return this.bufferedReader(charset).use { it.readText() }
}

जिसे तब आप आसानी से कॉल कर सकते हैं:

val inputAsString = input.readTextAndClose()  // defaults to UTF-8

एक साइड नोट पर, सभी कोटलिन एक्सटेंशन फ़ंक्शन जिन्हें charsetपहले से डिफ़ॉल्ट जानने की आवश्यकता होती है UTF-8, इसलिए यदि आपको एक अलग एन्कोडिंग की आवश्यकता होती है, तो आपको कॉल के लिए कोड को समायोजित करना होगा ताकि एन्कोडिंग शामिल हो reader(charset)या bufferedReader(charset)

चेतावनी: आप ऐसे उदाहरण देख सकते हैं जो छोटे हैं:

val inputAsString = input.reader().readText() 

लेकिन ये धारा को बंद नहीं करते हैं । सुनिश्चित करें कि आप उन सभी IO फ़ंक्शंस के लिए API दस्तावेज़ीकरण की जाँच करते हैं, जिनका उपयोग आप सुनिश्चित करते हैं कि कौन से करीबी और कौन से नहीं। आमतौर पर अगर वे शब्द शामिल करते हैं use(जैसे कि ) useLines()या use()उसके बाद धारा को बंद कर दें। एक अपवाद यह है कि File.readText()इससे अलग है कि Reader.readText()पूर्व कुछ भी खुला नहीं छोड़ता है और बाद में वास्तव में एक स्पष्ट करीबी की आवश्यकता होती है।

इसे भी देखें: कोटलिन IO संबंधित विस्तार कार्य


1
मुझे लगता है कि "readText" आपके द्वारा प्रस्तावित एक्सटेंशन फ़ंक्शन के लिए "useText" से बेहतर नाम होगा। जब मैं "useText" पढ़ा है कि मैं एक समारोह उम्मीद useया useLinesजो क्या "पुराना" किया जा रहा है पर एक ब्लॉक समारोह निष्पादित करता है। उदाहरण के inputStream.useText { text -> ... }लिए, जब मैं "readText" पढ़ता हूं, तो मैं एक ऐसे फ़ंक्शन की उम्मीद करता हूं जो पाठ को लौटाता है val inputAsString = inputStream.readText():।
mfulton26

यह सच है, लेकिन रीडटेक्स्ट में पहले से ही गलत अर्थ है, इसलिए यह संकेत करना चाहता था useकि यह उस संबंध में कार्यों की तरह अधिक था । कम से कम इस प्रश्नोत्तर के संदर्भ में। शायद एक नई क्रिया मिल सकती है ...
जैसन मिनर्ड

3
@ mfulton26 मैं readTextAndClose()इस उदाहरण के साथ गया readText()था कि बंद न करने के पैटर्न के साथ संघर्ष से बचने के लिए , और useपैटर्न के साथ एक लैंबडा चाहते हैं, क्योंकि मैं एक नया stdlib फ़ंक्शन शुरू करने की कोशिश नहीं कर रहा हूं जो मैं उपयोग करने के बारे में एक बिंदु बनाने से अधिक नहीं करना चाहता हूं भविष्य के श्रम को बचाने के लिए विस्तार।
जैसन मिनार्ड

@JaysonMinard आप जवाब के लिए इसे चिह्नित क्यों नहीं करते? हालांकि यह बहुत अच्छा है :-)
piotrek1543

2

एक उदाहरण जो एक इनपुटस्ट्रीम की सामग्री को एक स्ट्रिंग में पढ़ता है

import java.io.File
import java.io.InputStream
import java.nio.charset.Charset

fun main(args: Array<String>) {
    val file = File("input"+File.separator+"contents.txt")
    var ins:InputStream = file.inputStream()
    var content = ins.readBytes().toString(Charset.defaultCharset())
    println(content)
}

संदर्भ के लिए - कोटलिन फ़ाइल पढ़ें


1
आपके उदाहरण में दोष हैं: 1) क्रॉस-प्लेटफ़ॉर्म पथ के लिए आपको Paths.get()विधि का उपयोग करना चाहिए । 2) धाराओं के लिए - प्रयास-संसाधन सुविधा (कोटलिन में .use {})
एवगेनी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.