store whole InputStream in a String

G

Guest

Can I write all contents of an InputStream to a String at once?

something like

String a = inputStream.readAll();
 
A

ak

Can I write all contents of an InputStream to a String at once?
something like

String a = inputStream.readAll();
sure:

public String readAll(InputStream inputStream) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte [] buffer = new byte[1024];
while(true) {
int len = inputStream.read[buffer];
if(len < 0) {
break;
}
bout.write(buffer, 0, len);
}
byte [] data = bout.toByteArray();
return new String(data);
}

String a = readAll(in);
 
P

Paul Lutus

ak said:
Can I write all contents of an InputStream to a String at once?

something like

String a = inputStream.readAll();
sure:

public String readAll(InputStream inputStream) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte [] buffer = new byte[1024];
while(true) {
int len = inputStream.read[buffer];
if(len < 0) {
break;
}
bout.write(buffer, 0, len);
}

??? Please consider the following, and avoid constructions like
"while(true)" and "break" when possible:

int len;

while((len = inputStream.read[buffer]) > 0) {
bout.write(buffer, 0, len);
}
 
M

Mike Schilling

Paul Lutus said:
ak said:
Can I write all contents of an InputStream to a String at once?

something like

String a = inputStream.readAll();
sure:

public String readAll(InputStream inputStream) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte [] buffer = new byte[1024];
while(true) {
int len = inputStream.read[buffer];
if(len < 0) {
break;
}
bout.write(buffer, 0, len);
}

??? Please consider the following, and avoid constructions like
"while(true)" and "break" when possible:

int len;

while((len = inputStream.read[buffer]) > 0) {
bout.write(buffer, 0, len);
}

I find the other version clearer, myself. The nesting of method call and
test in the while statement is too much information in one line, and it's
unfortunate to declare len outside the loop that it's only used inside of.
 
P

Paul Lutus

Mike said:
Paul Lutus said:
ak said:
Can I write all contents of an InputStream to a String at once?

something like

String a = inputStream.readAll();

sure:

public String readAll(InputStream inputStream) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte [] buffer = new byte[1024];
while(true) {
int len = inputStream.read[buffer];
if(len < 0) {
break;
}
bout.write(buffer, 0, len);
}

??? Please consider the following, and avoid constructions like
"while(true)" and "break" when possible:

int len;

while((len = inputStream.read[buffer]) > 0) {
bout.write(buffer, 0, len);
}

I find the other version clearer, myself.

You can't be serious. The original arrangement has two control structures
where only one is needed. Also, both "while(true)" and "break" are frowned
upon in any case where they are not required. They are not particularly
good examples of structure programming.

A while() clause should actually perform a test, not be added as a patch to
create a loop that must later be broken out of, by force, using break.
The nesting of method call and
test in the while statement is too much information in one line,

1. A for-loop typically contains one additional piece of information (three
instead of two items as in my example). Want to object to that also?

2. Compared to the original, this version is simpler to read and interpret.
It is also better coding practice -- it doesn't misuse while().
and it's
unfortunate to declare len outside the loop that it's only used inside of.

I could instead have said:

for (int len = inputStream.read[buffer]); len > 0;) {
}

But this replaces one arbitrary choice with another, and uses a for clause
in a place where it is not the ideal choice.

In any case, writing "while(true)" simply builds a perpetual loop that
requires "break" to terminate, creating the illusion of appropriate usage.
 
V

Vincent Lascaux

1. A for-loop typically contains one additional piece of information
(three
instead of two items as in my example). Want to object to that also?

Although I agree with you for the while loop, I don't think that this is a
good example. A for loop should always be that kind (I think):

for(T i = start; i<end; i++)
(where T could be int, Iterator...)

There is only few information here: start and end, and assuming you are
always using the for loop that way, you get use to it and understand easily
the statement
I could instead have said:

for (int len = inputStream.read[buffer]); len > 0;) {
}

And this is the example of what not to do. First I'm not sure it would
compile, then it should be
for(int len = inputStream.read(buffer); len>0; len =
inputStream.read(buffer)) {
//...
}

And this is too much... ;)
 
P

Paul Lutus

