Strange behavior of java streaming - java

I've the necessity to share a streaming of data between two instances as below:
// get EClasses which should be connected
final uk.man.xman.xcore.Parameter source = getParameter(sourceAnchor);
final uk.man.xman.xcore.Parameter target = getParameter(targetAnchor);
// Set data channels
//Output stream
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(new BufferedOutputStream(outputStream));
source.setOutputStream(dataOutputStream);
//Input stream
DataInputStream inpuDataStream = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(outputStream.toByteArray())));
target.setInputStream(inpuDataStream);
Everything works ok if I write, during those lines of code. Strangely, when I need to use the data channel to write something in another class, like here:
DataOutputStream dataOutputStream = (DataOutputStream) inputParameter.getOutputStream();
System.out.println("WRITE:" + attributes.getValue("value"));
dataOutputStream.writeUTF(attributes.getValue("value"));
dataOutputStream.flush();
I am not able to read, and I really do not know why. Am I missing something?
Thanks for your time

Not sure if that's what you're asking, but you're creating an InputStream that reads from an empty byte array. That doesn't make much sense:
// create an Output stream that will write in memory
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
...
// transform what has been written to the output stream into a byte array.
// Since othing has been written yet, outputStream.toByteArray() returns
// an empty array
DataInputStream inpuDataStream = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(outputStream.toByteArray())));

Related

Compare output stream performance

I have a serializable object and I want to write it down to file. Should I use ObjectOutputStream.writeObject() or convert it into a byte[] (using ObjectOutputStream) then use FileOutputStream.write()?
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file))
objectOutputStream.writeObject(myObject);
or
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out;
out = new ObjectOutputStream(byteOut);
out.writeObject(myObject);
new FileOutputStream(file).write(byteOut.toByteArray());
Buffering can improve performance by coalescing small writes into larger bulk writes. If you want to introduce buffering use a BufferedOutputStream, which does what you're doing with the byte array stream without changing downstream code.
// Unbuffered
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
// Buffered
ObjectOutputStream outputStream = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
This way you can continue to use ObjectOutputStream without the rest of the code having to know whether the stream is buffered or unbuffered.
As with any performance-related change, you should benchmark both approaches to see which performs better. Don't make changes like this without empirical testing. If you don't test, you're just guessing.

Is BufferedInputStream and BufferedOutputstream different from InputStream and Outputstream

