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 .
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.
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.
I wrote a file using Java's FileChannel class that uses RandomAccessFiles. I wrote objects at various locations in the file. The objects were of variable sizes but all of the same class. I wrote the objects using the following idea :
ByteArrayOutputStream bos= new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(r);
byte[] recordBytes= bos.toByteArray();
ByteBuffer rbb= ByteBuffer.wrap(recordBytes);
while(rbb.hasRemaining()) {
fileChannel.write(rbb);
}
Now I want to read from such a file. I dont want to have to specify the number of bytes to read. I want to be able to read the object directly using Object Input Stream. How to achieve this ?
I have to use Random Access Files because I need to write to different positions in file. I am also recording in a separate data structure, the locations where objects have been written.
I have to use Random Access Files because I need to write to different
positions in file.
No, you don't. You can reposition a FileOutputStream or FileInputStream via its channel.
That would significantly simplify your writing code as well: you wouldn't need to use the buffer or channel, and depending on your needs you could omit the ByteArrayOutputStream as well. However, as you note in a comment, you won't know the size of the object in advance, and the ByteArrayOutputStream is a useful way to verify that you don't overrun your allotted space.
Object obj = // something
FileOutputStream fos = // an initialized stream
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
if (bos.size() > MAX_ALLOWED_SIZE)
throw // or log, or whatever you want to do
else
{
fos.getChannel().position(writeLocation);
bos.writeTo(fos);
}
To read the objects, do the following:
FileInputStream fis = // an initialized stream
fis.getChannel().position(offsetOfSerializedObject);
ObjectInputStream iis = new ObjectInputStream(new BufferedInputStream(fis));
Object obj = iis.readObject();
One comment here: I wrapped the FileInputStream in a BufferedInputStream. In this specific case, where the file stream is repositioned before each use, that can provide a performance benefit. Be aware, however, that the buffered stream can read more bytes than are needed, and there are some situations using construct-as-needed object streams where it would be a really bad idea.
Why doesn't seek work for you? I believe you need to seek() to correct locations and then just read objects using your object stream. Also, if you store the correct locations of serialized objects, why don't you store their sizes? In this case you may apply ObjectInputStream against bytes you read from file.
The simplest solution that comes to mind is to write out the length of the array before writing out the array itself:
while(rbb.hasRemaining()) {
fileChannel.writeLong(recordBytes.length);
fileChannel.write(rbb);
}
When reading the object, you first read the length. This'll tell you how many further bytes to read to get your object. Similarly to what you are already doing on the writing side, you could read the data into a byte[] and then use ByteArrayInputputStream and ObjectInputStream.
You could use a FileInputStream constructed on the RandomAccesFile's FileDescriptor object, like so:
FileDescriptor f = raf.getFD();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
Assuming that the RandomAccessFile is called raf.
I've got multiple objects stored in a file .This is regarding the ObjectInputStream. If I've got the below code:
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj1 = (Object)ois.readObject();
ois.close();
ois = new ObjectInputStream(fis);
Object obj2 = (Object)ois.readObject();
My question is : will the readObject called from the second Object stream (obj2) be the 1st or 2nd object in the file
It will infact throw an exception. Calling close on the ObjectInputStream will close the FileInputStream as well.
It depends on how you stored the objects. If you used one single ObjectOutputStream, then you better also use one single ObjectInputStream.
If you used separate streams for the output, you also should use separate streams for the input. But this is not really recommended.
For your "persistent queue", I would recommend something like this:
On the sending side:
Create a ByteArrayOutputStream, wrap an ObjectOutputStream around it.
Write the object to the OOS, and close the OOS.
Get the byte[], and write it together with a header indicating the length to your queue-stream.
On the receiving side:
read a header length from the queue stream.
read a byte[] of the given length from the queue stream.
create an ByteArrayInputStream from this array, and wrap an ObjectInputStream around it.
read one object from the OIS, close the OIS.
When you store parts of your queue, make sure to always store whole messages (i.e. the header together with the object).
Of course, it might be easier to use already existing solutions, like JMS (where you would create an ObjectMessage, and submit it to the queue).
How to convert string to stream in java without using bytearrayinputstream and example?
You could extend the InputStream class and implement the read() method such that it returns data from a String.
But it would be really useless to do that when using a ByteArrayInputStream is so much simpler and easier.
InputStream is = new StringInputStream(string);