How to use ByteArrayOutputStream and DataOutputStream simultaneously in Java? - java

I'm having quite a problem here, and I think it is because I don't understand very much how I should use the API provided by Java.
I need to write an int and a byte[] into a byte[].
I thought of using a DataOutputStream to solve the data writing with writeInt(int i) and write(byte[] b), and to be able to put that into a byte array, I should use ByteArrayOutputStream method toByteArray().
I understand that this classes use the Wrapper pattern, so I had two options:
DataOutputStream w = new DataOutputStream(new ByteArrayOutputStream());
or
ByteArrayOutputStream w = new ByteArrayOutputStream(new DataOutputStream());
but in both cases, I "loose" a method. in the first case, I can't access the toByteArray() method, and in the second, I can't access the writeInt() method.
How should I use this classes together?

Like this:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream w = new DataOutputStream(baos);
w.writeInt(100);
w.write(byteArray);
w.flush();
byte[] result = baos.toByteArray();
Actually your second version will not work at all. DataOutputStream requires an actual target stream in which to write the data. You can't do new DataOutputStream(). There isn't actually any constructor like that.

Could you make a variable to hold on to the ByteArrayOutputStream and pass it into the DataOutputStream.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(1);
byte[] result = dos.toByteArray();

Use the former case - wrap DataOutputStream around the ByteArrayOutputStream. Just make sure you save the reference to the ByteArrayOutputStream. When you are finished, close() or at least flush() the DataOutputStream and then use the toByteArray method of the ByteArrayOutputStream.

You could use a stream approach if you connect your outputstream to an inputstream through a PipedInputStream/PipetOutputStream. Then you will consume the data from the inputstream.
Anyway if what you need to do is simple and doesn't not require a stream approach I would use a java.nio.ByteBuffer on which you have
put(byte[] src) for your byte[]
putInt(int value)
and byte[] array() to get the content

You don´t need more like this
Example exampleExample = method(example);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); marshaller.marshal(exampleExample , baos);
Message message = MessageBuilder.withBody(baos.toByteArray()).build();

The Integer class has a method to get the byte value of an int.
Integer.byteValue()

Related

How to properly read an InputStream with multiple contents

public static void main(String[] args) throws Exception
{
// Server sends 3 numbers to the client
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(1000);
bos.write(2000);
bos.write(3000);
// Client receive the bytes
final byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
System.out.println(bis.read());
System.out.println(bis.read());
System.out.println(bis.read());
}
The code above is breaking because bis.read() returns an int in the range 0 to 255
How can I receive those numbers properly? Should I use a delimiter and keep reading the stream until I find it? If so, what if I'm sending multiple files, I think if the delimiter as a single byte it could matched somewhere in the file and also break.
Use decorators for your streams!
All you have to do is to wrap your Output- and InputStream by java.io.ObjectOutputStream / and java.io.ObjectInputStream. These classes support writing and reading ints (a 4-byte value) with a single method call to writeInt/readInt.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeInt(1000);
os.writeInt(2000);
os.writeInt(3000);
os.close();
// Client receive the bytes
final byte[] bytes = bos.toByteArray();
ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(bytes));
System.out.println(is.readInt());
System.out.println(is.readInt());
System.out.println(is.readInt());
Don't forget to close the streams. Use try/finally or try-with-resources.
Byte stream is a stream of bytes. So if you're reading stream and want to differentiate between different parts of the stream then you should "create" some sort of protocol.
Here are some ideas that can be relevant:
Use delimiter as you've stated by yourself, If you're concerned about the length - do not one byte length, but something more unique - something that you're sure you won't see in the parts themselves.
At the beginning of the part allocate N bytes (2-4 or maybe more, depending on data) and write the size of the part that will follow.
So that when you create the stream (writer), before actually streaming the "part" - calculate its size and encode it. This is a protocol between reader and writer.
When you read - read the size (=N bytes for example), and then read N bytes. Now you know that the part is ended, and the next part (again, size + content) will follow
Can you try ByteBuffer class?
ByteStream is just a stream of bytes. It doesn't understand integer which actually needs more than one byte. If you print bytes.length it will return you 3. Surely you need more bytes than that. Allocate 4 bytes before you write an integer and then write to it. Check out this class above. Hope that helps!

Wrapping byte array in ByteArrayInputStream