Vincent said:
Although I agree with you for the while loop, I don't think that this is a
good example. A for loop should always be that kind (I think):

for(T i = start; i<end; i++)
(where T could be int, Iterator...)

No. The third field is optional. If T is an iterator, one might want to:

for(T i = start; i.hasNext();) {
something q = i.next();
}

Which makes it exactly like my example. The third clause in the for-loop
construct is optional and one sees code shaped this way regularly.
There is only few information here: start and end, and assuming you are
always using the for loop that way, you get use to it and understand
easily the statement

But a typical use is not the only acceptable use.
I could instead have said:

for (int len = inputStream.read[buffer]); len > 0;) {
}

And this is the example of what not to do.

Quite false. It is entirely appropriate and a common coding practice.
First I'm not sure it would
compile,

I compiled it, then posted it. You could do the same.
then it should be
for(int len = inputStream.read(buffer); len>0; len =
inputStream.read(buffer)) {

What? No wonder you think there's something wrong. Your example is broken
(it discards the first block of input), mine is not.
//...
}

And this is too much... ;)

Yes, if you take my working example and render it unworkable, then it won't
work.
 
A

ak

int len = inputStream.read[buffer];
while(len > 0) {
bout.write(buffer, 0, len);
len = inputStream.read[buffer];
}

or

for(int len = inputStream.read[buffer]; len > 0;) {
bout.write(buffer, 0, len);
len = inputStream.read[buffer];
}
 
P

Paul Lutus

ak said:
int len = inputStream.read[buffer];
while(len > 0) {
bout.write(buffer, 0, len);
len = inputStream.read[buffer];
}

A maintenance nightmare. This is an example of the kind of coding practice
that drives software administrators up the wall. Always avoid this silly
construction, the kind that uses two identical lines of code to avoid a
little thought.

Summary: Never write two identical lines of code when you can instead write
one.
or

for(int len = inputStream.read[buffer]; len > 0;) {
bout.write(buffer, 0, len);
len = inputStream.read[buffer];
}

Same nightmare, different pillow.
 
M

Mike Schilling

Paul Lutus said:
Mike said:
Paul Lutus said:
ak wrote:

Can I write all contents of an InputStream to a String at once?

something like

String a = inputStream.readAll();

sure:

public String readAll(InputStream inputStream) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte [] buffer = new byte[1024];
while(true) {
int len = inputStream.read[buffer];
if(len < 0) {
break;
}
bout.write(buffer, 0, len);
}

??? Please consider the following, and avoid constructions like
"while(true)" and "break" when possible:

int len;

while((len = inputStream.read[buffer]) > 0) {
bout.write(buffer, 0, len);
}

I find the other version clearer, myself.

You can't be serious. The original arrangement has two control structures
where only one is needed. Also, both "while(true)" and "break" are frowned
upon in any case where they are not required. They are not particularly
good examples of structure programming.

I am entirely serious.
A while() clause should actually perform a test, not be added as a patch
to
create a loop that must later be broken out of, by force, using break.


1. A for-loop typically contains one additional piece of information
(three
instead of two items as in my example). Want to object to that also?

They're nicely punctuated..
2. Compared to the original, this version is simpler to read and
interpret.
It is also better coding practice -- it doesn't misuse while().
and it's
unfortunate to declare len outside the loop that it's only used inside
of.

I could instead have said:

for (int len = inputStream.read[buffer]); len > 0;) {
}

But this replaces one arbitrary choice with another, and uses a for clause
in a place where it is not the ideal choice.

And it's wrong :) It reads from the stream only once, rather than each
time through the loop. You need

len = inputStream.read[buffer]

as the iteration clause.
In any case, writing "while(true)" simply builds a perpetual loop that
requires "break" to terminate, creating the illusion of appropriate usage.


You make a lot of absolute assertions. I disagree with many of them. I'm
not sure what that leaves us to discuss.
 
M

Mike Schilling

Paul Lutus said:
What? No wonder you think there's something wrong. Your example is broken
(it discards the first block of input), mine is not.

No, try it. That loop is entirely correct. Yours only reads from the
stream once.
 
V

Vincent Lascaux

