Java: accessing a List of Strings as an InputStream












13















Is there any way InputStream wrapping a list of UTF-8 String? I'd like to do something like:



InputStream in = new XyzInputStream( List<String> lines )









share|improve this question

























  • Can you share the situation, why you want this?

    – Chandra Sekhar
    Mar 23 '12 at 10:41






  • 2





    Note that InputStream deals with binary data. Strings are text data. Which encoding are you interested in?

    – Jon Skeet
    Mar 23 '12 at 10:43











  • You're right I forgot to precise : UTF-8 only.

    – Marc Polizzi
    Mar 23 '12 at 10:47













  • How did you finally accomplish creating an InputStream from List<String> Marc? I have to do the same thing. Any Input will help.

    – Rahul Dabas
    Sep 25 '14 at 19:05
















13















Is there any way InputStream wrapping a list of UTF-8 String? I'd like to do something like:



InputStream in = new XyzInputStream( List<String> lines )









share|improve this question

























  • Can you share the situation, why you want this?

    – Chandra Sekhar
    Mar 23 '12 at 10:41






  • 2





    Note that InputStream deals with binary data. Strings are text data. Which encoding are you interested in?

    – Jon Skeet
    Mar 23 '12 at 10:43











  • You're right I forgot to precise : UTF-8 only.

    – Marc Polizzi
    Mar 23 '12 at 10:47













  • How did you finally accomplish creating an InputStream from List<String> Marc? I have to do the same thing. Any Input will help.

    – Rahul Dabas
    Sep 25 '14 at 19:05














13












13








13


5






Is there any way InputStream wrapping a list of UTF-8 String? I'd like to do something like:



InputStream in = new XyzInputStream( List<String> lines )









share|improve this question
















Is there any way InputStream wrapping a list of UTF-8 String? I'd like to do something like:



InputStream in = new XyzInputStream( List<String> lines )






java java-io






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 23 '12 at 10:56









Andrew Thompson

154k28164347




154k28164347










asked Mar 23 '12 at 10:38









Marc PolizziMarc Polizzi

7,11232649




7,11232649













  • Can you share the situation, why you want this?

    – Chandra Sekhar
    Mar 23 '12 at 10:41






  • 2





    Note that InputStream deals with binary data. Strings are text data. Which encoding are you interested in?

    – Jon Skeet
    Mar 23 '12 at 10:43











  • You're right I forgot to precise : UTF-8 only.

    – Marc Polizzi
    Mar 23 '12 at 10:47













  • How did you finally accomplish creating an InputStream from List<String> Marc? I have to do the same thing. Any Input will help.

    – Rahul Dabas
    Sep 25 '14 at 19:05



















  • Can you share the situation, why you want this?

    – Chandra Sekhar
    Mar 23 '12 at 10:41






  • 2





    Note that InputStream deals with binary data. Strings are text data. Which encoding are you interested in?

    – Jon Skeet
    Mar 23 '12 at 10:43











  • You're right I forgot to precise : UTF-8 only.

    – Marc Polizzi
    Mar 23 '12 at 10:47













  • How did you finally accomplish creating an InputStream from List<String> Marc? I have to do the same thing. Any Input will help.

    – Rahul Dabas
    Sep 25 '14 at 19:05

















Can you share the situation, why you want this?

– Chandra Sekhar
Mar 23 '12 at 10:41





Can you share the situation, why you want this?

– Chandra Sekhar
Mar 23 '12 at 10:41




2




2





Note that InputStream deals with binary data. Strings are text data. Which encoding are you interested in?

– Jon Skeet
Mar 23 '12 at 10:43





Note that InputStream deals with binary data. Strings are text data. Which encoding are you interested in?

– Jon Skeet
Mar 23 '12 at 10:43













You're right I forgot to precise : UTF-8 only.

– Marc Polizzi
Mar 23 '12 at 10:47







You're right I forgot to precise : UTF-8 only.

– Marc Polizzi
Mar 23 '12 at 10:47















How did you finally accomplish creating an InputStream from List<String> Marc? I have to do the same thing. Any Input will help.

– Rahul Dabas
Sep 25 '14 at 19:05





How did you finally accomplish creating an InputStream from List<String> Marc? I have to do the same thing. Any Input will help.

– Rahul Dabas
Sep 25 '14 at 19:05












6 Answers
6






active

oldest

votes


















3














You can concatenate all the lines together to create a String then convert it to a byte array using String#getBytes and pass it into ByteArrayInputStream. However this is not the most efficient way of doing it.






share|improve this answer


























  • Done this way already; I'd like to avoid this copy.

    – Marc Polizzi
    Mar 23 '12 at 10:48











  • You can implement a InputStream yourself and convert each String to a byte array as you go along and wrap it in a ByteArrayInputStream and forward the calls to the ByteArrayInputStream. Though, seeing as you will have to have logic dealing with splitting reads across Strings it's probably just as easy to do all the logic yourself and not use ByteArrayInputStream at all.

    – benmmurphy
    Mar 23 '12 at 10:53













  • @Marc avoiding this copy is not necessary a good idea. It allows you to process all the data at once. If the strings are small this can save you a lot of object allocations. It can be faster and in some cases even consume less memory. Whatever you do, benchmark it on sample data and make sure it really is more efficient.

    – Piotr Praszmo
    Mar 23 '12 at 11:26











  • @Marc You can avoid the copy, but not without writing a significant amount of code. You would have to implement InputStream yourself, and somehow adapt all of its methods to working over a List of Strings, which will be an enormous pain to do, and won't buy you that much in terms of performance or reduced memory footprint.

    – Jon
    Mar 23 '12 at 11:41



















7














You can read from a ByteArrayOutputStream and you can create your source byte array using a ByteArrayInputStream.