recently i had troubles working with InputStreams and OutputStreams when i was trying to implement a basic file downloader in my android application.. to elaborate things this is how i did it..
i get an InputStream object using the apache HttpClient classes then tried writing the stream to a file.. but strangely when i buffer the InputStream or the OutputStream i get an unreadable file.... this is the code..
//to make the code concise i removed exceptions and stream closing..
private void download(InputStream in,String fileName){
//if i dont use the buffered thing and read directly from in everything is ok
// same is the buffered out i had to use in/outstream
BufferedInputStream bufferedIn = new BufferedInputStream(in);
FileOutputStream fout = new FileOutputStream(new File(fileName));
BufferedOutputstream bufferedOut = new BufferedOutputstream(fout);
int read = -1;
while((read = bufferedIn.read()) != -1){
bufferedOut.write(read);
}
//close the buffers
}
You have to flush the buffered outputstream when you're done with it.
In any case you probably want to flush() your output (done implicitly by close()), but with BufferedOutputStream this is even more important than with a other OutputStreams. If you have a FileOutputStream, the only buffering performed is that of the OS. If you have a BufferedOutputStream, Java performs its own buffering on top of it.
If you use Java 7 or newer, I'd recommend to write the code like this:
try (BufferedInputStream bIn = new BufferedInputStream(in);
BufferedOutputStream bOut = new BufferedOutputStream(new FileOutputStream(fileName))) {
for (int read; ((read = bIn.read()) != -1; )
bOut.write(read);
}
In your case I suspect you were closing the FileOutputStream but not the BufferedOutputStream. Therefore the file was truncated or even empty because the data buffered in the BufferedOutputStream was not flushed.

Get InputStream From a Socket

I want to stream and audio with SIP Connection in java application(SE).I connected with the server and got 200 OK messages.I want to receive data sent by the server. I created a SOCKET and got an InputStream. Here is how I do it. 123.456.789.1 is the my ip address and 1234 is which my application listening port.
Socket socket=new Socket("123.456.789.1",1234);
InputStream in=socket.getInputStream();
System.out.println("inputSream available :"+in.available());
But in.available() is always 0 .
But if I get the Object content=response.getContent();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(content);
byte[] contentBytes = bos.toByteArray();
the lenght of contenBytes equals to the response content length.But when I try to get inputStream and Play ,like following
InputStream pp=new ByteArrayInputStream(b);
AudioStream as = new AudioStream(pp);
AudioData data = as.getData();
ContinuousAudioDataStream cas = new ContinuousAudioDataStream (data);
An Exception throws;java.io.IOException: could not create audio stream from input stream
Then I tried to read the inputstream in.read() then when read some bytes,and IOException was thrown.
Q1. How can I solve and get InputStream from the socket?
Q2. how to get an inputStream to play the audio?
or let me know where the problem is and how to solve it.
UPDATED: Thank you all who showed a fault in.availabe();
Then I changed the code.
ByteArrayOutputStream ou=new ByteArrayOutputStream();
int i=0;
System.out.println("Before while");
while((i=in.read())!=-1){
ou.write(i);
System.out.println("Wrote :"+i);
}
Unfortunately the application doesn't go further.That means only Before while is printed.Application just shows running(I use netbeans IDE).I don't why.Any clarification?
When you use getContent you get some kind of object wrapping the content. Then using an ObjectOutputStream you write the Java representation of that object, not the actual bytes of the original data.
You should be able to do
AudioStream as = new AudioStream(in);
AudioData data = as.getData();
ContinuousAudioDataStream cas = new ContinuousAudioDataStream (data);
or if you do want to buffer the data
int chunkSize;
byte[] chunk = new byte[2048];
ByteArrayOutputStream outBuffer = new ByteArrayOutputStream();
while ( ( chunkSize = in.read(chunk) ) != -1) {
outBuffer.write(chunk, 0, chunkSize);
}
ByteArrayInputStream inBuffer = new ByteArrayInputStream(outBuffer.toByteArray());
AudioStream as = new AudioStream(inBuffer);
AudioData data = as.getData();
ContinuousAudioDataStream cas = new ContinuousAudioDataStream (data);
available() show how many bytes can be guaranteed read before blocking. It might always return 0.
available() is the number of bytes which can be read with out performing a blocking call to the OS. If you want to know how much data is available you should try to read it and see how much you get.

Socket: premature end of JPEG file

I'm trying to send an image file from a server to a client via a socket. The socket was previously used to send some strings from the server to the client (with buffered input/output streams).
The trouble is the image file can't be received properly, with "Premature end of JPEG file" error.
The server first sends the file size to the client, the client then creates a byte[] of that size, and starts to receive the file.
Here are the codes:
Server:
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
//Send file size
dos.writeInt((int) file.length());
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
byte[] fileBytes = new byte[bis.available()];
bis.read(fileBytes);
bis.close();
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(fileBytes);
bos.flush();
Client:
DataInputStream dis = new DataInputStream(socket.getInputStream());
//Receive file size
int size = dis.readInt();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
byte[] fileBytes = new byte[size];
bis.read(fileBytes, 0, fileBytes.length);
More interestingly, if I let server sleep for about 2 seconds between sending the file size and writing the byte[], then the image is received properly. I wonder if there's some kind of race condition between the server and the client
The error is most likely here:
byte[] fileBytes = new byte[bis.available()];
The method available does not return the size of the file. It might return only the size of the input buffer, which is smaller than the size of the file. See the API documentation of the method in BufferedInputStream.
Also, read in the line below is not guaranteed to read the whole file in one go. It returns the number of bytes that were actually read, which can be less than what you asked for. And in the client code, you are using read in the same way, without actually checking if it read all the data.
Please check commons-io with FileUtils and IOUtils. This should make work a lot easier.
http://commons.apache.org/io/
The correct way to copy a stream in Java is as follows:
int count;
byte[] buffer = new byte[8192]; // more if you like, but over a network it won't make much difference
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Your code fails to logically match this at several points.
Also available() is not a valid way to determine either a file size or the size of an incoming network transmission - see the Javadoc. It has few if any correct uses and these aren't two of them.

UDP client / server ....include 16-bit message sequence number for filtering duplicates

my assignment includes sending an image file using UDP service (using java I implemented that successfully). My professor asked to include:
"The exchanged data messages must also have a header part for the sender to include 16-bit message sequence number for duplicate filtering at the receiver end"
How to do this?
I assume to create your UDP packet, you are using a ByteArrayOutputStream to generate the data. If that is the case, just Wrap a DataOutputStream on top of that ByteArrayOutputStream, and call writeInt(somesequenceNumber) before writing the image data to the stream.
on the receive side, do the opposite, wrap a DataInputStream around a ByteArrayInputStream, and call readInt() to get the sequence number. From there you can check whether you have already received this packet.
Something like
Write Side
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(sequenceNumber++);
dos.writeInt(imageDataLength);
dos.write(imageData);
dos.flush();
byte[] udpPacketBytes = baos.toByteArray();
Read Side
ByteArrayInputStream bais = new ByteArrayInputStream(udpPacketBytes);
DataInputStream dis = new DataInputStream(bais);
int sequenceNumber = dis.readInt();
if (seenSequenceNumbers.add(Integer.valueOf(sequenceNumber)))
{
int imageLength = dis.readInt();
byte[] imageData = new byte[imageLength];
dis.read(imageData);
}
where seenSequenceNumbers is some Set
For a 16-bit value I would use DataOutputStream.writeShort() and DataInputSTream readShort()/readUnsignedShort(). writeInt() and readInt() are for 32-bit values. If you want to avoid duplicates, a 32-bit value may be a better choice in any case. ;)

Categories