Java Netty 5 ByteBuf to String the right way - java

Hi so i started using Netty a couple of days ago but i noticed that the way am converting the ByteBuf to String is using lot's of memory each time its used
Is there any other way to do this with out using lots of memory?
By the way CheckPacket function is a simple if string contains.
Thx.
ByteBuf byteBuffer=(ByteBuf)msg;
byte[] result = new byte[byteBuffer.readableBytes()];
byteBuffer.readBytes(result).retain();
String resultStr = new String(result);
if (!resultStr.isEmpty()) {
System.out.println(resultStr);
CheckPacket(resultStr, client);
}
byteBuffer.release();
byteBuffer.clear();

This example may help you:
byte[] inputBytes;
int offset = 0;
int length = input.readableBytes();
if (input.hasArray()) {
inputBytes = input.array();
offset = input.arrayOffset() + input.readerIndex();
} else {
inputBytes = new byte[length];
input.getBytes(input.readerIndex(), inputBytes);
}
Full source here.

You might get help from code.openhub.net:
driveableType = ByteBufUtils.readUTF8String(data);
driveableData = new DriveableData(ByteBufUtils.readTag(data));
initType(getDriveableType(), true);

Related

Read and Write strings via ByteBuf using byte[] array

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

Convert ZIP to byte array without saving the output to file

I have a ZIP file and when I convert it into byte array and encode it, I am unable to print the encoded format without writing it into file.
Could anyone help in solving this issue?
My code is
InputStream is = null;
OutputStream os = null;
is = new FileInputStream("C:/Users/DarkHorse/Desktop/WebServicesTesting/PolicyCredit.zip");
os = new FileOutputStream("D:/EclipseTestingFolder/EncodedFile1.txt");
int bytesRead = 0;
int chunkSize = 10000000;
byte[] chunk = new byte[chunkSize];
while ((bytesRead = is.read(chunk)) > 0)
{
byte[] ba = new byte[bytesRead];
for(int i=0;i<ba.length;i++)
{
ba[i] = chunk[i];
}
byte[] encStr = Base64.encodeBase64(ba);
os.write(encStr);
}
os.close();
is.close();
}
My Output in the file is
UEsDBBQAAAAIANGL/UboGxdAAQUAAK0WAAAQAAAAUG9saWN5Q3JlZGl0LnhtbJVY3Y6rNhC+r9R34AlqSPankSwkdtNskbLZKOk5Va8QC95d6wRIDZyeffszxgSMGUPKFcx8M/b8egwN87IWcZ6waF+cePLp//qLAw/d8BOL/mRxykRL6sk89T1KLq8adx1XLHp5i55YzkRc8SL3F6534y69O0oQpia6K6LiLTqwpBBpKdUPCRq
But when I am trying to print it on the screen, I am getting in this way
8569115686666816565656573657871764785981117112010065658185656575488765656581656565658571571159787785381517410890711084876110104116987486895189541147810467431145782515265108113838097110107831191071001167811510798769075791075386975681675753100541198273689012110110210211512212010383777185807570991205677479856101103119785655738799905411997704399101807611247471137665119471005666797647109821201211078276
You need to create a string representation of Base 64 encoded data.
System.out.println( new String(encStr, Charset.forName("UTF-8")));
Here are some other examples Base 64 Print Question
String Class
Assuming your result array byte[] encStr = Base64.encodeBase64(ba) is actually the encoded string, try the following:
System.out.println(new String(bytes, Charset.defaultCharset());
If you are using JDK 7 you can use Files.readAllBytes(path)
Your code would be much simpler like below:
Path path = Paths.get("C:/Users/DarkHorse/Desktop/WebServicesTesting/PolicyCredit.zip");
byte[] data = Files.readAllBytes(path);
byte[] encStr = Base64.encodeBase64(data);
System.out.println( new String(encStr));
Your will be able to print on console.

C# equivalent of this stream related code (Java)

I'm more of a Java developer than a C# developer, but I work with both languages; Unfortunately I'm nowhere near the level of most people in either language, but that's why I'm constantly asking questions and reading to expand my knowledge.
Currently I've been working on a Server/Client in Java which works wonderfully, I've written a test client in Java for a game that I've been working on in Unity3D. Honestly, I would just use Java for the entire game if the community was there to easily get level designers etc.
In this code, I'm using a BufferedInputStream in java, and the setup looks like this:
DataInputStream dataIn = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
Throughout this code, I perform the following logic to check to make sure all of the data for a specified packet as arrived:
if(dataIn.available() < 4) {
continue;
}
dataIn.mark(4);
int length = dataIn.readInt();
System.out.println("Packet length is" + length);
if(dataIn.available() < length) {
System.out.println("Only read " + dataIn.available() + "/ " + length + " bytes.");
dataIn.reset();
continue;
}
and I've been struggling to find an equivalent to this in C#. -- Other issues I've noticed is that a byte being sent by java's DataOutputStream, and the byte being read by C#'s BinaryReader is not always the same, but that's another problem.
Something like this reads all the expected data in a memorystream. Further processing of the received data is possible by using the memorystream as a stream, or by getting the bytes in it with memoryStream.ToArray().
using (var ns = new NetworkStream(socket))
{
int dataLength = 0;
// reading the datalength
for (int i = 0; i < 4; i++)
{
while (!ns.DataAvailable)
{
System.Threading.Thread.Sleep(20);
}
dataLength = (dataLength << 8) + ns.ReadByte();
}
// reading the data
byte[] buffer = new byte[1024];
int bytesRead;
using (var memoryStream = new MemoryStream())
{
while (memoryStream.Length < dataLength)
{
while (!ns.DataAvailable)
{
System.Threading.Thread.Sleep(20);
}
bytesRead = ns.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, bytesRead);
}
}
}
Edit: minimalistic approach
Beware of the socket.ReceiveBufferSize when using this approach! If it's smaller than data size you're in for a long sleep.
Socket socket = listener.AcceptSocket();
while (socket.Available < 4)
{
System.Threading.Thread.Sleep(20);
}
byte[] lengthBuffer = new byte[4];
socket.Receive(lengthBuffer);
if (BitConverter.IsLittleEndian) Array.Reverse(lengthBuffer);
int dataLength = BitConverter.ToInt32(lengthBuffer, 0);
while (socket.Available < dataLength)
{
System.Threading.Thread.Sleep(20);
}
byte[] dataBuffer = new byte[dataLength];
socket.Receive(dataBuffer);