I am just trying to understand the wrapping of an array of bytes using ByteArrayInputStream class. Here is the code that I have doubt about it.
byte[] bytes = new byte[1024];
//write data into byte array...
InputStream input = new ByteArrayInputStream(bytes);
//read first byte
int data = input.read();
while(data != -1) {
//do something with data
//read next byte
data = input.read();
}
My question is it it possible to write this part
InputStream input = new ByteArrayInputStream(bytes);
like this
ByteArrayInputStream input = new ByteArrayInputStream(bytes);
And why the author of this code created the object with both the super and sub classes?
I really thank you for your help.
Yes, you can write
InputStream input = new ByteArrayInputStream(bytes);
like
ByteArrayInputStream input = new ByteArrayInputStream(bytes);
It is functionally the same.
However, in OOP it's widely recommended to "program to interfaces". See What does it mean to "program to an interface"? for an explanation.
In this case, strictly speaking, InputStream is not an interface, but an abstract superclass. However, it more or less acts like an interface.
is it it possible to write this part
(InputStream input = new ByteArrayInputStream(bytes);)
like this
( ByteArrayInputStream input = new ByteArrayInputStream(bytes);)
Certainly. Why do you think otherwise? What happened when you tried it? Why are you using StackOverflow as a substitute for conclusive experiments?
And why the author of this code created the object with both the super and sub classes?
He didn't. He created the object as an instance of ByteArrayInputStream. He then assigned the result to a variable of type InputStream. It's perfectly normal.

Which one is better approach so as to able to use wrapper class read() / write() method with android.content.res.Resources.openRawResource() method?

//Reading a image file from #drawable res folder and writing to a file on external sd card
//below one works no doubt but I want to imrpove it:
OutputStream os = new FileOutputStream(file); //File file.........
InputStream is =getResources().openRawResource(R.drawable.an_image);
byte[] b = new byte[is.available()];
is.read(b);
os.write(b);
is.close();
os.close();
In above code I am using basic io classes to read and write. My question is what can I do in order to able to use wrapper classes like say DataInputStream/ BufferedReaderd or PrintStream / BufferedWriter /PrintWriter.
As openRawResources(int id ) returns InputStream ;
to read a file from res I either need to typecast like this:
DataInputStream is = (DataInputStream) getResources().openRawResource(R.drawble.an_image));
or I can link the stream directly like this:
DataInputStream is = new DataInputStream(getResources().openRawResource(R.drawable.greenball));
and then I may do this to write it to a file on sd card:
PrintStream ps =new PrintStream (new FileOutputStream(file));
while(s=is.readLine()!=null){
ps.print(s);
}
So is that correct approach ? which one is better? Is there a better way?better practice..convention?
Thanks!!!
If openRawResource() is documented to return an InputStream then you cannot rely on that result to be any more specific kind of InputStream, and in particular, you cannot rely on it to be a DataInputStream. Casting does not change that; it just gives you the chance to experience interesting and exciting exceptions. If you want a DataInputStream wrapping the the result of openRawResource() then you must obtain it via the DataInputStream constructor. Similarly for any other wrapper stream.
HOWEVER, do note that DataInputStream likely is not the class you want. It is appropriate for reading back data that were originally written via a DataOutputStream, but it is inappropriate (or at least offers no advantages over any other InputStream) for reading general data.
Furthermore, your use of InputStream.available() is incorrect. That method returns the number of bytes that can currently be read from the stream without blocking, which has only a weak relationship with the total number of bytes that could be read from the stream before it is exhausted (if indeed it ever is).
Moreover, your code is also on shaky ground where it assumes that InputStream.read(byte[]) will read enough bytes to fill the array. It probably will, since that many bytes were reported available, but that's not guaranteed. To copy from one stream to another, you should instead use code along these lines:
private final static int BUFFER_SIZE = 2048;
void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE];
int nread;
while ( (nread = in.read(buffer) != 0 ) do {
out.write(buffer, 0, nread);
}
}

How to send size of serialized data before the data itself?

I'm crating a client-server chat application. After discovering the C/C++ approach with sending bytes of data is a real pain in Java (signed bytes are simply hilarious), I started trying to use more convenient methods - specifically Serializable interface and ObjectOutputStream along with ByteArrayOutputStream.
This answer quite describes what I know at the moment.
So, I can convert my object into a byte array, which can then be put into output buffer that is eventually sent (the sending is done asynchronously).
Now with object, I need to send the size of the byte array first - so that the receiving function knows how much data should be read before parsing the object.
So in this code:
out = new ObjectOutputStream(bos);
out.writeObject(this);
return bos.toByteArray();
Can I somehow prepend the object size?
out = new ObjectOutputStream(bos);
out.writeObject(this);
//PSEUDO FUNCTION - beware
out.writeIntOnOffset(out.size(), 0) //Push the size on the beginning of the array
return bos.toByteArray();
Once you have object size just send it:
MyClass obj = ....;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj); // this is what you already have.
int size = baos.length; // now we have size
OutputStream socketStream = .... // I guess you know how to get it.
ObjectOutputStream socketOos = new ObjectOutputStream(socketStream);
socketOos.writeInt(size);
socketOos.write(baos.toByteArray());
You should definitely not mess with the array it self.
Instead you should create a separate method that returns size

