I have a byte array of size 200 that has data received with socket.receive(). Let's say the packet data is "hello".
int size = 200;
DatagramPacket packet = new DatagramPacket(new byte[size], size);
socket.receive(packet);
byte[] byte1 = packet.getData();
I tried to convert the byte array into string, and the string length is 200 even though it prints out only 'hello' string.
String result = new String(byte1); // .toString();
System.out.println(result.length()); --> 200
System.out.println(result); ---> hello
How can I truncate the String to contain only "hello" when converting it from byte[]?
ADDED
Based on malchow's answer, this solved my issue:
int packetLength = packet.getLength();
byte[] byte1 = packet.getData();
String result = new String(byte1);
return result.substring(0, packetLength);
maybe you should try to check the length of the data received AFTER receiving it:
http://docs.oracle.com/javase/1.5.0/docs/api/java/net/DatagramPacket.html#getLength%28%29
this should be 4 (after the call to socket.receive())
If the extra bites are all empty/whitespace, trim() should do it.
Related
I'm having some problem sending datagram packets in java. I have part of my code below.
Sender:
String str = "abcdefghijk.txt"
byte[] data = new byte[1000];
ByteBuffer buf = ByteBuffer.wrap(data);
buf.put(str.getBytes());
//data = str.getBytes(); line 1
//checksum
crc.reset();
crc.update(data, 8, data.length-8);
checksum = crc.getValue();
buf.rewind();
buf.putLong(checksum);
packet = new DatagramPacket(data, data.length, address);
Receiver:
packet.setLength(data.length);
socket.receive(packet);
data = packet.getData();
str = new String(data);
str = str.trim();
buf.rewind();
checksum = buf.getLong();
crc.reset();
crc.update(data, 8, packet.getLength()-8);
I will then do a check by using checksum==crc.getValue(). If i run the code as it is, my checksum is valid but the str received will be like this -> ##$%ijk.txt (garbage values infront). First 8 characters are gone in this case, which I think has something to do with the getLong().
However if i use line 1 in my code, the str received is correct (abcdefghijk.txt), but the checksum will be wrong.
Note that the code is not the entire thing but only the part that is affecting the output. Any help will be appreciated.
I believe your problem here is you consider that your packet will arrive in one chunk, but Streams have the property to cut the data into slices.
On the output, you have to encapsulate your data to know where you start and where you stop.
At the input, you have to rebuild your buffer chunk by chunk until you find that 'end tag'.
Are you using ObjectStreams ? If so, be aware they send and receive their own identifiers through the streams. It could explain the missing 8 bytes.
I have a situation where I have a String and three binary literals i need to add to a Byte array to send to a server.
The Client:
String arbitrary = "/AN/ARBITRARY/STRING";
int b_f32b = 0b00000000000000000000000011111111;
int b_seconds = 0b00000000000000001111111111111111;
int b_fraction = 0b01000000000000000000000000000000;
ByteBuffer bb = ByteBuffer.allocate(1024);
bb.put(arbitrary.getBytes());
bb.putInt(b_f32b);
bb.putInt(b_seconds);
bb.putInt(b_fraction);
bb.clear();
byte[] sendDataBytes = new byte[bb.capacity()];
bb.get(sendDataBytes, 0, sendDataBytes.length);
DatagramPacket sendPacket = new DatagramPacket(sendDataBytes, sendData.length, IPAddress, 7000);
clientSocket.send(sendPacket);
On the Server:
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String( receivePacket.getData());
The result is:
RECEIVED: /AN/ARBITRARY/STRING ÿ ÿÿ#
The String works fine - but the binary values do not is there something fundamental I am missing?
You're missing the fundamental understanding between binary and character data.
Strings are character data, meaning they're displayable. Binary data is not necessary displayable (especially in this case, since you know that you're not writing character data).
The putInt() method puts 4 bytes in the buffer. Read it with getInt() and then you'll get a value you can display.
Edit:
You're also creating a 1024 byte array with byte[] sendDataBytes = new byte[bb.capacity()]; and sending that over the wire. You'll never know how much of the 1024 bytes are actual data, and how much is just empty garbage.
Yes, you're missing a lot of fundamentals here and it's too broad to address everything in an answer.
I'm working on a project that involves receiving a byte array over wireless, the Android app reads this as a String over a TCP connection:
input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
...
...
//Loop
String read = input.readLine();
//Do something meaningful with String read...
The String will always be of a fixed format i.e. the first 3 characters will be an ID and the next following 20 characters will be the message data. The amount of characters will not change (3+20 characters = 23, with a starting and ending character '[' and ']' so that's 25 characters in total.
An example of a String received by the application would be [01A01020304050A0B0C0D]
ID - 0x01A
Byte0 0x01
Byte1 0x02
Byte2 0x03
Byte3 0x04
Byte4 0x05
Byte5 0x0A
Byte6 0x0B
Byte7 0x0C
Byte 8 0x0D
I would guess that I would have to use the substring operation, but I'm having trouble converting the substring to a byte value (note: the app is expecting byte[] and not Byte[]) and I feel I'm not doing it efficiently. I came across this piece of code that I've been using:
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
This is returning a byte array of size 1 and will have to be run 9 times (9 bytes) per message. I'm a bit concerned that this may be a bit too strenuous on processing, especially when the application is receiving messages very frequently (roughly about 10-15 messages per second)
I appreciate any thoughts and many thanks in advance!
just use this :
byte[] decodedString = Base64.decode(your_string, Base64.DEFAULT);
byte[] b = string.getBytes();
byte[] b = string.getBytes(Charset.forName("UTF-8"));
byte[] b = string.getBytes("UTF-8");
There is no way to be more effecient than using this methods.
Best and simple way:
String myString = "This is my string";
byte[] myByteArray = myString.getBytes("UTF-8");
Now, you able to access id, message whatever; easily from myByteArray.
Just write your data like
byte[] data = yourData.getBytes();
os.write(data, 0, data.length) // data is of 23 bytes
os.flush();
what about reading through InputStream, as you mentioned in your question that String is of 23 characters just do like
public byte[] readData(InputStream is) {
byte[] data = new byte[23];
int read = is.read(data);
System.out.println("Read: " + read);
return data;
}
When you have data then you can split data like this
byte[] tempId = new byte[3];
System.arrayCopy(data, 0, id, 0, id.length);
byte[] tempMessage = new byte[20];
System.arrayCopy(data, 3, message, 0, message.length);
String id = new String(tempId);
String message = new String(tempMessage);
Now you id and message separated and converted into String.
byte[] array = String.getBytes("UTF-8");
I am reading a DatagramPacket into a byte[] as such:
byte[] buffer = new byte[4 + size];
DatagramPacket request = new DatagramPacket(buffer, 4 + size);
receiver_Socket.receive(request);
I then print out the contents of the byte[].
String string = new String(buffer);
System.out.println(string);
The info that should be in the DatagramPacket is an int and 15 characters. size has been set to 15. However, when I print out the byte[] I just get 4 random symbols.
I printed out the byte[] right before I sent it and the output was: a random symbol, followed by the correct 15 characters... I am certain I am sending over 19 bytes as I also checked this value prior to sending the DatagramPacket.
Would anyone know what is going on here?
Thank you.
I'm using array of bytes to store data packet received from another computer.
receivedData = new byte[1024];
receivedPacket = new DatagramPacket(receivedData, receivedData.length);
socket.receive(receivedPacket);
receivedData = receivedPacket.getData();
String res = new String(receivedData); // PROBLEM HERE
the problem is at last line: because I declare receivedData as a byte stream with length 1024. so, always last line will create a new string from whole array, although it doesn't know exactly how many real byte I received. So, I meet frustrated error: res is not received as I wish. (because length of real bytes that I received not fix whole array)
So, my question is: how can I fix this point, how can I know how many bytes I really received to convert to string?
Try using DatagramPacket.getLength().
receivedData = new byte[1024];
receivedPacket = new DatagramPacket(receivedData, receivedData.length);
socket.receive(receivedPacket);
receivedData = receivedPacket.getData();
String charsetName = "US-ASCII"; // set to desired charset
String res = new String(receivedData, 0, receivedPacket.getLength(), charsetName);
Edited to add charset. Thanks, parsifal.
From the javadoc for DatagramSocket.receive():
The length field of the datagram packet object contains the length of
the received message
You can then construct your String using the constructor that takes a byte array and offsets.
Call DatagramPacket.getLength() to find out how many bytes were actually received.
And when you construct the String from those bytes, be sure to specify the encoding (as it is, you're using the JDK default encoding, which may differ from the server's encoding).