user482594
user482594

Reputation: 17476

What is the resource efficient way to generate inputstream?

I am new to Java IO. Currently, I have these lines of code which generates an input stream based on string.

String sb = new StringBuilder();
for(...){
   sb.append(...);
}
String finalString = sb.toString();
byte[] objectBytes = finalString.getBytes(StandardCharsets.UTF_8);
InputStream inputStream = new ByteArrayInputStream(objectBytes);

Maybe, I am misunderstanding something, but is there a better way to generate InputStream from String other than using getBytes()?

For instance, if String is really large, 50MB, and there is no way to create another copy (getBytes() for another 50MB) of it due to resource constraints, it could potentially throw an out of memory error.

I just wanted to know if above lines of code is the efficient way to generate InputStream from String. For instance, is there a way which I can "stream" String into input stream without using additional memory? Like a Reader-like abstraction on top of String?

Upvotes: 3

Views: 73

Answers (3)

Joop Eggen
Joop Eggen

Reputation: 109547

You are producing data, actually writing and you want to almost immediately consume the data, reading.

The Unix technique is to pipe the output of one process to the input of an other process. In java one also needs at least two threads. They will synchronize on producing and consuming.

PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(in);
new Thread(() -> writeAllYouveGot(out)).start();
readAllYouveGot(in);

Here I started a Thread for writing with a Runnable that calls some self-defined method on out. Instead of using new Thread you might prefer an ExecutorService.

Piped I/O is rather seldomly used, though the asynchrone behaviour is optimal. One can even set the pipe's size on the PipedInputStream. The reason for that rare usage, is the need for a second thread.

To complete things, one would probably wrap the binary Input/OutputStreams in new InputStreamReader(in, "UTF-8") and new OutputStreamWriter(out, "UTF-8").

Upvotes: 0

Jacob G.
Jacob G.

Reputation: 29680

I think what you're looking for is a StringReader which is defined as:

A character stream whose source is a string.

To use this efficiently, you would need to know exactly where the bytes are located that you wish to read. It supports both random and sequential access, so you can read the entire String, char by char, if you prefer.

Upvotes: 3

Steve11235
Steve11235

Reputation: 2923

Try something like this (no promises about typos:)

BufferedReader reader = new BufferedRead(new InputStreamReader(yourInputStream), Charset.defaultCharset());
final char[] buffer = new char[8000];
int charsRead = 0;
while(true) {
    charsRead = reader.read(buffer, 0, 8000);
    if (charsRead == -1) {
        break;
    }
    // Do something with buffer
}

The InputStreamReader converts from byte to char, using the Charset. BufferedReader allows you to read blocks of char.

For really large input streams, you may want to process the input in chunks, rather than reading the entire stream into memory and then processing.

Upvotes: -1

Related Questions