मैं java.io.InputStream को java.lang.String से कैसे प्राप्त कर सकता हूं?


95

मैं एक है Stringकि मैं एक के रूप में उपयोग करना चाहते हैं InputStream। जावा 1.0 में, आप उपयोग कर सकते हैं java.io.StringBufferInputStream, लेकिन वह @Deprecrated(अच्छे कारण के साथ - आप वर्ण सेट एन्कोडिंग निर्दिष्ट नहीं कर सकते हैं):

यह वर्ग वर्णों को बाइट में ठीक से परिवर्तित नहीं करता है। JDK 1.1 के रूप में, एक स्ट्रिंग से एक स्ट्रीम बनाने का पसंदीदा तरीका StringReader क्लास के माध्यम से है ।

आप एक के java.io.Readerसाथ बना सकते हैं java.io.StringReader, लेकिन एक लेने Readerऔर एक बनाने के लिए कोई एडेप्टर नहीं हैं InputStream

मैंने एक प्राचीन बग को एक उपयुक्त प्रतिस्थापन के लिए कहा, लेकिन ऐसी कोई चीज मौजूद नहीं है - जहां तक ​​मैं बता सकता हूं।

आम java.lang.String.getBytes()तौर पर सुझाए गए वर्कअराउंड का उपयोग इनपुट के रूप में किया जाता है java.io.ByteArrayInputStream:

public InputStream createInputStream(String s, String charset)
    throws java.io.UnsupportedEncodingException {

    return new ByteArrayInputStream(s.getBytes(charset));
}

लेकिन इसका मतलब है कि Stringबाइट्स की एक सरणी के रूप में पूरे मेमोरी को भौतिक बनाना और एक स्ट्रीम के उद्देश्य को पराजित करना। ज्यादातर मामलों में यह कोई बड़ी बात नहीं है, लेकिन मैं एक ऐसी चीज की तलाश कर रहा था, जो एक धारा के इरादे को बनाए रखे - कि जितना संभव हो उतना कम डेटा (री) मेमोरी में भौतिक हो।

जवाबों:


78

अद्यतन: यह उत्तर ठीक वही है जो ओपी नहीं चाहता है। कृपया अन्य उत्तर पढ़ें।

उन मामलों के लिए जब हम स्मृति में पुन: भौतिक होने वाले डेटा की परवाह नहीं करते हैं, कृपया उपयोग करें:

new ByteArrayInputStream(str.getBytes("UTF-8"))

3
इस उत्तर द्वारा प्रस्तावित समाधान को प्रत्याशित, चिंतन और प्रश्न द्वारा खारिज कर दिया गया है। तो मेरी राय में, इस जवाब को हटा दिया जाना चाहिए।
माइक नाकिस

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

28
प्रश्न शीर्षक के कारण यहाँ आने वाले एक आगंतुक के रूप में, मुझे खुशी है कि यह उत्तर यहाँ है। तो: कृपया इस उत्तर को न हटाएँ। शीर्ष पर टिप्पणी "यह उत्तर ठीक वही है जो ओपी नहीं चाहता है। कृपया अन्य उत्तर पढ़ें।" काफी है।
याकोव बेल

10
जावा 7 के रूप में:new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))
धीमी गति

19

यदि आपको कॉमन्स- आईआईओ पैकेज पर निर्भरता का बुरा नहीं लगता है , तो आप IOUtils.toInputStream (स्ट्रिंग पाठ) विधि का उपयोग कर सकते हैं ।