for(T i = start; i<end; i++)
No. The third field is optional. If T is an iterator, one might want to:

for(T i = start; i.hasNext();) {
something q = i.next();
}

Yes... I would actually have voted for something like

for(Iterator i = start; i.hasNext(); i.next()) {
something q = i.current();
}

The C# and C++ STL iterators work like that (well, same idea), and I am more
used to reading a for statement with an "inc" as a third "parameter"
I could instead have said:

for (int len = inputStream.read[buffer]); len > 0;) {
}

And this is the example of what not to do.

Quite false. It is entirely appropriate and a common coding practice.

Actually, all the while loop could be written as a for loop (while(cond) {
body; } is like for(;cond;) { body; }, with the benefit for the second
version to have a smiley in it). So I think you have to make a rule for
where to use while and where to use for.
I would reserve the for statement for an iteration over a limited number of
elements, like an array or the numbers from 0 to 100 for example. To me it
is important to find in a for statement a starting value, an ending value
and an incrementation. Else I would prefer using a while loop.
But my "what not to do" was probably too strong (apologize for that). I feel
it more unreadable than the while((len = inputStream.read(buffer))>0) { }. I
really think a while statement should be used in that case. My "what not to
do" was also here because I feel your code doesnt act as intended (see
further).
I compiled it, then posted it. You could do the same.

It dont manage to compile it. I'm using Java 1.4.2... maybe it's the reason?
Has a new version of the language introduced something with more closing
parenthesis than opening ones? If so, I don't like it :p
What? No wonder you think there's something wrong. Your example is broken
(it discards the first block of input), mine is not.

I think that
for(Init; Cond; Inc) { Body; }
is equivalent to { Init; while(Cond) { Body; Inc; } }

So my loop is equivalent to
{ int len = inputStream.read(buffer); while(len>0) { /* Body */ len =
inputStream.read(buffer); } }
To me it doesnt look like any block of input is discarded by that.

If I understand your code (I am not sure I do), and if it is equivalent to
for(int len = inputStream.read(buffer); len>0; ) { /* Body */ }
then it is equivalent to
{ int len = inputStream.read(buffer); while(len>0) { /* Body */ } }
Since /*Body*/ is not supposed to change len, you have an infinite loop (for
a non empty inputStream)
 
A

ak

int len = inputStream.read[buffer];
while(len > 0) {
bout.write(buffer, 0, len);
len = inputStream.read[buffer];
}

A maintenance nightmare. This is an example of the kind of coding practice
that drives software administrators up the wall. Always avoid this silly
construction, the kind that uses two identical lines of code to avoid a
little thought.

there is nothing wrong if len initialized with same code as incremented.
Summary: Never write two identical lines of code when you can instead write
one.
even if this one line looks ugly?
 
A

ak

int len = inputStream.read[buffer];
while(len > 0) {
bout.write(buffer, 0, len);
len = inputStream.read[buffer];
}

A maintenance nightmare. This is an example of the kind of coding practice
that drives software administrators up the wall. Always avoid this silly
construction, the kind that uses two identical lines of code to avoid a
little thought.

Summary: Never write two identical lines of code when you can instead write
one.

ok, what is with folowing, also nightmare?

int len;
do {
len = inputStream.read[buffer];
if(len > 0) {
bout.write(buffer, 0, len);
}
}while(len > 0);

or better:

int len;
do {
len = inputStream.read[buffer];
writeBuffer(buffer, len, bout);
}

private static void writeBuffer(byte [] buffer, int len, OutputStream out) {
if(len > 0) {
out.write(buffer, 0, len);
}
}
 
T

Tony Morris

I'm waiting for someone to notice in this thread, as I thought it was
inevitable, but to no avail.

Take a closer look at the following line of code that I keep seeing posted:

int len = inputStream.read[buffer];

Side Note: I'm with Paul Lutus all the way so far, but then, I'm more of a
"purist" than most.
 
P

Paul Lutus

Mike said:
Paul Lutus said:
Mike said:
ak wrote:

Can I write all contents of an InputStream to a String at once?

something like

String a = inputStream.readAll();

sure:

public String readAll(InputStream inputStream) {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte [] buffer = new byte[1024];
while(true) {
int len = inputStream.read[buffer];
if(len < 0) {
break;
}
bout.write(buffer, 0, len);
}

??? Please consider the following, and avoid constructions like
"while(true)" and "break" when possible:

int len;

while((len = inputStream.read[buffer]) > 0) {
bout.write(buffer, 0, len);
}


I find the other version clearer, myself.

You can't be serious. The original arrangement has two control structures
where only one is needed. Also, both "while(true)" and "break" are
frowned upon in any case where they are not required. They are not
particularly good examples of structure programming.

I am entirely serious.

Then I don't know what to say. I posted the appropriate construction, the
one that confers the greatest reliability and maintainability, the one that
is most consistent with structured prorgamming principles. Then (see below,
as as you point out) I managed to post a bronken version of the same idea.
They're nicely punctuated..

:) Not terribly relevant.
2. Compared to the original, this version is simpler to read and
interpret.
It is also better coding practice -- it doesn't misuse while().
and it's
unfortunate to declare len outside the loop that it's only used inside
of.

I could instead have said:

for (int len = inputStream.read[buffer]); len > 0;) {
}

But this replaces one arbitrary choice with another, and uses a for
clause in a place where it is not the ideal choice.

And it's wrong :) It reads from the stream only once, rather than each
time through the loop.

I should have tested it and posted more carefully. I meant to say:

for (int len;(len = inputStream.read[buffer])) > 0;) {
}

In other words, the same construction I have been advocating with a minor
variation to change the scope of the variable.

You need

len = inputStream.read[buffer]

as the iteration clause.
In any case, writing "while(true)" simply builds a perpetual loop that
requires "break" to terminate, creating the illusion of appropriate
usage.


You make a lot of absolute assertions. I disagree with many of them.

This is a programming principle, not a debate about something vague,
something about which there is any dispute. Reliable, maintainable code
doesn't arise by accident.
I'm
not sure what that leaves us to discuss.

I agree. This is not a matter for any kind of debate.
 
P

Paul Lutus

Tony said:
I'm waiting for someone to notice in this thread, as I thought it was
inevitable, but to no avail.

Take a closer look at the following line of code that I keep seeing
posted:

int len = inputStream.read[buffer];

Yes, it should be:

int len = inputStream.read(buffer);

But I haven't been compiling anything (as should be obvious from my other
error).
 
P

Paul Lutus

Mike said:
You like infinite for loops? :)

It would not have been infinite had I been paying attention to what I was
posting. The correct version looks so much like the original while clause
that there is scarcely any point in posting it as a variation -- the only
difference is that the "len" variable is local to the loop.

For the record, to correct two errors, one mine, one belonging to the OP:

// using while

int len;

while((len = inputStream.read(buffer)) > 0) {
        bout.write(buffer, 0, len);
}

// using for

for(int len;(len = inputStream.read(buffer)) > 0;) {
        bout.write(buffer, 0, len);
}

Apologies to all for my laziness.
 
P

Paul Lutus

Vincent Lascaux wrote:

/ ...
If I understand your code (I am not sure I do), and if it is equivalent to
for(int len = inputStream.read(buffer); len>0; ) { /* Body */ }
then it is equivalent to
{ int len = inputStream.read(buffer); while(len>0) { /* Body */ } }
Since /*Body*/ is not supposed to change len, you have an infinite loop
(for a non empty inputStream)

I got lazy, and I thank you for your correction. The correct for-loop looks
very much like the while-loop, differing only in that the "len" variable is
made local to the loop. I only offered the for-loop version because the
objection was raised that "len" was not local.

// using while

int len;

while((len = inputStream.read(buffer)) > 0) {
        bout.write(buffer, 0, len);
}

// using for

for(int len;(len = inputStream.read(buffer)) > 0;) {
        bout.write(buffer, 0, len);
}

In any case, the problem with those versions that duplicate one line of code
is that there is a duplicate line of code, something professional code
administrators try to avoid at all costs.

The problem with "while(true)" should be obvious to all -- it is a hack, as
is the use of "break" to get around the original hack.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top