Reading from InputStream to byte[] throws IndexOutOfBoundsException - java

I obviously don't know where is the problem!, First I ask the client to send me the Length of the byte[] he is going to send, then I read for its length like this.
int i = 323292; // length of incoming Byte[]
byte[] b = new byte[i];
int readBytes=inputStream.read(b,0,b.length);
But It always kept reading readBytes less than i. And I am sure that the client sends the whole byte[].
I tried to put it inside a loop, to read till my total number of read bytes is i, but I always get IndexOutOfBoundsException after the second Iteration! here is the code
boolean flag = true;
int i = 323292;
int threshold = 0;
byte[] b = new byte[i];
int read = 0;
while (flag) {
if (threshold < i) {
System.out.println(threshold);
try {
read = inputStreamFromClient.read(b, threshold, b.length);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
threshold = threshold + read;
} else {
flag = false;
}
}
AnyIdeas?

This:
read = inputStreamFromClient.read(b, threshold, b.length);
should be:
read = inputStreamFromClient.read(b, threshold, b.length - threshold);

Related

Java client to C# server TCP

The problem is when i send up to 40 KB everything is okay when i send more sometime half of the data received some time nothing ,is there a limit of the networkstream.Read ,even though i cunked the data ,i can't determine if the problem form the java or the c# from the network stream or the Output stream
C# SERVER
private void ReadData(){
if (networkStream.DataAvailable)
{
int size = GetBufferSize();
Thread.Sleep(340);
byte[] myReadBuffer = new byte[size];
int numberOfBytesRead = 0;
while (true)
{
numberOfBytesRead = networkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
if (numberOfBytesRead >= myReadBuffer.Length)
{
break;
}
}
string str = Encoding.UTF8.GetString(myReadBuffer, 0, size);
dynamic Message = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(str);
// Android Message , JSON String
if (OnAndroidMessage != null)
{
OnAndroidMessage(Message);
}
}
}
private int GetBufferSize()
{
byte[] myReadBuffer = new byte[4];
int numberOfBytesRead = 0;
do
{
numberOfBytesRead = networkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
} while (networkStream.DataAvailable && numberOfBytesRead < myReadBuffer.Length);
if (numberOfBytesRead > 0)
{
// reverse the byte array.
if (BitConverter.IsLittleEndian)
{
Array.Reverse(myReadBuffer);
}
return BitConverter.ToInt32(myReadBuffer, 0);
}
else
{
return 0;
}
}
Java Client // i tested this also without cutting the data to smaller paces ,half of the data received not all of them
mBufferOut = socket.getOutputStream();
private void sendMessage(final String message) {
if (mBufferOut != null && message != null) {
try {
byte[] data = message.getBytes("UTF-8");
Log.d("_TAG", "Sending: " + message);
Log.d("_TAG", "Message length: " + Integer.toString(data.length));
mBufferOut.write(toByteArray(data.length));
mBufferOut.flush();
List<byte[]> divideArray = divideArray(data, 10000);
for (byte[] dataChunk : divideArray) {
Log.e("_TAG","CHUNK SIZE > " + Integer.toString(dataChunk.length));
mBufferOut.write(dataChunk, 0, dataChunk.length);
mBufferOut.flush();
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
private List<byte[]> divideArray(byte[] source, int chunksize) {
List<byte[]> result = new ArrayList<byte[]>();
int start = 0;
while (start < source.length) {
int end = Math.min(source.length, start + chunksize);
result.add(Arrays.copyOfRange(source, start, end));
start += chunksize;
}
return result;
}
Any ideas ?
Solution from this post NetworkStream is reading data that should not be there
static void ReadExact(Stream stream, byte[] buffer, int offset, int count)
{
int read;
while(count > 0 && (read = stream.Read(buffer, offset, count)) > 0) {
offset += read;
count -= read;
}
if(count != 0) throw new EndOfStreamException();
}
the problem is the Read it takes size and want to get that size you need to give it chunks and check each chunk
And also read does not restart from where it stopped until it reads the amount is set to read meaning if i set to read 10 then if it not find the 10 then it will read what it find as example it reads 6 ,it will return 6 and when to loop another time ti read the rest it dose not start from 6 it start from 0 and read until 4 so you overwrite your data ,and if it read 10 from the first try then it set the read to finish so it dose not start from 0 ,it needs to read the amount the has been set to it to re set the read to new buffer location.

Java Client to C# server. Not receiving negative numbers

I have a Java app sending coordinates to a c# game in Unity. My data checks out with the exception of the negative values. I instead only get 63 or 250 something. Depending on the encoding.
Here is my Java client app:
#Override
public void run() {
//Keep in a loop as long as the running variable is true
while(running)
{
//Try catch block to catch exceptions for the networking code
try{
data1[0]=currentPlayer; // These are integers
.....
data1[8]=sendPause;
for(int i=0; i<=9;i++){
buf1[i]=(byte)data1[i]; //Casting to byte array
//System.out.println(buf1[i]);
}
//socket is created in "onCreate" earlier
socket.setTcpNoDelay(true);
out = socket.getOutputStream();
dos = new DataOutputStream(out);
dos.write(buf1, 0, buf1.length);
dos.flush();
synchronized(this){ this.wait(30); } //This is to minimize the frequency
}catch(Exception e)
{
Log.e("TCP", "Error",e);
}
}
}
This is my method for receiving in the C# server.
private void HandleClient(TcpClient client){
try{
byte[] bytes = new byte[256];
String data = null;
while(true)
{
data = null;
NetworkStream stream = client.GetStream();
int i;
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
byte[] msg = System.Text.Encoding.UTF8.GetBytes(data);
/*sbyte[] sbytes = new sbyte[msg.Length];
for (int j = 0; j < msg.Length; j++)
sbytes[j] = (sbyte)msg[j];
Debug.Log(sbytes[2]+" "+sbytes[3]);*/
packetID=msg[0];
switch(packetID){
case 1:
p1.joyLx = msg[1];
....
p1.pause = msg[8];
p1.active=true;
break;
....
case 4:
p4.joyLx = msg[1];
....
p4.active=true;
break;
}
}
client.Close();
}
}
catch(SocketException e)
{
Debug.Log("SocketException:"+e);
}
}
I've been looking into the whole signed/unsigned byte ordeal but I'm worried that upon saving it into a byte array beforehand is erasing this data.
P.S. this is my first visit here and I'm not really a programmer so I've probably missed something obvious. So sorry if I'm not accustomed...
Got it working! Thanks for the help and pointing out my oddities!
[...]byte[] bytes = new byte[256];
sbyte[] sbytes;
while(true)
{
NetworkStream stream = client.GetStream();
int i;
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
sbytes = new sbyte[bytes.Length];
for (int j = 0; j < bytes.Length; j++)
sbytes[j] = (sbyte)bytes[j];
packetID=bytes[0]; [...]
I think your problem is that you are using a byte array in your C# code. A byte in java has a range of -128 to 127. A byte in C# ranges from 0 to 255. Try copying the received byte array into an sbyte array:
sbyte[] signedB = new sbyte[bytes.Length];
Buffer.BlockCopy(bytes, 0, signedB, 0, bytes.Length);
Check the values of signedB after this.

Android Bluetooth Java, Constant bluetooth stream to fill up array and write to sdcard

I am writing an Android app that uses bluetooth to stream data (bytes) into an array in another class. The idea behind this is to record a set amount of data (i.e. buffer[60000]) and when it is full, write the buffer to a file and store it on the SD Card.
The issue i am having is everytime the call is made on the bluetooth class and it handles a method of HandleBluetooth.write(buffer, bytes); to send to the HandleBluetooth class my buffer index is getting reset each time that pass is made. The index for the buffer, and the buffer are both global variables which is confusing me as to why it is setting the index back to 0 every time HandleBluetooth.write(buffer, bytes); is called so i am never able to fill the buffer to write it to the file.
here is my code:
BluetoothSerialService.java
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[9999];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
HandleBluetooth.write(buffer, bytes);
// Send the obtained bytes to the UI Activity
//mHandler.obtainMessage(BlueTerm.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
String a = buffer.toString();
a = "";
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
HandleBluetooth class:
public static void write(byte[] buffer, int length) {
byte[] readBuf = (byte[]) buffer;
data_length = length;
for (x = 0; x < data_length; x++) {
raw = UByte(readBuf[x]);
if (odd_even_flag == 0) {
buffer1[out_index] = raw;
// System.out.println("ch1: " + buffer1[out_index]);
odd_even_flag = 1;
} else {
buffer2[out_index] = raw;
// System.out.println("ch2: " + buffer2[out_index]);
odd_even_flag = 0;
}
if (x % 10000 == 0) {
Write2File(buffer1, buffer2);
}
out_index++;
if (x >= 60000) {
StopIncomingData();
break;
}
}
}
As you can see I have been trying to index the buffer using out_index which is a global class variable.
I feel like this is something dumb that i am over looking here. Please steer me in the right direction so i can understand why my index is being reset every time that method is called.

Get from ByteBuffer to byte[] does not write to byte[]

I'm consecutively reading blocks of BLOCKSIZE (e.g. 512) bytes from a SocketChannel into a ByteBuffer. I'd then like to append the ByteBuffer content to a byte[] and go for the next round. The result would be a byte[] containing all the bytes that were read from the SocketChannel.
Now, System.arraycopy(...) works as expected. But when I use ByteBuffer's get(result, offset, length), nothing is written. The result array values remain zeroed.
Why is that?
public final static int BLOCKSIZE = 512;
public byte[] getReceivedData() {
int offset = 0, read;
byte[] result = {};
ByteBuffer buffer = ByteBuffer.allocate(BLOCKSIZE);
try {
while (true) {
read = _socketChannel.read(buffer);
if (read < 1) {
// Nothing was read.
break;
}
// Enlarge result so we can append the bytes we just read.
result = Arrays.copyOf(result, result.length + read);
// This works as expected.
System.arraycopy(buffer.array(), 0, result, offset * BLOCKSIZE, read);
// With this, however, nothing is written to result. Why?
buffer.get(result, offset * BLOCKSIZE, read);
if (read < BLOCKSIZE) {
// Nothing left to read from _socketChannel.
break;
}
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
EDIT:
I noticed offset++ was missing, too. So if there is more than BLOCKSIZE bytes on the channel, things get messed up...
Anyways, ByteArrayOutputStream really makes things simpler there so I decided to use that.
Working code:
public byte[] getReceivedData() {
int read;
ByteArrayOutputStream result = new ByteArrayOutputStream();
ByteBuffer buffer = ByteBuffer.allocate(BLOCKSIZE);
try {
while (true) {
buffer.clear();
read = _socketChannel.read(buffer);
if (read < 1) {
break;
}
result.write(buffer.array(), 0, read);
if (read < BLOCKSIZE) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return result.toByteArray();
}
You need to flip() the buffer before the get(), and compact() it afterwards.
If read == -1 you need to not only break out of the loop but close the channel too.
Your result array is of length 0 and cannot hold any information. Byte arrays do not grow, and you are unable to append buffers' content. Use java.io.ByteArrayOutputStream to accumulate result.

Performance in reading and writing files, what the best?. Serialization X Java.nio

I have an object with 1 int and 4 doubles.
I compared the performance to write 5 million of these objects in a file using serialization and FileChannel object.
In the serialization used the following method to read and write the file.
public void print() throws IOException, ClassNotFoundException{
ObjectInputStream input = new ObjectInputStream(new FileInputStream(this.filePath) );
try {
while(true) {
this.sb = (Sbit) input.readObject();
//System.out.println(this.sb.toString());
}
}
catch ( EOFException eofException ) {
return;
}
catch (IOException ioException) {
System.exit( 1 );
}
finally {
if( input != null )
input.close();
}
}
public void build() throws IOException {
ObjectOutputStream output = new ObjectOutputStream( new FileOutputStream(this.filePath) );
try {
Random random = new Random();
for (int i = 0; i<5000000; i++) {
this.sb = new Sbit();
this.sb.setKey(i);
this.sb.setXMin( random.nextDouble() );
this.sb.setXMax( random.nextDouble() );
this.sb.setYMin( random.nextDouble() );
this.sb.setYMax( random.nextDouble() );
output.writeObject(this.sb);
}
}
catch (IOException ioException) {
System.exit( 1 );
}
finally {
try {
if( output != null)
output.close();
}
catch ( Exception exception ) {
exception.printStackTrace();
System.exit(1);
}
}
}
While using java.nio was:
public void print() throws IOException {
FileChannel file = new RandomAccessFile(this.filePath, "rw").getChannel();
ByteBuffer[] buffers = new ByteBuffer[5];
buffers[0] = ByteBuffer.allocate(4); // 4 bytes to int
buffers[1] = ByteBuffer.allocate(8); // 8 bytes to double
buffers[2] = ByteBuffer.allocate(8);
buffers[3] = ByteBuffer.allocate(8);
buffers[4] = ByteBuffer.allocate(8);
while (true) {
if(file.read(buffers[0]) == -1 ) // Read the int,
break; // if its EOF exit the loop
buffers[0].flip();
this.sb = new Sbit();
this.sb.setKey(buffers[0].getInt());
if(file.read(buffers[1]) == -1) { // Read the int primary value
assert false; // Should not get here!
break; // Exit loop on EOF
}
buffers[1].flip();
this.sb.setXMin( buffers[1].getDouble() );
if(file.read(buffers[2]) == -1) {
assert false;
break;
}
buffers[2].flip();
this.sb.setXMax( buffers[2].getDouble() );
if(file.read(buffers[3]) == -1) {
assert false;
break;
}
buffers[3].flip();
this.sb.setYMin( buffers[3].getDouble() );
if(file.read(buffers[4]) == -1) {
assert false;
break;
}
buffers[4].flip();
this.sb.setYMax( buffers[4].getDouble() );
for(int i = 0; i < 5; i++)
buffers[i].clear();
}
}
public void build() throws IOException {
FileChannel file = new RandomAccessFile(this.filePath, "rw").getChannel();
Random random = new Random();
for (int i = 0; i<5000000; i++) {
this.sb = new Sbit();
this.sb.setKey(i);
this.sb.setXMin( random.nextDouble() );
this.sb.setXMax( random.nextDouble() );
this.sb.setYMin( random.nextDouble() );
this.sb.setYMax( random.nextDouble() );
ByteBuffer[] buffers = new ByteBuffer[5];
buffers[0] = ByteBuffer.allocate(4); // 4 bytes to into
buffers[1] = ByteBuffer.allocate(8); // 8 bytes to double
buffers[2] = ByteBuffer.allocate(8);
buffers[3] = ByteBuffer.allocate(8);
buffers[4] = ByteBuffer.allocate(8);
buffers[0].putInt(this.sb.getKey()).flip();
buffers[1].putDouble(this.sb.getXMin()).flip();
buffers[2].putDouble(this.sb.getXMax()).flip();
buffers[3].putDouble(this.sb.getYMin()).flip();
buffers[4].putDouble(this.sb.getYMax()).flip();
try {
file.write(buffers);
}
catch (IOException e) {
e.printStackTrace(System.err);
System.exit(1);
}
for(int x = 0; x < 5; x++)
buffers[x].clear();
}
}
But I read a lot about on the java.nio and tried to use it precisely because it has better performance. But that's not what happened in my case.
To write the file were the following (java.nio):
file size: 175 MB
time in milliseconds: 57638
Using serialization:
file size: 200 MB
time in milliseconds: 34504
For the reading of this file, were as follows (java.nio):
time in milliseconds: 78172
Using serialization:
time in milliseconds: 35288
Am I doing something wrong in java.nio? I would like to write to the same binary files as done. There is another way to write file efficiently? actually serializing an object is the best way?
Thank you.
You are creating 25,000,000 ByteBuffer objects, with each ByteBuffer being at most 8 bytes. Thats very inefficient.
Create just one ByteBuffer by allocating it to 38 bytes outside the loop (before the for statement)
Inside the loop you can use the same ByteBuffer as follows:
buffer.clear();
buffer.putInt(this.sb.getKey());
buffer.putDouble(this.sb.getXMin());
buffer.putDouble(this.sb.getXMax());
buffer.putDouble(this.sb.getYMin());
buffer.putDouble(this.sb.getYMax());
buffer.flip();
try
{
file.write(buffer);
}
catch (IOException ex)
{
ex.printStackTrace();
//etc...
}
buffer.flip();
Try it out and let us know if you see any improvements.
Instead of using multiple ByteBuffers, declare a single byte buffer that is large enough to hold all of the data you want to put into it. Then put data into it just like you are now. When done, flip the buffer and write it out. When you are ready to read it back in, read the data from disk into the byte buffer, flip it, and then read the data out using getInt/getDouble.
I haven't tried to serialize stuff on my own, but have achieved good results with kryo. It is a lot faster than standard Java serialization.

Categories