11
उस मामले में आप एक निर्भरता जोड़ते हैं, जो `वापसी नई बाइटएयरइंटरप्यूटस्ट्रीम (इनपुट.गेटबाइट्स ()) के अलावा और कुछ नहीं करता है; ' क्या यह वास्तव में एक निर्भरता के लायक है? सभी ईमानदारी में, नहीं - यह नहीं है।
whaefelinger

3
यह सच है, के अलावा यह वास्तव में समाधान नहीं है, क्योंकि वह सेशन स्ट्रिंग से किया जा रहा करने के लिए oposed "स्मृति में स्ट्रिंग अमल में लाना" नहीं चाहता है प्रणाली में :) कहीं और materialized का उपयोग करने के लिए wan't नहीं है
Fotis Paraskevopoulos

क्या हमारे पास कोई लाइब्रेरी है जो कस्टम ऑब्जेक्ट को इनपुट स्ट्रीम के स्रोत में परिवर्तित करती है; IOUtils.toInputStream (MyObject ऑब्जेक्ट) जैसा कुछ?
नवाज़िश-स्टैकओवरफ़्लो

5

Apache Commons-IO से एक एडेप्टर होता है जो रीडर से इनपुटस्ट्रीम में एडाप्ट करता है, जिसे ReaderInputStream नाम दिया गया है

उदाहरण कोड:

@Test
public void testReaderInputStream() throws IOException {
    InputStream inputStream = new ReaderInputStream(new StringReader("largeString"), StandardCharsets.UTF_8);
    Assert.assertEquals("largeString", IOUtils.toString(inputStream, StandardCharsets.UTF_8));
}

संदर्भ: https://stackoverflow.com/a/27909221/5658642


3

मेरे दिमाग में, ऐसा करने का सबसे आसान तरीका एक लेखक के माध्यम से डेटा को धक्का देना है:

public class StringEmitter {
  public static void main(String[] args) throws IOException {
    class DataHandler extends OutputStream {
      @Override
      public void write(final int b) throws IOException {
        write(new byte[] { (byte) b });
      }
      @Override
      public void write(byte[] b) throws IOException {
        write(b, 0, b.length);
      }
      @Override
      public void write(byte[] b, int off, int len)
          throws IOException {
        System.out.println("bytecount=" + len);
      }
    }

    StringBuilder sample = new StringBuilder();
    while (sample.length() < 100 * 1000) {
      sample.append("sample");
    }

    Writer writer = new OutputStreamWriter(
        new DataHandler(), "UTF-16");
    writer.write(sample.toString());
    writer.close();
  }
}

जेवीएम कार्यान्वयन मैं 8K विखंडू में धकेल दिए गए डेटा का उपयोग कर रहा हूं, लेकिन आप एक समय में लिखे गए वर्णों की संख्या को कम करके और फ्लश कहकर बफर आकार पर कुछ प्रभाव डाल सकते हैं।


डेटा को एन्कोड करने के लिए राइटर का उपयोग करने के लिए अपने खुद के चारसेटएन्कोडर रैपर लिखने का विकल्प, हालांकि यह सही करने के लिए एक दर्द की बात है। यह एक विश्वसनीय (यदि अक्षम है) कार्यान्वयन होना चाहिए:

/** Inefficient string stream implementation */
public class StringInputStream extends InputStream {

  /* # of characters to buffer - must be >=2 to handle surrogate pairs */
  private static final int CHAR_CAP = 8;

  private final Queue<Byte> buffer = new LinkedList<Byte>();
  private final Writer encoder;
  private final String data;
  private int index;

  public StringInputStream(String sequence, Charset charset) {
    data = sequence;
    encoder = new OutputStreamWriter(
        new OutputStreamBuffer(), charset);
  }

  private int buffer() throws IOException {
    if (index >= data.length()) {
      return -1;
    }
    int rlen = index + CHAR_CAP;
    if (rlen > data.length()) {
      rlen = data.length();
    }
    for (; index < rlen; index++) {
      char ch = data.charAt(index);
      encoder.append(ch);
      // ensure data enters buffer
      encoder.flush();
    }
    if (index >= data.length()) {
      encoder.close();
    }
    return buffer.size();
  }

  @Override
  public int read() throws IOException {
    if (buffer.size() == 0) {
      int r = buffer();
      if (r == -1) {
        return -1;
      }
    }
    return 0xFF & buffer.remove();
  }

  private class OutputStreamBuffer extends OutputStream {

    @Override
    public void write(int i) throws IOException {
      byte b = (byte) i;
      buffer.add(b);
    }

  }

}

2

खैर, एक संभव तरीका यह है:

  • बनाओ PipedOutputStream
  • इसे पाइप करें PipedInputStream
  • OutputStreamWriterचारों ओर लपेटें PipedOutputStream(आप कंस्ट्रक्टर में एन्कोडिंग निर्दिष्ट कर सकते हैं)
  • Et voilá, कुछ भी आप लिख OutputStreamWriterसकते हैं से पढ़ा जा सकता है PipedInputStream!

बेशक, यह ऐसा करने के बजाय एक हैकिश तरीका लगता है, लेकिन कम से कम यह एक तरीका है।


1
दिलचस्प ... निश्चित रूप से, इस समाधान के साथ मेरा मानना ​​है कि आप या तो पूरे स्ट्रिंग को स्मृति में बदल देंगे, या रीडिंग थ्रेड पर भुखमरी से पीड़ित होंगे। फिर भी उम्मीद है कि कहीं न कहीं वास्तविक कार्यान्वयन हो।
जेरेड ओबरहॉस

5
आपको Piped (Input | Output) स्ट्रीम से सावधान रहना होगा। डॉक्स के अनुसार: "... एक ही धागे से दोनों वस्तुओं का उपयोग करने का प्रयास करने की अनुशंसा नहीं की जाती है, क्योंकि यह थ्रेड को गतिरोध में डाल
ब्रायन काइल

1

एक समाधान अपने स्वयं के रोल करने के लिए है, एक InputStreamकार्यान्वयन का निर्माण करना जो संभवतः java.nio.charset.CharsetEncoderप्रत्येक के लिए charया charबाइट्स की एक सरणी के लिए InputStreamआवश्यक के रूप में बाइट्स को एन्कोड करने के लिए उपयोग करेगा ।


1
एक समय में एक ही काम करना महंगा है। यही कारण है कि हमारे पास इनपुटस्ट्रीम की तरह "चंक्ड इटएटर" हैं जो हमें एक समय में बफर पढ़ने की अनुमति देते हैं।
टॉम हॉल्टिन -

मैं टॉम से सहमत हूं - आप वास्तव में एक बार में यह एक चरित्र नहीं करना चाहते हैं।
एडी

1
जब तक कि डेटा वास्तव में छोटा नहीं है, और अन्य चीजें (नेटवर्क विलंबता, उदाहरण के लिए) अधिक समय लेती हैं। फिर इससे कोई फर्क नहीं पड़ता। :)
एंड्रेस रिओप्रियो

0

आप org.hsqldb.lib लाइब्रेरी की मदद ले सकते हैं।

public StringInputStream(String paramString)
  {
    this.str = paramString;
    this.available = (paramString.length() * 2);
  }

1
आम तौर पर, प्रश्न बहुत अधिक उपयोगी होते हैं यदि वे एक स्पष्टीकरण शामिल करते हैं कि कोड क्या करना है।
पीटर

-1

मुझे पता है कि यह एक पुराना प्रश्न है लेकिन मुझे आज भी यही समस्या थी, और यह मेरा समाधान था:

public static InputStream getStream(final CharSequence charSequence) {
 return new InputStream() {
  int index = 0;
  int length = charSequence.length();
  @Override public int read() throws IOException {
   return index>=length ? -1 : charSequence.charAt(index++);
  }
 };
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.