Invalid value for ByteString for Update photo in Google Apps engine in java

I am trying to update photo using Google apps engine.I have imageurl i convert it into byte array and then encode
it using base64.i got encoded string,now i m trying to update photodata using directory API Reference
https://developers.google.com/admin-sdk/directory/v1/reference/users/photos#resource
after update i got error invalid byteString.I face this problem from yesterday.So Let me know where i did wrong? Below is my code.
import com.google.appengine.repackaged.org.apache.commons.codec.binary.Base64;
above class used for Base64.
URL url = new URL(myImageUrl);
ByteArrayOutputStream bais = new ByteArrayOutputStream();
InputStream is = null;
try {
is = url.openStream ();
byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
int n;
while ( (n = is.read(byteChunk)) > 0 ) {
bais.write(byteChunk, 0, n);
}
System.out.println(byteChunk);
byte[] encoded = Base64.encodeBase64(byteChunk);
String ecodedString = new String(encoded, "UTF-8");
ecodedString = ecodedString.replace("/", "_");
ecodedString = ecodedString.replace("+", "-");
ecodedString = ecodedString.replace("=", "*");
System.out.println(ecodedString);
Padding could be the problem, try not replacing "=" with "*". See also:
Converting string to web-safe Base64 format
p.s. repackaged libs are discouraged in app engine; you may use DatatypeConverter.printBase64Binary() instead.

Getting input text back out of MessageDigest

There are many people here on SO suggesting different approaches to the problem that I am having, but non of them seem to work for me. I am currently testing a timestamp server and (among other things, I am sending the server a message) and I need to read that the message exists in the answer. So I am creating a request and preparing it:
MessageDigest digest = MessageDigest.getInstance("SHA1");
String s = "Trolololoooo";
DigestInputStream stream = new DigestInputStream(new ByteArrayInputStream(s.getBytes("UTF-8")), digest)
byte[] digest2 = stream.getMessageDigest().digest();
// timestamp stuff is all org.bouncycastle.tsp.*
TimeStampRequestGenerator timeStampRequestGenerator = new TimeStampRequestGenerator();
timeStampRequestGenerator.setReqPolicy(String.valueOf(new ASN1ObjectIdentifier("1.3.6.1.4.1.13762.3")));
TimeStampRequest timeStampRequest = timeStampRequestGenerator.generate(TSPAlgorithms.SHA1, digest2, BigInteger.valueOf(666));
byte request[] = timeStampRequest.getEncoded();
... skipped the sending part, ok got the answer
InputStream in = con.getInputStream();
TimeStampResp resp = TimeStampResp.getInstance(new ASN1InputStream(in).readObject());
TimeStampResponse response = new TimeStampResponse(resp);
response.validate(timeStampRequest);
Now, from the response, I can successfully read the byte stream like:
byte[] messageImprintDigest1 = response.getTimeStampToken().getTimeStampInfo().getMessageImprintDigest();
for( byte b : messageImprintDigest1) System.out.print(b);
Will output: -3857-93-189410775135085-65-17-1079624-112-81-4079
Anyway, I have been blindly trying all the suggestion that I have found, that would translate back to "Trolololoooo", but no success. Some (not limited to) things I have tried:
String s1 = DigestUtils.sha1Hex(messageImprintDigest1);
String s2 = new String(Hex.decodeHex(s1.toCharArray()), "UTF-8");
// how could that help me..? but nothing to lose here.
String s3 = Hex.encodeHexString(messageImprintDigest1);
String convert = convert(s1);
// String convert1 = convert(s2);
// String convert2 = convert(s3);
int len = s1.length();
byte[] cStr = new byte[len/2];
for(int i = 0; i < len; i+=2) {
cStr[i/2] = (byte)Integer.parseInt(s1.substring(i, i+2), 16);
}
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
decoder.onMalformedInput(CodingErrorAction.IGNORE);
ByteBuffer wrap = ByteBuffer.wrap(cStr);
CharBuffer decode = decoder.decode(wrap);
CharBuffer cb = decoder.decode( ByteBuffer.wrap( cStr ));
String s4 = cb.toString();
...
public static String convert(String hex){
ByteBuffer buff = ByteBuffer.allocate(hex.length()/2);
for (int i = 0; i < hex.length(); i+=2) {
buff.put((byte)Integer.parseInt(hex.substring(i, i+2), 16));
}
buff.rewind();
Charset cs = Charset.forName("UTF-8");
CharBuffer cb = cs.decode(buff);
return cb.toString();
}
Anyway, it is probably some obvious stuff I am missing, like that the messageImprintDigest1 doesn't look like a hex string at all (pardon me, I studied geology in university).. This stuff is all very new to me, so it is hard to argue with the compiler or some other stuff out there.
You can't get the original text back from a message digest. It's a one-way process.
Have you tried this simple solution?
byte[] b = "Trolololoooo".getBytes();
String s = new String(b);
System.out.println(s);
will output Trolololoooo.

Categories

Resources