Read and Write strings via ByteBuf using byte[] array - java

I'm trying to send a string through netty with a ByteBuf.
First of all I convert the string to a byte array like that:
byteBuf.writeInt(this.serverName.length());
byteBuf.writeInt(this.ipAdress.length());
byteBuf.writeBytes(this.serverName.getBytes(StandardCharsets.UTF_8));
byteBuf.writeBytes(this.ipAdress.getBytes(StandardCharsets.UTF_8));
This works well, but I don't know how to read the bytes to convert them back to the string?
I tried something like that:
int snLen = byteBuf.readInt();
int ipLen = byteBuf.readInt();
byte[] bytes = new byte[byteBuf.readableBytes()];
System.out.println(byteBuf.readBytes(bytes).readByte());
this.ipAdress = "";
There must be something to get the bytes back. You can send bytes from a string but can't get the bytes back at the end? Seems like there is a method for that, but I don't have an idea how to do that.
I hope anyone from you can help me.
Thanks in advance! :)

In netty 4.1 you can use:
byteBuf.writeCharSequence(...)
byteBuf.readCharSequence(...)

How about using Netty's own StringEncoder and StringDecoder ? http://netty.io/4.1/api/io/netty/handler/codec/string/StringEncoder.html

Here is an untested answer:
I assume the data order is correct.
Use this, method "readBytes(ByteBuf dst, int length)" : readBytes
Transmit side change to:
byteBuf.writeInt(this.serverName.getBytes().length);
byteBuf.writeInt(this.ipAdress.getBytes().length);
Receiving side:
int snLen = byteBuf.readInt();
int ipLen = byteBuf.readInt();
byte[] bytesServerName = new byte[snLen];
byte[] bytesIp = new byte[ipLen];
byteBuf.readBytes(bytesServerName,snLen);
byteBuf.readBytes(bytesIp, ipLen);
String serverName = new String(bytesServerName);
String ipAddress = new String(bytesIp);
System.out.println(bytesServerName);
System.out.println(bytesIp);

Related

Java packet sending with bytebuffer

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.

Hex to String in Android(Java)?

Maybe I was sticky in hex to String?I don't know.
my code:
final byte[] txValue = intent.getByteArrayExtra(UartService.EXTRA_DATA);
txValue should be byte ?
debug:
Log.d("p1", ""+txValue.toString());
then show me those:
[B#1e631929
[B#9264ae
I don't know how to fix it ? somebody help me ?
You should use public String(byte[] bytes) constructor:
Constructs a new String by decoding the specified array of bytes using the platform's default charset. The length of the new String is a function of the charset, and hence may not be equal to the length of the byte array.
String s = new String(txValue);
and then print s, it contains what you want.
Printing txValue and txValue.toString() will print it in byte format.
I find the way:
final byte[] txValue = intent.getByteArrayExtra(UartService.EXTRA_DATA);
final int GasValue = ((txValue[0]<<8)|(txValue[1]&0xff))&0xffff;
String text = Integer.toString(GasValue);
Log.d("p1", ""+text);
OK
You should use Arrays.toString(txValue)
This is how I use i code
final byte[] txValue = intent.getByteArrayExtra(UartService.EXTRA_DATA);
txtResult.setText(Arrays.toString(txValue));
Result is like below
[27,0,1,13,13,4,5]

Array of bytes: how to know exactly numbers of byte received

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).

network byte order to host byte order in java

I'm stuck with interpreting a response from a C server to my java application. Hoping that the C server is responding to my java in BIG_ENDIAN format, my question is how would I convert the response to an Integer. I'm pasting the response I got from the the C server and wondering how would I do "be64toh" function in java.
Response from the C server -
^#^#^#^#^#^#^#^#^#^#^#^#^#^#^H^#^#^#^#^#^A^A^B^#^#^#^N^#^#^#^#^#^#^#^#^#^#^#^H^#^#^#^#^#^#^#^A^#^#^#^K^#^#^#^#^#^#^#^#^#^#^#<80>^#^#^#^#^#^#^BÃ^#^#^#^AYour
request is successfully registered with us and is under
processing.^#^#^#^#^D^#^#^#^#^#^#^#¨ýf^#^#^#^#^#mX#^#^#^#^#^#^#^#^#^N^#^#^#^#^#^#^#^#^#^#^#^H
I'm not sure how to interpret the non readable bytes and when converted to hexadecimal most of them are null but few of them are filled with data just like the ^H, ^A etc.. Can you please help me find a solution for this one.
Suppose you have a java.nio.SocketChannel to read from, you can use a ByteBuffer to do the conversion:
private static final int BUFFER_SIZE = 1024;
ByteBuffer readBuffer = ByteBuffer.allocate(BUFFER_SIZE).order(ByteOrder.BIG_ENDIAN);
int bytesRead = socketChannel.read(readBuffer);
readBuffer.flip();
Now you can read your data out of the buffer, e.g.:
int someInt = readBuffer.getInt();
long someLong = readBuffer.getLong();

DatagramPacket to string

Trying to convert a received DatagramPacket to string, but I have a small problem. Not sure what's the best way to go about it.
The data I'll be receiving is mostly of unknown length, hence I have some buffer[1024] set on my receiving side. The problem is, suppose I sent string "abc" and the do the following on my receiver side...
buffer = new byte[1024];
packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
buffer = packet.getData();
System.out.println("Received: "+new String(buffer));
I get the following output: abc[][][][]][][][]..... all the way to the buffer length.
I'm guessing all the junk/null at the end should've been ignored, so I must be doing something wrong." I know the buffer.length is the problem because if I change it to 3 (for this example), my out comes out just fine.
Thanks.
new String(buffer, 0, packet.getLength())
Using this code instead:
String msg = new String(packet.getData(), packet.getOffset(), packet.getLength());
The DatagramPacket's length field gives the length of the actual packet received. Refer to the javadoc for DatagramPacket.receive for more details.
So you simply need to use a different String constructor, passing the byte array and the actual received byte count.
See #jtahlborn or #GiangPhanThanhGiang's answers for example.
However, that still leaves the problem of which character encoding should be used when decoding the bytes into a UTF-16 string. For your particular example it probably doesn't matter. But it you are passing data that could include non-ASCII characters, then you need to decode using the correct charset. If you get that wrong, you are liable to get garbled characters in your String values.
As I understand it, the DatagramPacket just has a bunch of junk at the end. As Stephen C. suggests, you might be able to find the actual length received. In that case, use:
int realSize = packet.getLength() //Method suggested by Stephen C.
byte[] realPacket = new byte[realSize];
System.arrayCopy(buffer, 0, realPacket, 0, realSize);
As for finding the length, I don't know.
Try
System.out.println("Received: "+new String(buffer).trim());
or
String sentence = new String(packet.getData()).trim();
System.out.println("Received: "+sentence);
Use this Code instead
buffer = new byte[1024];
packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String data = new String(packet.getData());
System.out.println("Received: "+data);

Categories

Resources