So create the array as follows:



 List<String> source = new ArrayList<String>();
source.add("one");
source.add("two");
source.add("three");
ByteArrayOutputStream baos = new ByteArrayOutputStream();

for (String line : source) {
baos.write(line.getBytes());
}

byte bytes = baos.toByteArray();


And reading from it is as simple as:



 InputStream in = new ByteArrayInputStream(bytes);


Alternatively, depending on what you're trying to do, a StringReader might be better.






share|improve this answer


























  • This is the best way of doing it if it's a one-off. If you have to reuse instances of the InputStream all over the place though, you could always implement the InputStream interface, and do all of the above under the hood.

    – Jon
    Mar 23 '12 at 11:10











  • Good example, but it would be nice to encourage best practice by specifying a charset during getBytes().

    – Duncan Jones
    Mar 11 '15 at 9:37



















4














In short, no, there is no way of doing this using existing JDK classes. You could, however, implement your own InputStream that read from a List of Strings.



EDIT: Dave Web has an answer above, which I think is the way to go. If you need a reusable class, then something like this might do:





public class StringsInputStream<T extends Iterable<String>> extends InputStream {

private ByteArrayInputStream bais = null;

public StringsInputStream(final T strings) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
for (String line : strings) {
outputStream.write(line.getBytes());
}
bais = new ByteArrayInputStream(outputStream.toByteArray());
}

@Override
public int read() throws IOException {
return bais.read();
}

@Override
public int read(byte b) throws IOException {
return bais.read(b);
}

@Override
public int read(byte b, int off, int len) throws IOException {
return bais.read(b, off, len);
}

@Override
public long skip(long n) throws IOException {
return bais.skip(n);
}

@Override
public int available() throws IOException {
return bais.available();
}

@Override
public void close() throws IOException {
bais.close();
}

@Override
public synchronized void mark(int readlimit) {
bais.mark(readlimit);
}

@Override
public synchronized void reset() throws IOException {
bais.reset();
}

@Override
public boolean markSupported() {
return bais.markSupported();
}

public static void main(String args) throws Exception {
List source = new ArrayList();
source.add("foo ");
source.add("bar ");
source.add("baz");

StringsInputStream<List<String>> in = new StringsInputStream<List<String>>(source);

int read = in.read();
while (read != -1) {
System.out.print((char) read);
read = in.read();
}
}
}



This basically an adapter for ByteArrayInputStream.






