IOUtils.toString (InputStream) के लिए अमरूद बराबर


106

Apache Commons IO में एक स्ट्रिंग को पढ़ने के लिए एक अच्छी सुविधा विधि IOUtils.toString () है InputStream

चूंकि मैं अपाचे कॉमन्स से और अमरूद से दूर जाने की कोशिश कर रहा हूं : क्या अमरूद में एक बराबर है? मैंने com.google.common.ioपैकेज में सभी वर्गों को देखा और मुझे कुछ भी सरल नहीं लगा।

संपादित करें: मैं चार्ट के साथ मुद्दों को समझता हूं और उनकी सराहना करता हूं। यह सिर्फ इतना होता है कि मुझे पता है कि मेरे सभी स्रोत ASCII (हाँ, ASCII, ANSI आदि) में नहीं हैं, इसलिए इस मामले में, एन्कोडिंग मेरे लिए कोई समस्या नहीं है।


2
चारसेट्स के बारे में: एक लाइब्रेरी के लिए यह अभी भी अच्छा है कि आपको यह निर्दिष्ट करने की आवश्यकता है कि आप जानते हैं कि आप किस प्रकार के साथ काम कर रहे हैं (जैसे Charsets.US_ASCII) आपको कहने की बजाय "एह, जो भी मैं अनुमान लगाता हूं?" जो सभी लोगों को करने में खुशी होती है। खासतौर से चूंकि जावा एक डिफ़ॉल्ट का उपयोग नहीं करता है जो समझ में आता है, जैसे यूटीएफ -8।
कॉलिनडी

मुझे पता है। इसलिए मैं अपने जवाब में डिफ़ॉल्ट संस्करण के रूप में UTF-8 का उपयोग कर रहा हूं।
सीन पैट्रिक फ्लोयड

डॉक्स भी देखें: code.google.com/p/guava-lbooks/wiki/IOExplained
वडज़िम

@Vadzim उन डॉक्स का अस्तित्व नहीं था जब यह प्रश्न :-)
सीन पैट्रिक फ्लोयड

जवाबों:


85

आपने कैलम के उत्तर पर अपनी टिप्पणी में कहा कि आप उपयोग करने जा रहे थे

CharStreams.toString(new InputStreamReader(supplier.get(), Charsets.UTF_8))

यह कोड समस्याग्रस्त है क्योंकि अधिभार CharStreams.toString(Readable)बताता है:

बंद नहीं करता है Readable

इसका मतलब यह है कि आपका InputStreamReader, और इसके द्वारा InputStreamलौटाए गए एक्सटेंशन के द्वारा supplier.get(), यह कोड पूरा होने के बाद बंद नहीं होगा।

