This question already has answers here:
Java - Is ByteArrayOutputStream safe without flush() and close()?
(3 answers)
Closed 6 years ago.
Having a java.awt.image.BufferedImage I'm getting and returning a ByteArrayOutputStream by:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write( combined, "png", baos );
return baos;
Then I generate a base64 representation to be returned on a REST endpoint:
return new String(Base64.encodeBase64(baos.toByteArray()), Charset.forName("UTF-8"));
My question is: should I flush and close the baos?
(I've never understood properly when I should close a baos and when not, so any tip will be appreciated)
My question is: should I flush and close the baos?
The good practice would be to always close an OutputStream but in case of a ByteArrayOutputStream, the methods flush and close don't do anything so it is not required (check the links to see by yourself).
From the Javadoc of close()
Closing a ByteArrayOutputStream has no effect.
From the Javadoc of OutputStream#flush() (since ByteArrayOutputStream doesn't override it)
The flush method of OutputStream does nothing.
It works like this:
the flush() method will some sort of push all remaining elements to their destination, like when you flush the toilet.
before using close() you should use flush() in order to make sure there isn't anything remaining, because if you close without everything sent it will probably get lost.
You should use flush() and close() after you have 'used the stream'.
This works for all OutputStreams.
Related
Here is an example code
ByteArrayOutputStream baos = new ByteArrayOutputStream(bufSize);
GZIPOutputStream gzos = new GZIPOutputStream1(baos);
gzos.write(...)
...
gzos.write(...)
...
// Would the content get flushed properly?
gzos.flush()
byte[] bytes = baos.toByteArray();
// Use bytes wherever you want
...
// Would this reset things for gzos?
baos.reset()
gzos.write(...)
...
gzos.write(...)
...
bytes = baos.toByteArray();
...
So, once the compressed byte array is used somewhere, I want to reset the stream. I have two concerns. I read somewhere that GZIPOutputStream's flush method do not necessarily always flushes the content? Is that true still for Java 7? If that works, is calling reset of the ByteArrayOutputStream object enough to reset things for the GZIPOutputStream object?
I read somewhere that GZIPOutputStream's flush method do not necessarily always flushes the content?
It depends on what GZIPOutputStream constructor you use. If you create a compressor passing true to boolean syncFlush, any flush() call will flush both compressor and output stream, respectively. If false, only the output strem will flush.
Is that true still for Java 7?
The behavior you described happened in Java 6. This syncFlush parameter is available since Java 7. It' in Java 8, of course.
If that works, is calling reset of the ByteArrayOutputStream object enough to reset things for the GZIPOutputStream object?
Yes, it seems so.
I am trying to convert an OutputStream to a ByteArrayOutput Stream. I was unable to find any clear simple answers on how to do this. This question was asked in the title of the question on StackOverflow, but the body of the question aske how to change a ByteArrayStream to OuputStream. I have an OutputStream that is already created and this example given in the answer will not compile!
That Question is Here
I have an OutputStream that is already constructed and has a length of 44 bytes called waveHeader. I want to convert that to a ByteArrayOutputStream because I want to be able to change that into a byte[] with waveHeader.ToByteArray() for simplicity in later processes;
Is there a simple type of casting or something that will allow this?
If not then:
Is there a way to construct a pointer to the data in the original OutputStream if it is not possible to convert it?
How would someone go about accessing the data that is contained in the OutputStream?
I am new to JAVA. This is just a hobby for me. Streams In VisualBasic .net where much easier!
There are multiple possible scenarios:
a) You have a ByteArrayOutputStream, but it was declared as OutputStream. Then you can do a cast like this:
void doSomething(OutputStream os)
{
// fails with ClassCastException if it is not a BOS
ByteArrayOutputStream bos = (ByteArrayOutputStream)os;
...
b) if you have any other type of output stream, it does not really make sense to convert it to a BOS. (You typically want to cast it, because you want to access the result array). So in this case you simple set up a new stream and use it.
void doSomething(OutputStream os)
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(something);
bos.close();
byte[] arr = bos.toByteArray();
// what do you want to do?
os.write(arr); // or: bos.writeTo(os);
...
c) If you have written something to any kind of OutputStream (which you do not know what it is, for example because you get it from a servlet), there is no way to get that information back. You must not write something you need later. A solution is the answer b) where you write it in your own stream, and then you can use the array for your own purpose as well as writing it to the actual output stream.
Keep in mind ByteArrayOutputStreams keep all Data in Memory.
You could use the writeTo method of ByteArrayOutputStream.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] bytes = new byte[8];
bos.write(bytes);
bos.writeTo(oos);
You can create an instance of ByteArrayOutputStream. You then need to write the data to this ByteOutputStream instance and then using the writeTo method, which accepts an OutputStream, you can enable the ByteArrayOutputStream to write the output, to the instance of OutputStream which you passed as the argument.
Hope it works!
You can use toByteArray function on the output stream you have.That's is let say you have outputStream buffer So you can do buffer.toByteArray .
For more you can look at the answer of Convert InputStream to byte array in Java .
I know it has been the point of many previous questions to close or not to close a ServletOutputStream like here: Should I close the servlet outputstream? or here: Should one call .close() on HttpServletResponse.getOutputStream()/.getWriter()? or with another focus here: Do I need to flush the servlet outputstream?
The general consensus seems to be not to close it because you are not owning it in a more strict sense. (The HttpServletResponse owns it.)
But what about e.g. these constructs:
PrintWriter out = new PrintWriter( new OutputStreamWriter( resp.getOutputStream(), MY.ENCODING ) );
Now I'm clearly the owner of the PrintWriter which has some additional buffers which at least needs to get flushed (and which are flushed e.g. by closing it).
What is the general consensus here? Do I need to close the PrintWriter (or any other such construct as for this matter.)?
EDIT: There are valid arguments for closing the stream, too. Notable e.g. not wanting something else writing on the stream. And meanwhile we have with try-with-resource constructs which might change the picture. See my other question here: Eclipse complaining over resource leak when not closing ServletOutputStream
This might change nothing (and my general feeling is to not close the stream, too) but try-with-resource above all literally screams for code like:
try( Something out = new Something( resp.getOutputStream() ) ){
out.print( "Foo" );
}
instead of
Something out;
try {
out = new Something( resp.getOutputStream() );
out.print( "Foo" )
} finally {
if( out != null && out.isUnFlushedWhatever() ) out.flush();
}
The OutputStream is something you're not creating, you just query a reference to it with ServletResponse.getOutputStream(). Therefore if you put something around it (e.g. OutputStreamWriter or ZipOutputStream) the wrapper stream or writer will just write to it.
It is implementation dependant whether closing a wrapper stream or writer closes the underlying stream, so you should not close that. But since in most of the cases the wrappers only use the underlying stream to write bytes, it is more than enough to flush the wrapper.
In cases where the wrapper needs some finalizing, it should be (and generally is) the wrapper's responsibility to provide this finalizing functionality in a separate method. For example ZipOutputStream provides a finish() method which finishes writing the contents of the ZIP output stream without closing the underlying stream.
Summarizing:
You should not close the wrapper, but check if it provides some finalizing method without closing the underlying stream, which you should obviously call.
In short I need to do two things with one stream.
I need to pass a stream through a method to see if the bytes of that stream are of a particular type.
I need to create a new class using that stream once that check is completed.
I'm very new to streams and I know that they are "one way streets." So I think I have a bad design in my code or something if I find myself needing to reuse a stream.
Here is a snippit of the logic:
byte[] header = new byte[1024];
//reads entire array or until EOF whichever is first
bis.mark(header.length);
bis.read(header);
if(isFileType(header)) {
bis.reset();
_data.put(fileName, new MyClass(bis)); // Stream is now closed...
methodForFinalBytes(bis);
} else {
// Do other stuff;
}
It depends entirely on whether the InputStream implementation supports mark(). See http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#markSupported(). Calling reset() on a stream that doesn't support mark() may throw an exception.
BufferedInputStream and ByteArrayInputStream support mark(), but others don't.
Generally, you can't reset an InputStream to get back to the start. There are, however the mark() / reset() methods, which make a stream remember the current position and you can rewind the stream to the marked position with reset().
Problem is, they are optional and may not be supported by the particular stream class in use. BufferedInputStream does support mark() / reset() (although within buffer limits). You can wrap your InputStream in a BufferedInputStream, immediately mark() and then run your detection code (but make sure it does not read ahead further than the buffer size, you can specify the buffer size in the BufferedInputStream constrcutor). Then call reset() and really read the stream.
EDIT: If you use ByteArrayInputStream anyway, that one supports mark/reset over its entire length (naturally).
My code is:
InputStream confFile=classLoader.getResourceAsStream("myconffile.properties");
In docs:
The close method of InputStream does nothing.
Does it mean that I don't need close InputStream?
You do need to close the input Stream, because the stream returned by the method you mention is actually FileInputStream or some other subclass of InputStream that holds a handle for a file. If you do not close this stream you have resource leakage.
No, it does not mean that - because InputStream is an abstract class, and getResourceAsStream() returns a concrete subclass whose close() method does something - most importantly free a file handle.