share|improve this answer

































    0














    you can also do this way create a Serializable List



    List<String> quarks = Arrays.asList(
    "up", "down", "strange", "charm", "top", "bottom"
    );

    //serialize the List
    //note the use of abstract base class references

    try{
    //use buffering
    OutputStream file = new FileOutputStream( "quarks.ser" );
    OutputStream buffer = new BufferedOutputStream( file );
    ObjectOutput output = new ObjectOutputStream( buffer );
    try{
    output.writeObject(quarks);
    }
    finally{
    output.close();
    }
    }
    catch(IOException ex){
    fLogger.log(Level.SEVERE, "Cannot perform output.", ex);
    }

    //deserialize the quarks.ser file
    //note the use of abstract base class references

    try{
    //use buffering
    InputStream file = new FileInputStream( "quarks.ser" );
    InputStream buffer = new BufferedInputStream( file );
    ObjectInput input = new ObjectInputStream ( buffer );
    try{
    //deserialize the List
    List<String> recoveredQuarks = (List<String>)input.readObject();
    //display its data
    for(String quark: recoveredQuarks){
    System.out.println("Recovered Quark: " + quark);
    }
    }
    finally{
    input.close();
    }
    }
    catch(ClassNotFoundException ex){
    fLogger.log(Level.SEVERE, "Cannot perform input. Class not found.", ex);
    }
    catch(IOException ex){
    fLogger.log(Level.SEVERE, "Cannot perform input.", ex);
    }





    share|improve this answer































      0














      You can do something similar to this:



      https://commons.apache.org/sandbox/flatfile/xref/org/apache/commons/flatfile/util/ConcatenatedInputStream.html



      It just implements the read() method of InputStream and has a list of InputStreams it is concatenating. Once it reads an EOF it starts reading from the next InputStream. Just convert the Strings to ByteArrayInputStreams.






      share|improve this answer































        0














        You can create some kind of IterableInputStream



        public class IterableInputStream<T> extends InputStream {

        public static final int EOF = -1;

        private static final InputStream EOF_IS = new InputStream() {
        @Override public int read() throws IOException {
        return EOF;
        }
        };

        private final Iterator<T> iterator;
        private final Function<T, byte> mapper;

        private InputStream current;

        public IterableInputStream(Iterable<T> iterable, Function<T, byte> mapper) {
        this.iterator = iterable.iterator();
        this.mapper = mapper;
        next();
        }

        @Override
        public int read() throws IOException {
        int n = current.read();
        while (n == EOF && current != EOF_IS) {
        next();
        n = current.read();
        }
        return n;
        }

        private void next() {
        current = iterator.hasNext()
        ? new ByteArrayInputStream(mapper.apply(iterator.next()))
        : EOF_IS;
        }
        }


        To use it



        public static void main(String args) throws IOException {
        Iterable<String> strings = Arrays.asList("1", "22", "333", "4444");
        try (InputStream is = new IterableInputStream<String>(strings, String::getBytes)) {
        for (int b = is.read(); b != -1; b = is.read()) {
        System.out.print((char) b);
        }
        }
        }





        share|improve this answer























          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f9837754%2fjava-accessing-a-list-of-strings-as-an-inputstream%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          6 Answers
          6






          active

          oldest

          votes








          6 Answers
          6






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          3














          You can concatenate all the lines together to create a String then convert it to a byte array using String#getBytes and pass it into ByteArrayInputStream. However this is not the most efficient way of doing it.






          share|improve this answer


























          • Done this way already; I'd like to avoid this copy.

            – Marc Polizzi
            Mar 23 '12 at 10:48











          • You can implement a InputStream yourself and convert each String to a byte array as you go along and wrap it in a ByteArrayInputStream and forward the calls to the ByteArrayInputStream. Though, seeing as you will have to have logic dealing with splitting reads across Strings it's probably just as easy to do all the logic yourself and not use ByteArrayInputStream at all.

            – benmmurphy
            Mar 23 '12 at 10:53













          • @Marc avoiding this copy is not necessary a good idea. It allows you to process all the data at once. If the strings are small this can save you a lot of object allocations. It can be faster and in some cases even consume less memory. Whatever you do, benchmark it on sample data and make sure it really is more efficient.

            – Piotr Praszmo
            Mar 23 '12 at 11:26











          • @Marc You can avoid the copy, but not without writing a significant amount of code. You would have to implement InputStream yourself, and somehow adapt all of its methods to working over a List of Strings, which will be an enormous pain to do, and won't buy you that much in terms of performance or reduced memory footprint.

            – Jon
            Mar 23 '12 at 11:41
















          3














          You can concatenate all the lines together to create a String then convert it to a byte array using String#getBytes and pass it into ByteArrayInputStream. However this is not the most efficient way of doing it.






          share|improve this answer


























          • Done this way already; I'd like to avoid this copy.

            – Marc Polizzi
            Mar 23 '12 at 10:48











          • You can implement a InputStream yourself and convert each String to a byte array as you go along and wrap it in a ByteArrayInputStream and forward the calls to the ByteArrayInputStream. Though, seeing as you will have to have logic dealing with splitting reads across Strings it's probably just as easy to do all the logic yourself and not use ByteArrayInputStream at all.

            – benmmurphy
            Mar 23 '12 at 10:53













          • @Marc avoiding this copy is not necessary a good idea. It allows you to process all the data at once. If the strings are small this can save you a lot of object allocations. It can be faster and in some cases even consume less memory. Whatever you do, benchmark it on sample data and make sure it really is more efficient.

            – Piotr Praszmo
            Mar 23 '12 at 11:26











          • @Marc You can avoid the copy, but not without writing a significant amount of code. You would have to implement InputStream yourself, and somehow adapt all of its methods to working over a List of Strings, which will be an enormous pain to do, and won't buy you that much in terms of performance or reduced memory footprint.

            – Jon
            Mar 23 '12 at 11:41














          3












          3








          3







          You can concatenate all the lines together to create a String then convert it to a byte array using String#getBytes and pass it into ByteArrayInputStream. However this is not the most efficient way of doing it.






          share|improve this answer















          You can concatenate all the lines together to create a String then convert it to a byte array using String#getBytes and pass it into ByteArrayInputStream. However this is not the most efficient way of doing it.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 23 '12 at 10:47









          Riduidel

          18k1160134




          18k1160134










          answered Mar 23 '12 at 10:46









          benmmurphybenmmurphy

          1,93811626




          1,93811626













          • Done this way already; I'd like to avoid this copy.

            – Marc Polizzi
            Mar 23 '12 at 10:48











          • You can implement a InputStream yourself and convert each String to a byte array as you go along and wrap it in a ByteArrayInputStream and forward the calls to the ByteArrayInputStream. Though, seeing as you will have to have logic dealing with splitting reads across Strings it's probably just as easy to do all the logic yourself and not use ByteArrayInputStream at all.

            – benmmurphy
            Mar 23 '12 at 10:53













          • @Marc avoiding this copy is not necessary a good idea. It allows you to process all the data at once. If the strings are small this can save you a lot of object allocations. It can be faster and in some cases even consume less memory. Whatever you do, benchmark it on sample data and make sure it really is more efficient.

            – Piotr Praszmo
            Mar 23 '12 at 11:26











          • @Marc You can avoid the copy, but not without writing a significant amount of code. You would have to implement InputStream yourself, and somehow adapt all of its methods to working over a List of Strings, which will be an enormous pain to do, and won't buy you that much in terms of performance or reduced memory footprint.

            – Jon
            Mar 23 '12 at 11:41



















          • Done this way already; I'd like to avoid this copy.

            – Marc Polizzi
            Mar 23 '12 at 10:48











          • You can implement a InputStream yourself and convert each String to a byte array as you go along and wrap it in a ByteArrayInputStream and forward the calls to the ByteArrayInputStream. Though, seeing as you will have to have logic dealing with splitting reads across Strings it's probably just as easy to do all the logic yourself and not use ByteArrayInputStream at all.

            – benmmurphy
            Mar 23 '12 at 10:53













          • @Marc avoiding this copy is not necessary a good idea. It allows you to process all the data at once. If the strings are small this can save you a lot of object allocations. It can be faster and in some cases even consume less memory. Whatever you do, benchmark it on sample data and make sure it really is more efficient.

            – Piotr Praszmo
            Mar 23 '12 at 11:26











          • @Marc You can avoid the copy, but not without writing a significant amount of code. You would have to implement InputStream yourself, and somehow adapt all of its methods to working over a List of Strings, which will be an enormous pain to do, and won't buy you that much in terms of performance or reduced memory footprint.

            – Jon
            Mar 23 '12 at 11:41

















          Done this way already; I'd like to avoid this copy.

          – Marc Polizzi
          Mar 23 '12 at 10:48





          Done this way already; I'd like to avoid this copy.

          – Marc Polizzi
          Mar 23 '12 at 10:48













          You can implement a InputStream yourself and convert each String to a byte array as you go along and wrap it in a ByteArrayInputStream and forward the calls to the ByteArrayInputStream. Though, seeing as you will have to have logic dealing with splitting reads across Strings it's probably just as easy to do all the logic yourself and not use ByteArrayInputStream at all.

          – benmmurphy
          Mar 23 '12 at 10:53







          You can implement a InputStream yourself and convert each String to a byte array as you go along and wrap it in a ByteArrayInputStream and forward the calls to the ByteArrayInputStream. Though, seeing as you will have to have logic dealing with splitting reads across Strings it's probably just as easy to do all the logic yourself and not use ByteArrayInputStream at all.

          – benmmurphy
          Mar 23 '12 at 10:53















          @Marc avoiding this copy is not necessary a good idea. It allows you to process all the data at once. If the strings are small this can save you a lot of object allocations. It can be faster and in some cases even consume less memory. Whatever you do, benchmark it on sample data and make sure it really is more efficient.

          – Piotr Praszmo
          Mar 23 '12 at 11:26





          @Marc avoiding this copy is not necessary a good idea. It allows you to process all the data at once. If the strings are small this can save you a lot of object allocations. It can be faster and in some cases even consume less memory. Whatever you do, benchmark it on sample data and make sure it really is more efficient.

          – Piotr Praszmo
          Mar 23 '12 at 11:26













          @Marc You can avoid the copy, but not without writing a significant amount of code. You would have to implement InputStream yourself, and somehow adapt all of its methods to working over a List of Strings, which will be an enormous pain to do, and won't buy you that much in terms of performance or reduced memory footprint.

          – Jon
          Mar 23 '12 at 11:41





          @Marc You can avoid the copy, but not without writing a significant amount of code. You would have to implement InputStream yourself, and somehow adapt all of its methods to working over a List of Strings, which will be an enormous pain to do, and won't buy you that much in terms of performance or reduced memory footprint.

          – Jon
          Mar 23 '12 at 11:41













          7














          You can read from a ByteArrayOutputStream and you can create your source byte array using a ByteArrayInputStream.



          So create the array as follows:



           List<String> source = new ArrayList<String>();
          source.add("one");
          source.add("two");
          source.add("three");
          ByteArrayOutputStream baos = new ByteArrayOutputStream();

          for (String line : source) {
          baos.write(line.getBytes());
          }

          byte bytes = baos.toByteArray();


          And reading from it is as simple as:



           InputStream in = new ByteArrayInputStream(bytes);


          Alternatively, depending on what you're trying to do, a StringReader might be better.






          share|improve this answer


























          • This is the best way of doing it if it's a one-off. If you have to reuse instances of the InputStream all over the place though, you could always implement the InputStream interface, and do all of the above under the hood.

            – Jon
            Mar 23 '12 at 11:10











          • Good example, but it would be nice to encourage best practice by specifying a charset during getBytes().

            – Duncan Jones
            Mar 11 '15 at 9:37
















          7














          You can read from a ByteArrayOutputStream and you can create your source byte array using a ByteArrayInputStream.



          So create the array as follows:



           List<String> source = new ArrayList<String>();
          source.add("one");
          source.add("two");
          source.add("three");
          ByteArrayOutputStream baos = new ByteArrayOutputStream();

          for (String line : source) {
          baos.write(line.getBytes());
          }

          byte bytes = baos.toByteArray();


          And reading from it is as simple as:



           InputStream in = new ByteArrayInputStream(bytes);


          Alternatively, depending on what you're trying to do, a StringReader might be better.






          share|improve this answer


























          • This is the best way of doing it if it's a one-off. If you have to reuse instances of the InputStream all over the place though, you could always implement the InputStream interface, and do all of the above under the hood.

            – Jon
            Mar 23 '12 at 11:10











          • Good example, but it would be nice to encourage best practice by specifying a charset during getBytes().

            – Duncan Jones
            Mar 11 '15 at 9:37














          7












          7








          7







          You can read from a ByteArrayOutputStream and you can create your source byte array using a ByteArrayInputStream.



          So create the array as follows:



           List<String> source = new ArrayList<String>();
          source.add("one");
          source.add("two");
          source.add("three");
          ByteArrayOutputStream baos = new ByteArrayOutputStream();

          for (String line : source) {
          baos.write(line.getBytes());
          }

          byte bytes = baos.toByteArray();


          And reading from it is as simple as:



           InputStream in = new ByteArrayInputStream(bytes);


          Alternatively, depending on what you're trying to do, a StringReader might be better.






          share|improve this answer















          You can read from a ByteArrayOutputStream and you can create your source byte array using a ByteArrayInputStream.



          So create the array as follows:



           List<String> source = new ArrayList<String>();
          source.add("one");
          source.add("two");
          source.add("three");
          ByteArrayOutputStream baos = new ByteArrayOutputStream();

          for (String line : source) {
          baos.write(line.getBytes());
          }

          byte bytes = baos.toByteArray();


          And reading from it is as simple as:



           InputStream in = new ByteArrayInputStream(bytes);


          Alternatively, depending on what you're trying to do, a StringReader might be better.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 23 '12 at 11:15

























          answered Mar 23 '12 at 10:48









          Dave WebbDave Webb

          157k49282291




          157k49282291













          • This is the best way of doing it if it's a one-off. If you have to reuse instances of the InputStream all over the place though, you could always implement the InputStream interface, and do all of the above under the hood.

            – Jon
            Mar 23 '12 at 11:10











          • Good example, but it would be nice to encourage best practice by specifying a charset during getBytes().

            – Duncan Jones
            Mar 11 '15 at 9:37



















          • This is the best way of doing it if it's a one-off. If you have to reuse instances of the InputStream all over the place though, you could always implement the InputStream interface, and do all of the above under the hood.

            – Jon
            Mar 23 '12 at 11:10











          • Good example, but it would be nice to encourage best practice by specifying a charset during getBytes().

            – Duncan Jones
            Mar 11 '15 at 9:37

















          This is the best way of doing it if it's a one-off. If you have to reuse instances of the InputStream all over the place though, you could always implement the InputStream interface, and do all of the above under the hood.

          – Jon
          Mar 23 '12 at 11:10





          This is the best way of doing it if it's a one-off. If you have to reuse instances of the InputStream all over the place though, you could always implement the InputStream interface, and do all of the above under the hood.

          – Jon
          Mar 23 '12 at 11:10













          Good example, but it would be nice to encourage best practice by specifying a charset during getBytes().

          – Duncan Jones
          Mar 11 '15 at 9:37





          Good example, but it would be nice to encourage best practice by specifying a charset during getBytes().

          – Duncan Jones
          Mar 11 '15 at 9:37











          4














          In short, no, there is no way of doing this using existing JDK classes. You could, however, implement your own InputStream that read from a List of Strings.



          EDIT: Dave Web has an answer above, which I think is the way to go. If you need a reusable class, then something like this might do:





          public class StringsInputStream<T extends Iterable<String>> extends InputStream {

          private ByteArrayInputStream bais = null;

          public StringsInputStream(final T strings) throws IOException {
          ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
          for (String line : strings) {
          outputStream.write(line.getBytes());
          }
          bais = new ByteArrayInputStream(outputStream.toByteArray());
          }

          @Override
          public int read() throws IOException {
          return bais.read();
          }

          @Override
          public int read(byte b) throws IOException {
          return bais.read(b);
          }

          @Override
          public int read(byte b, int off, int len) throws IOException {
          return bais.read(b, off, len);
          }

          @Override
          public long skip(long n) throws IOException {
          return bais.skip(n);
          }

          @Override
          public int available() throws IOException {
          return bais.available();
          }

          @Override
          public void close() throws IOException {
          bais.close();
          }

          @Override
          public synchronized void mark(int readlimit) {
          bais.mark(readlimit);
          }

          @Override
          public synchronized void reset() throws IOException {
          bais.reset();
          }

          @Override
          public boolean markSupported() {
          return bais.markSupported();
          }

          public static void main(String args) throws Exception {
          List source = new ArrayList();
          source.add("foo ");
          source.add("bar ");
          source.add("baz");

          StringsInputStream<List<String>> in = new StringsInputStream<List<String>>(source);

          int read = in.read();
          while (read != -1) {
          System.out.print((char) read);
          read = in.read();
          }
          }
          }



          This basically an adapter for ByteArrayInputStream.






          share|improve this answer






























            4














            In short, no, there is no way of doing this using existing JDK classes. You could, however, implement your own InputStream that read from a List of Strings.



            EDIT: Dave Web has an answer above, which I think is the way to go. If you need a reusable class, then something like this might do:





            public class StringsInputStream<T extends Iterable<String>> extends InputStream {

            private ByteArrayInputStream bais = null;

            public StringsInputStream(final T strings) throws IOException {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            for (String line : strings) {
            outputStream.write(line.getBytes());
            }
            bais = new ByteArrayInputStream(outputStream.toByteArray());
            }

            @Override
            public int read() throws IOException {
            return bais.read();
            }

            @Override
            public int read(byte b) throws IOException {
            return bais.read(b);
            }

            @Override
            public int read(byte b, int off, int len) throws IOException {
            return bais.read(b, off, len);
            }

            @Override
            public long skip(long n) throws IOException {
            return bais.skip(n);
            }

            @Override
            public int available() throws IOException {
            return bais.available();
            }

            @Override
            public void close() throws IOException {
            bais.close();
            }

            @Override
            public synchronized void mark(int readlimit) {
            bais.mark(readlimit);
            }

            @Override
            public synchronized void reset() throws IOException {
            bais.reset();
            }

            @Override
            public boolean markSupported() {
            return bais.markSupported();
            }

            public static void main(String args) throws Exception {
            List source = new ArrayList();
            source.add("foo ");
            source.add("bar ");
            source.add("baz");

            StringsInputStream<List<String>> in = new StringsInputStream<List<String>>(source);

            int read = in.read();
            while (read != -1) {
            System.out.print((char) read);
            read = in.read();
            }
            }
            }



            This basically an adapter for ByteArrayInputStream.






            share|improve this answer




























              4












              4








              4







              In short, no, there is no way of doing this using existing JDK classes. You could, however, implement your own InputStream that read from a List of Strings.



              EDIT: Dave Web has an answer above, which I think is the way to go. If you need a reusable class, then something like this might do:





              public class StringsInputStream<T extends Iterable<String>> extends InputStream {

              private ByteArrayInputStream bais = null;

              public StringsInputStream(final T strings) throws IOException {
              ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
              for (String line : strings) {
              outputStream.write(line.getBytes());
              }
              bais = new ByteArrayInputStream(outputStream.toByteArray());
              }

              @Override
              public int read() throws IOException {
              return bais.read();
              }

              @Override
              public int read(byte b) throws IOException {
              return bais.read(b);
              }

              @Override
              public int read(byte b, int off, int len) throws IOException {
              return bais.read(b, off, len);
              }

              @Override
              public long skip(long n) throws IOException {
              return bais.skip(n);
              }

              @Override
              public int available() throws IOException {
              return bais.available();
              }

              @Override
              public void close() throws IOException {
              bais.close();
              }

              @Override
              public synchronized void mark(int readlimit) {
              bais.mark(readlimit);
              }

              @Override
              public synchronized void reset() throws IOException {
              bais.reset();
              }

              @Override
              public boolean markSupported() {
              return bais.markSupported();
              }

              public static void main(String args) throws Exception {
              List source = new ArrayList();
              source.add("foo ");
              source.add("bar ");
              source.add("baz");

              StringsInputStream<List<String>> in = new StringsInputStream<List<String>>(source);

              int read = in.read();
              while (read != -1) {
              System.out.print((char) read);
              read = in.read();
              }
              }
              }



              This basically an adapter for ByteArrayInputStream.






              share|improve this answer















              In short, no, there is no way of doing this using existing JDK classes. You could, however, implement your own InputStream that read from a List of Strings.



              EDIT: Dave Web has an answer above, which I think is the way to go. If you need a reusable class, then something like this might do:





              public class StringsInputStream<T extends Iterable<String>> extends InputStream {

              private ByteArrayInputStream bais = null;

              public StringsInputStream(final T strings) throws IOException {
              ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
              for (String line : strings) {
              outputStream.write(line.getBytes());
              }
              bais = new ByteArrayInputStream(outputStream.toByteArray());
              }

              @Override
              public int read() throws IOException {
              return bais.read();
              }

              @Override
              public int read(byte b) throws IOException {
              return bais.read(b);
              }

              @Override
              public int read(byte b, int off, int len) throws IOException {
              return bais.read(b, off, len);
              }

              @Override
              public long skip(long n) throws IOException {
              return bais.skip(n);
              }

              @Override
              public int available() throws IOException {
              return bais.available();
              }

              @Override
              public void close() throws IOException {
              bais.close();
              }

              @Override
              public synchronized void mark(int readlimit) {
              bais.mark(readlimit);
              }

              @Override
              public synchronized void reset() throws IOException {
              bais.reset();
              }

              @Override
              public boolean markSupported() {
              return bais.markSupported();
              }

              public static void main(String args) throws Exception {
              List source = new ArrayList();
              source.add("foo ");
              source.add("bar ");
              source.add("baz");

              StringsInputStream<List<String>> in = new StringsInputStream<List<String>>(source);

              int read = in.read();
              while (read != -1) {
              System.out.print((char) read);
              read = in.read();
              }
              }
              }



              This basically an adapter for ByteArrayInputStream.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Mar 23 '12 at 13:37

























              answered Mar 23 '12 at 10:50









              JonJon

              2,44551932




              2,44551932























                  0














                  you can also do this way create a Serializable List



                  List<String> quarks = Arrays.asList(
                  "up", "down", "strange", "charm", "top", "bottom"
                  );

                  //serialize the List
                  //note the use of abstract base class references

                  try{
                  //use buffering
                  OutputStream file = new FileOutputStream( "quarks.ser" );
                  OutputStream buffer = new BufferedOutputStream( file );
                  ObjectOutput output = new ObjectOutputStream( buffer );
                  try{
                  output.writeObject(quarks);
                  }
                  finally{
                  output.close();
                  }
                  }
                  catch(IOException ex){
                  fLogger.log(Level.SEVERE, "Cannot perform output.", ex);
                  }

                  //deserialize the quarks.ser file
                  //note the use of abstract base class references

                  try{
                  //use buffering
                  InputStream file = new FileInputStream( "quarks.ser" );
                  InputStream buffer = new BufferedInputStream( file );
                  ObjectInput input = new ObjectInputStream ( buffer );
                  try{
                  //deserialize the List
                  List<String> recoveredQuarks = (List<String>)input.readObject();
                  //display its data
                  for(String quark: recoveredQuarks){
                  System.out.println("Recovered Quark: " + quark);
                  }
                  }
                  finally{
                  input.close();
                  }
                  }
                  catch(ClassNotFoundException ex){
                  fLogger.log(Level.SEVERE, "Cannot perform input. Class not found.", ex);
                  }
                  catch(IOException ex){
                  fLogger.log(Level.SEVERE, "Cannot perform input.", ex);
                  }





                  share|improve this answer




























                    0














                    you can also do this way create a Serializable List



                    List<String> quarks = Arrays.asList(
                    "up", "down", "strange", "charm", "top", "bottom"
                    );

                    //serialize the List
                    //note the use of abstract base class references

                    try{
                    //use buffering
                    OutputStream file = new FileOutputStream( "quarks.ser" );
                    OutputStream buffer = new BufferedOutputStream( file );
                    ObjectOutput output = new ObjectOutputStream( buffer );
                    try{
                    output.writeObject(quarks);
                    }
                    finally{
                    output.close();
                    }
                    }
                    catch(IOException ex){
                    fLogger.log(Level.SEVERE, "Cannot perform output.", ex);
                    }

                    //deserialize the quarks.ser file
                    //note the use of abstract base class references

                    try{
                    //use buffering
                    InputStream file = new FileInputStream( "quarks.ser" );
                    InputStream buffer = new BufferedInputStream( file );
                    ObjectInput input = new ObjectInputStream ( buffer );
                    try{
                    //deserialize the List
                    List<String> recoveredQuarks = (List<String>)input.readObject();
                    //display its data
                    for(String quark: recoveredQuarks){
                    System.out.println("Recovered Quark: " + quark);
                    }
                    }
                    finally{
                    input.close();
                    }
                    }
                    catch(ClassNotFoundException ex){
                    fLogger.log(Level.SEVERE, "Cannot perform input. Class not found.", ex);
                    }
                    catch(IOException ex){
                    fLogger.log(Level.SEVERE, "Cannot perform input.", ex);
                    }





                    share|improve this answer


























                      0












                      0








                      0







                      you can also do this way create a Serializable List



                      List<String> quarks = Arrays.asList(
                      "up", "down", "strange", "charm", "top", "bottom"
                      );

                      //serialize the List
                      //note the use of abstract base class references

                      try{
                      //use buffering
                      OutputStream file = new FileOutputStream( "quarks.ser" );
                      OutputStream buffer = new BufferedOutputStream( file );
                      ObjectOutput output = new ObjectOutputStream( buffer );
                      try{
                      output.writeObject(quarks);
                      }
                      finally{
                      output.close();
                      }
                      }
                      catch(IOException ex){
                      fLogger.log(Level.SEVERE, "Cannot perform output.", ex);
                      }

                      //deserialize the quarks.ser file
                      //note the use of abstract base class references

                      try{
                      //use buffering
                      InputStream file = new FileInputStream( "quarks.ser" );
                      InputStream buffer = new BufferedInputStream( file );
                      ObjectInput input = new ObjectInputStream ( buffer );
                      try{
                      //deserialize the List
                      List<String> recoveredQuarks = (List<String>)input.readObject();
                      //display its data
                      for(String quark: recoveredQuarks){
                      System.out.println("Recovered Quark: " + quark);
                      }
                      }
                      finally{
                      input.close();
                      }
                      }
                      catch(ClassNotFoundException ex){
                      fLogger.log(Level.SEVERE, "Cannot perform input. Class not found.", ex);
                      }
                      catch(IOException ex){
                      fLogger.log(Level.SEVERE, "Cannot perform input.", ex);
                      }





                      share|improve this answer













                      you can also do this way create a Serializable List



                      List<String> quarks = Arrays.asList(
                      "up", "down", "strange", "charm", "top", "bottom"
                      );

                      //serialize the List
                      //note the use of abstract base class references

                      try{
                      //use buffering
                      OutputStream file = new FileOutputStream( "quarks.ser" );
                      OutputStream buffer = new BufferedOutputStream( file );
                      ObjectOutput output = new ObjectOutputStream( buffer );
                      try{
                      output.writeObject(quarks);
                      }
                      finally{
                      output.close();
                      }
                      }
                      catch(IOException ex){
                      fLogger.log(Level.SEVERE, "Cannot perform output.", ex);
                      }

                      //deserialize the quarks.ser file
                      //note the use of abstract base class references

                      try{
                      //use buffering
                      InputStream file = new FileInputStream( "quarks.ser" );
                      InputStream buffer = new BufferedInputStream( file );
                      ObjectInput input = new ObjectInputStream ( buffer );
                      try{
                      //deserialize the List
                      List<String> recoveredQuarks = (List<String>)input.readObject();
                      //display its data
                      for(String quark: recoveredQuarks){
                      System.out.println("Recovered Quark: " + quark);
                      }
                      }
                      finally{
                      input.close();
                      }
                      }
                      catch(ClassNotFoundException ex){
                      fLogger.log(Level.SEVERE, "Cannot perform input. Class not found.", ex);
                      }
                      catch(IOException ex){
                      fLogger.log(Level.SEVERE, "Cannot perform input.", ex);
                      }






                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Mar 23 '12 at 10:55









                      Riddhish.ChaudhariRiddhish.Chaudhari

                      7121522




                      7121522























                          0














                          You can do something similar to this:



                          https://commons.apache.org/sandbox/flatfile/xref/org/apache/commons/flatfile/util/ConcatenatedInputStream.html



                          It just implements the read() method of InputStream and has a list of InputStreams it is concatenating. Once it reads an EOF it starts reading from the next InputStream. Just convert the Strings to ByteArrayInputStreams.






                          share|improve this answer




























                            0














                            You can do something similar to this:



                            https://commons.apache.org/sandbox/flatfile/xref/org/apache/commons/flatfile/util/ConcatenatedInputStream.html



                            It just implements the read() method of InputStream and has a list of InputStreams it is concatenating. Once it reads an EOF it starts reading from the next InputStream. Just convert the Strings to ByteArrayInputStreams.






                            share|improve this answer


























                              0












                              0








                              0







                              You can do something similar to this:



                              https://commons.apache.org/sandbox/flatfile/xref/org/apache/commons/flatfile/util/ConcatenatedInputStream.html



                              It just implements the read() method of InputStream and has a list of InputStreams it is concatenating. Once it reads an EOF it starts reading from the next InputStream. Just convert the Strings to ByteArrayInputStreams.






                              share|improve this answer













                              You can do something similar to this:



                              https://commons.apache.org/sandbox/flatfile/xref/org/apache/commons/flatfile/util/ConcatenatedInputStream.html



                              It just implements the read() method of InputStream and has a list of InputStreams it is concatenating. Once it reads an EOF it starts reading from the next InputStream. Just convert the Strings to ByteArrayInputStreams.







                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Mar 23 '12 at 10:59









                              benmmurphybenmmurphy

                              1,93811626




                              1,93811626























                                  0














                                  You can create some kind of IterableInputStream



                                  public class IterableInputStream<T> extends InputStream {

                                  public static final int EOF = -1;

                                  private static final InputStream EOF_IS = new InputStream() {
                                  @Override public int read() throws IOException {
                                  return EOF;
                                  }
                                  };

                                  private final Iterator<T> iterator;
                                  private final Function<T, byte> mapper;

                                  private InputStream current;

                                  public IterableInputStream(Iterable<T> iterable, Function<T, byte> mapper) {
                                  this.iterator = iterable.iterator();
                                  this.mapper = mapper;
                                  next();
                                  }

                                  @Override
                                  public int read() throws IOException {
                                  int n = current.read();
                                  while (n == EOF && current != EOF_IS) {
                                  next();
                                  n = current.read();
                                  }
                                  return n;
                                  }

                                  private void next() {
                                  current = iterator.hasNext()
                                  ? new ByteArrayInputStream(mapper.apply(iterator.next()))
                                  : EOF_IS;
                                  }
                                  }


                                  To use it



                                  public static void main(String args) throws IOException {
                                  Iterable<String> strings = Arrays.asList("1", "22", "333", "4444");
                                  try (InputStream is = new IterableInputStream<String>(strings, String::getBytes)) {
                                  for (int b = is.read(); b != -1; b = is.read()) {
                                  System.out.print((char) b);
                                  }
                                  }
                                  }





                                  share|improve this answer




























                                    0














                                    You can create some kind of IterableInputStream



                                    public class IterableInputStream<T> extends InputStream {

                                    public static final int EOF = -1;

                                    private static final InputStream EOF_IS = new InputStream() {
                                    @Override public int read() throws IOException {
                                    return EOF;
                                    }
                                    };

                                    private final Iterator<T> iterator;
                                    private final Function<T, byte> mapper;

                                    private InputStream current;

                                    public IterableInputStream(Iterable<T> iterable, Function<T, byte> mapper) {
                                    this.iterator = iterable.iterator();
                                    this.mapper = mapper;
                                    next();
                                    }

                                    @Override
                                    public int read() throws IOException {
                                    int n = current.read();
                                    while (n == EOF && current != EOF_IS) {
                                    next();
                                    n = current.read();
                                    }
                                    return n;
                                    }

                                    private void next() {
                                    current = iterator.hasNext()
                                    ? new ByteArrayInputStream(mapper.apply(iterator.next()))
                                    : EOF_IS;
                                    }
                                    }


                                    To use it



                                    public static void main(String args) throws IOException {
                                    Iterable<String> strings = Arrays.asList("1", "22", "333", "4444");
                                    try (InputStream is = new IterableInputStream<String>(strings, String::getBytes)) {
                                    for (int b = is.read(); b != -1; b = is.read()) {
                                    System.out.print((char) b);
                                    }
                                    }
                                    }





                                    share|improve this answer


























                                      0












                                      0








                                      0







                                      You can create some kind of IterableInputStream



                                      public class IterableInputStream<T> extends InputStream {

                                      public static final int EOF = -1;

                                      private static final InputStream EOF_IS = new InputStream() {
                                      @Override public int read() throws IOException {
                                      return EOF;
                                      }
                                      };

                                      private final Iterator<T> iterator;
                                      private final Function<T, byte> mapper;

                                      private InputStream current;

                                      public IterableInputStream(Iterable<T> iterable, Function<T, byte> mapper) {
                                      this.iterator = iterable.iterator();
                                      this.mapper = mapper;
                                      next();
                                      }

                                      @Override
                                      public int read() throws IOException {
                                      int n = current.read();
                                      while (n == EOF && current != EOF_IS) {
                                      next();
                                      n = current.read();
                                      }
                                      return n;
                                      }

                                      private void next() {
                                      current = iterator.hasNext()
                                      ? new ByteArrayInputStream(mapper.apply(iterator.next()))
                                      : EOF_IS;
                                      }
                                      }


                                      To use it



                                      public static void main(String args) throws IOException {
                                      Iterable<String> strings = Arrays.asList("1", "22", "333", "4444");
                                      try (InputStream is = new IterableInputStream<String>(strings, String::getBytes)) {
                                      for (int b = is.read(); b != -1; b = is.read()) {
                                      System.out.print((char) b);
                                      }
                                      }
                                      }





                                      share|improve this answer













                                      You can create some kind of IterableInputStream



                                      public class IterableInputStream<T> extends InputStream {

                                      public static final int EOF = -1;

                                      private static final InputStream EOF_IS = new InputStream() {
                                      @Override public int read() throws IOException {
                                      return EOF;
                                      }
                                      };

                                      private final Iterator<T> iterator;
                                      private final Function<T, byte> mapper;

                                      private InputStream current;

                                      public IterableInputStream(Iterable<T> iterable, Function<T, byte> mapper) {
                                      this.iterator = iterable.iterator();
                                      this.mapper = mapper;
                                      next();
                                      }

                                      @Override
                                      public int read() throws IOException {
                                      int n = current.read();
                                      while (n == EOF && current != EOF_IS) {
                                      next();
                                      n = current.read();
                                      }
                                      return n;
                                      }

                                      private void next() {
                                      current = iterator.hasNext()
                                      ? new ByteArrayInputStream(mapper.apply(iterator.next()))
                                      : EOF_IS;
                                      }
                                      }


                                      To use it



                                      public static void main(String args) throws IOException {
                                      Iterable<String> strings = Arrays.asList("1", "22", "333", "4444");
                                      try (InputStream is = new IterableInputStream<String>(strings, String::getBytes)) {
                                      for (int b = is.read(); b != -1; b = is.read()) {
                                      System.out.print((char) b);
                                      }
                                      }
                                      }






                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered Nov 16 '18 at 3:10









                                      Mike ShauneuMike Shauneu

                                      1,743915




                                      1,743915






























                                          draft saved

                                          draft discarded




















































                                          Thanks for contributing an answer to Stack Overflow!


                                          • Please be sure to answer the question. Provide details and share your research!

                                          But avoid



                                          • Asking for help, clarification, or responding to other answers.

                                          • Making statements based on opinion; back them up with references or personal experience.


                                          To learn more, see our tips on writing great answers.




                                          draft saved


                                          draft discarded














                                          StackExchange.ready(
                                          function () {
                                          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f9837754%2fjava-accessing-a-list-of-strings-as-an-inputstream%23new-answer', 'question_page');
                                          }
                                          );

                                          Post as a guest















                                          Required, but never shown





















































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown

































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown







                                          Popular posts from this blog

                                          List item for chat from Array inside array React Native

                                          Thiostrepton

                                          Caerphilly