यदि, दूसरी ओर, आप इस तथ्य का लाभ उठाते हैं कि आप पहले से ही एक ( InputSupplier<InputStream>और अधिभार का उपयोग करते हैं CharStreams.toString(InputSupplier<R extends Readable & Closeable>) दिखाई देते हैं , तो toStringविधि आपके लिए निर्माण और समापन दोनों को संभाल लेगी Reader

यह वही है जो जॉन स्कीट ने सुझाव दिया था, सिवाय इसके कि वास्तव में कोई भी अधिभार नहीं है CharStreams.newReaderSupplierजो एक InputStreamइनपुट के रूप में लेता है ... आपको इसे देना होगा InputSupplier:

InputSupplier<? extends InputStream> supplier = ...
InputSupplier<InputStreamReader> readerSupplier = 
    CharStreams.newReaderSupplier(supplier, Charsets.UTF_8);

// InputStream and Reader are both created and closed in this single call
String text = CharStreams.toString(readerSupplier);

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

संपादित करें: व्यक्तिगत रूप से, मुझे निम्नलिखित मिलते हैं (जो है कि मैं वास्तव में इसे कैसे लिखूंगा, बस ऊपर दिए गए कोड में चरणों को तोड़ रहा था):

String text = CharStreams.toString(
    CharStreams.newReaderSupplier(supplier, Charsets.UTF_8));

होने के लिए अब तक इस से वर्बोज़ कम:

String text;
InputStreamReader reader = new InputStreamReader(supplier.get(), 
    Charsets.UTF_8);
boolean threw = true;
try {
  text = CharStreams.toString(reader);
  threw = false;
}
finally {
  Closeables.close(reader, threw);
}

कौन सा कम या ज्यादा है यह आपको स्वयं ठीक से संभालने के लिए लिखना होगा।


संपादित करें: फ़रवरी २०१४

InputSupplierऔर OutputSupplierउन्हें इस्तेमाल करने वाले तरीकों को अमरूद 16.0 में चित्रित किया गया है। उनकी प्रतिस्थापन कर रहे हैं ByteSource, CharSource, ByteSinkऔर CharSink। दिया गयाByteSource , अब आप इसकी सामग्री Stringइस प्रकार प्राप्त कर सकते हैं :

ByteSource source = ...
String text = source.asCharSource(Charsets.UTF_8).read();

महान जानकारी (+1) के लिए धन्यवाद। लेकिन यह बहुत क्रिया है। मुझे लगता है कि Closeables.closeQuietly () के साथ स्वीकृत उत्तर का संयोजन आसान है।
शॉन पैट्रिक फ्लोयड

@CollinD: मैंने अपने एक उत्तर में आपकी विधि का उपयोग किया है। कृपया कोड पर एक नज़र डालें और मुझे बताएं कि क्या यह इनपुटसुप्लाइयर का उपयोग करने का सही तरीका है।
एमिल

1
@ColinD, अगर इनपुटस्ट्रीम doPost सर्वलेट के अंदर से आ रहा है, तो क्या इसे बंद करने का कोई मतलब है? (या इसे बंद करने के बारे में चिंता करना)
ब्लेंकमैन

CharStreams.toString (InputSupplier) अब पदावनत हो गया है। मैंने एक CharSource बनाया (एक ByteSource से asCharSource का उपयोग करके) फिर डॉक्स सुझाव के रूप में इसके स्ट्रींग का उपयोग किया।
जॉन लेहमैन

4
@ TedM.Young: यदि आपके पास सब कुछ है InputStream, और आप इसे एक के रूप में प्राप्त करना चाहते हैं String, CharStreams.toString(new InputStreamReader(inputStream, charset))तो जाने का रास्ता है। ByteSourceऔर CharSourceविशेष रूप से ऐसे मामलों के लिए जहां आपके पास कुछ ऐसा है जो InputStreamएस या Readerएस के स्रोत के रूप में कार्य कर सकता है ।
कॉलिनड

56

यदि आपको मिल गया है Readableतो आप उपयोग कर सकते हैं CharStreams.toString(Readable)। तो आप शायद निम्नलिखित कर सकते हैं:

String string = CharStreams.toString( new InputStreamReader( inputStream, "UTF-8" ) );

आपको एक वर्ण सेट निर्दिष्ट करने के लिए मजबूर करता है, जो मुझे लगता है कि आपको वैसे भी करना चाहिए।


4
वास्तव में, मैं आपके और जॉन स्कीट के उत्तरों के संयोजन का उपयोग करूंगा: `CharStreams.toString (नया InputStreamReader (supplier.get), Charsets.UTF_8))`
शॉन पैट्रिक

हां, विकल्प गठबंधन करने के बहुत सारे तरीके!
कलुम

10
@SPFloyd: यदि आपके पास एक InputSupplier<InputStream>आई- फ़ोन है, तो CharStreams.newReaderSupplier(supplier, Charsets.UTF_8)इसके बजाय मैं दृढ़ता से उपयोग करने की सलाह दूंगा new InputStreamReader। कारण यह है कि जब दिया जाता है InputStreamReader, toStringतो वह बंद नहीं होगा Reader(और इस प्रकार अंतर्निहित धारा नहीं!)। एक का उपयोग करके InputSupplierके लिए Reader, toStringविधि को बंद संभाल लेंगे Readerआप के लिए।
कॉलिनडी

17

अद्यतन : पीछे मुड़कर, मुझे अपना पुराना समाधान पसंद नहीं है। इसके अलावा यह अब 2013 है और जावा 7 के लिए अब बेहतर विकल्प उपलब्ध हैं। तो यहाँ मैं अब क्या उपयोग है:

InputStream fis = ...;
String text;
try (  InputStreamReader reader = new InputStreamReader(fis, Charsets.UTF_8)){
        text = CharStreams.toString(reader);
}

या अगर InputSupplier के साथ

InputSupplier<InputStreamReader> spl = ...
try (  InputStreamReader reader = spl.getInput()){
        text = CharStreams.toString(reader);
    }

16

लगभग। आप कुछ इस तरह का उपयोग कर सकते हैं:

InputSupplier<InputStreamReader> readerSupplier = CharStreams.newReaderSupplier
    (streamSupplier, Charsets.UTF_8);
String text = CharStreams.toString(readerSupplier);

व्यक्तिगत रूप से मुझे नहीं लगता कि IOUtils.toString(InputStream)यह "अच्छा" है - क्योंकि यह हमेशा प्लेटफ़ॉर्म के डिफ़ॉल्ट एन्कोडिंग का उपयोग करता है, जो कि लगभग कभी भी आप क्या चाहते हैं। एक अधिभार है जो एन्कोडिंग का नाम लेता है, लेकिन नामों का उपयोग करना एक महान विचार आईएमओ नहीं है। इसलिए मुझे पसंद है Charsets.*

संपादित करें: ऐसा नहीं है कि ऊपर के InputSupplier<InputStream>रूप में की जरूरत है streamSupplier। यदि आपको पहले ही स्ट्रीम मिल गई है तो आप इसे आसानी से लागू कर सकते हैं, हालांकि:

InputSupplier<InputStream> supplier = new InputSupplier<InputStream>() {
    @Override public InputStream getInput() {
        return stream;
    }
};

जॉन, request.getInputStream के माध्यम से स्ट्रीम है? इसके अलावा, क्या आप @ कालम के उत्तर में वर्णित कॉलिनड की धारा को बंद कर देंगे?
ब्लैंकमैन

ओह, और यह एक सर्वलेट doPost पर्यावरण है, मैं किसी भी तरह धारा बंद कर देना चाहिए?
ब्लेंकमैन

@ ब्लैंकमैन: आह, तो यह आपका संदर्भ है - यह आपके प्रश्न से बिल्कुल स्पष्ट नहीं था। यह बहुत ज्यादा मायने नहीं रखता कि आप अनुरोध स्ट्रीम बंद करते हैं, लेकिन मैं आमतौर पर ऐसा करता हूं। मैं इस उत्तर को संपादित करूँगा - हालांकि ऐसा कोई अधिभार नहीं है, ऐसा लगता है।
जॉन स्कीट

1
मैं अभी यह कर रहा हूं: स्ट्रिंग payLoad = CharStreams.toString (नया InputStreamReader (request.getInputStream) (), "UTF-8");
ब्लेंकमैन

1
@BeeOnRope: मुझे लगता है कि एक मध्यवर्ती दृष्टिकोण है Charsets.UTF_8.name()- अधिक टाइपो-प्रतिरोधी।
जॉन स्कीट

11

एक अन्य विकल्प स्ट्रीम से बाइट्स पढ़ना और उनसे एक स्ट्रिंग बनाना है:

new String(ByteStreams.toByteArray(inputStream))
new String(ByteStreams.toByteArray(inputStream), Charsets.UTF_8)

यह 'शुद्ध' अमरूद नहीं है, लेकिन यह थोड़ा छोटा है।


दुर्भाग्य से, ByteStreams.toByteArray()जावदोक के अनुसार, धारा को बंद नहीं करता है।
एलकेमिस्ट

यह सच है। मैंने किसी भी अमरूद के फंक्शन को नहीं देखा है जो स्ट्रीम को बंद करता है। खैर, करीब से छोड़कर।
२२:०५ पर पोनमेंद्र

1
आमतौर पर, स्ट्रीम कोशिश-के-संसाधनों के स्टेटमेंट में खोली जाती है और स्वचालित रूप से बंद हो जाती है, इसलिए यह BBteteArray () के लिए ज़िम्मेदार नहीं होना चाहिए
23

4

स्वीकार किए गए उत्तर के आधार पर, यहां एक उपयोगिता विधि है जो IOUtils.toString()(और साथ ही एक अतिभारित संस्करण को एक चारसेट के साथ, साथ ही) के व्यवहार का मजाक उड़ाती है । यह संस्करण सुरक्षित होना चाहिए, है ना?

public static String toString(final InputStream is) throws IOException{
    return toString(is, Charsets.UTF_8);
}


public static String toString(final InputStream is, final Charset cs)
throws IOException{
    Closeable closeMe = is;
    try{
        final InputStreamReader isr = new InputStreamReader(is, cs);
        closeMe = isr;
        return CharStreams.toString(isr);
    } finally{
        Closeables.closeQuietly(closeMe);
    }
}

मुझे बहुत अच्छा लगता है। यदि आप 1-शॉट स्ट्रीम और पाठकों (संभव हो) के बजाय पुन: प्रयोज्य इनपुट आपूर्तिकर्ताओं के संदर्भ में सोचना सीखते हैं, तो अमरूद का आईओ सामान सबसे अच्छा काम करता है, लेकिन मुझे लगता है कि आप मौजूदा IOUtils कोड को परिवर्तित कर रहे हैं जो कि एक बड़ा बदलाव होगा।
कॉलिनड

2
मेरे अमरूद 14 में, करीब पहले से ही पदावनत है। सुझाव है कि जावा में मौजूद
ट्राय

2
@ अल्बर्टकाम सहमत हो गए। लेकिन याद रखें: यह उत्तर तीन साल पुराना है।
सीन पैट्रिक फ्लॉयड

@SeanPatrickFloyd: धन्यवाद! वास्तव में मैं आपके उत्तर से शुरू होने वाले नए समाधान के लिए तैयार हूं। मैं उन लोगों के लिए टिप्पणी जोड़ने के बारे में सोच रहा था जो नए संस्करण का उपयोग कर रहे होंगे। :)
बर्टनी