How can we read or use the contents of outputstream [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
How can we read or use the contents of outputstream.
In my case, I am using a method having signature.
public static OutputStream decryptAsStream(InputStream inputStream,
String encryptionKey)
This method return OutputStream. I want get OutputStream to String.
Is it possible to pipe the output from an java.io.OutputStream to a String in Java?
How can we read or use the contents of outputstream.
In general you can't. An OutputStream is an object that you write bytes to. The general API doesn't provide any way to get the bytes back.
There are specific kinds of output stream that would allow you to get the bytes back. For instance:
A ByteArrayOutputStream has a method for getting the byte array contents.
A PipeOutputStream has a corresponding PipeInputStream that you can read from.
If you use a FileOutputStream to write to file, you can typically open a FileInputStream to read the file contents ... provided you know the file pathname.
Looking at that method, it strikes me that the method signature is wrong for what you are trying to do. If the purpose is to provide an encrypter for a stream, then the method should return an InputStream. If the purpose is to write the encrypted data somewhere, then the method should return void and take an extra parameter that is the OutputStream that the method should write to. (And then the caller can use an OutputStream subclass to capture the encrypted data ... if that is what is desired.)
Another alternative that would "work" is to change the method's signature to make the return type ByteArrayOutputStream (or a file name). But that is not a good solution because it takes away the caller's ability to decide where the encrypted output should be sent.
UPDATE
Regarding your solution
OutputStream os = AESHelper.decryptAsStream(sourceFile, encryptionKey);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos = (ByteArrayOutputStream) os;
byte[] imageBytes = baos.toByteArray();
response.setContentType("image/jpeg");
response.setContentLength(imageBytes.length);
OutputStream outs = response.getOutputStream();
outs.write(imageBytes);
That could work, but it is poor code:
If AESHelper.decryptAsStream is a method that you wrote (and it looks like it is!), then you should declare it as returning a ByteArrayOutputStream.
If it is already declared as returning a ByteArrayOutputStream you should assign it directly to baos.
Either way, you should NOT initialize baos to a newly created ByteArrayOutputStream instance that immediately gets thrown away.
It is also worth noting that the Content-Type is incorrect. If you sent that response to a browser, it would attempt to interpret the encrypted data as an image ... and fail. In theory you could set a Content-Encoding header ... but there isn't one that is going to work. So the best solution is to send the Content-Type as "application/octet-stream".
You can do something like following :
OutputStream output = new OutputStream()
{
private StringBuilder string = new StringBuilder();
#Override
public void write(int x) throws IOException {
this.string.append((char) x );
}
public String toString(){
return this.string.toString();
}
};
Mainly you can use outputstreams to send the file contents as #The New Idiot mentioned. .pdf files, zip file, image files etc.
In such scenarios, get the output stream of your servlet and to that write the contentes
OutputStream outStream = response.getOutputStream();
FileInputSteram fis = new FileInputStream(new File("abc.pdf));
byte[] buf = new byte[4096];
int len = -1;
while ((len = fis.read(buf)) != -1) {
outStream .write(buf, 0, len);
}
response.setContentType("application/octect");(if type is binary) else
response.setContentType("text/html");
outStream .flush();
outStream.close();
If you got the OutputStream from the response , you can write the contents of the OutputStream to the response which will be sent back to the browser . Sample code :
OutputStream outStream = response.getOutputStream();
response..setHeader("Content-Disposition", "attachment; filename=datafile.xls");
response.setContentType("application/vnd.ms-excel");
byte[] buf = new byte[4096];
int len = -1;
while ((len = inStream.read(buf)) != -1) {
outStream.write(buf, 0, len);
}
outStream.flush();
outStream.close();
Read this : Content-Disposition:What are the differences between “inline” and “attachment”?
In your case the method definition is :
public static OutputStream decryptAsStream(InputStream inputStream,
String encryptionKey)
So you can get the OutputStream from that method as :
OutputStream os = ClassName.decryptAsStream(inputStream,encryptionKey);
And then use the os .

Categories