4

वर्ग प्रवाह संसाधन से इनपुट स्ट्रीम होने पर मामले में बहुत कम आटोक्लोजिंग समाधान होता है:

URL resource = classLoader.getResource(path);
byte[] bytes = Resources.toByteArray(resource);
String text = Resources.toString(resource, StandardCharsets.UTF_8);

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


1
जब यह प्रश्न पूछा गया था, तो संसाधन वर्ग मौजूद नहीं था, लेकिन आप सही हैं: आज वह रास्ता तय करेगा। धन्यवाद
सीन पैट्रिक फ्लोयड

2

EDIT (2015): Okio जावा / Android में I / O के लिए सबसे अच्छा अमूर्त और उपकरण है जिसे मैं जानता हूं। मैं इसका हर समय उपयोग करता हूं।

FWIW यहाँ मैं क्या उपयोग है।

यदि मेरे पास पहले से ही एक धारा है, तो:

final InputStream stream; // this is received from somewhere
String s = CharStreams.toString(CharStreams.newReaderSupplier(new InputSupplier<InputStream>() {
    public InputStream getInput() throws IOException {
        return stream;
    }
}, Charsets.UTF_8));

अगर मैं एक स्ट्रीम बना रहा हूँ:

String s = CharStreams.toString(CharStreams.newReaderSupplier(new InputSupplier<InputStream>() {
    public InputStream getInput() throws IOException {
        return <expression creating the stream>;
    }
}, Charsets.UTF_8));

एक ठोस उदाहरण के रूप में, मैं इस तरह एक Android पाठ फ़ाइल संपत्ति पढ़ सकता हूं:

final Context context = ...;
String s = CharStreams.toString(CharStreams.newReaderSupplier(new InputSupplier<InputStream>() {
    public InputStream getInput() throws IOException {
        return context.getAssets().open("my_asset.txt");
    }
}, Charsets.UTF_8));

सभी अब अपदस्थ हो गए। :(
user3562927

1
इसके बजाय github.com/square/okio आज़माएं - मैंने अभी थोड़ी देर में अमरूद के I / O का उपयोग नहीं किया है, Okio बस बेहतर है,
orp

0

एक ठोस उदाहरण के लिए, यहां बताया गया है कि मैं Android टेक्स्ट फ़ाइल संपत्ति कैसे पढ़ सकता हूं:

public static String getAssetContent(Context context, String file) {
    InputStreamReader reader = null;
    InputStream stream = null;
    String output = "";

    try {
        stream = context.getAssets().open(file);
        reader = new InputStreamReader(stream, Charsets.UTF_8);
        output = CharStreams.toString(reader);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

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