read line from sequence of byte arrays - java

I receive data from Bluetooth BLE as follow in 250 bytes chunk at most.
onDataReceived(byte[] data) {
my_readline(); // <-- how could I implement this
}
the data are string but chuncked. so what is the proper way to detect lines from incomming byte arrays. or it would be good as well if it is possible to convert received data to inputStream as well.

You could do it with an ByteArrayInputStream and turn that into an BufferedReader. It is not very clean altough it should work.
InputStream inputStream = new ByteArrayInputStream(data);
BufferedReader buffReader = new BufferedReader(new InputStreamReader(inputStream));

You can convert byte array to String,
String inputStr = new String(data, "UTF-8");
And if you want to convert to InputStream,
InputStream dataInputStream = new ByteArrayInputStream(data);

Related

Read a socket direclty from InputStream or from BufferedReader?

My goal is to read the n number of bytes from a Socket.
Is it better to directly read from the InputStream, or wrap it into a BufferedReader?
Throughout the net you find both approaches, but none states which to use when.
Socket socket;
is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
char[] buffer = new char[CONTENT_LENGTH];
//what is better?
is.read(buffer);
br.read(buffer);
Since your goal is to "read the n number of bytes" there is little point creating a character Reader from your input as this might mean the nth byte is part way into a character - and assuming that the stream is character based.
Since JDK11 there is handy call for reading n bytes:
byte[] input = is.readNBytes(n);
If n is small and you repeat the above often, consider reading the stream using one of bis = new BufferedInputStream(is), in.transferTo(out) or len = read(byteArray) which may be more effective for longer streams.

Java - read an array of bytes from an InputStream until a certain character

i need to read an Base64 encoded array of bytes from an inputstream.
I have to stop reading when I reach a \n character in the decoded string, i cannot find an efficient way to do this.
Now i ended with something like this but it does not work as intended because it's too easy it catches an exception and messes all up...
byte buffer[] = new byte[2048];
byte results[] = new byte[2048];
String totalResult = null;
try {
int bytes_read = is.read(buffer);
while (buffer[bytes_read - 1] != '\n') {
bytes_read = is.read(buffer);
String app = new String(buffer, 0, bytes_read);
totalResult += app;
}
String response = Base64.getDecoder().decode(totalResult).toString();
Any idea? The input Stream does not close, so i need to get data from it and separated by '\n'
Rather than reinventing the wheel, consider using (for example) org.apache.commons.codec.binary.Base64InputStream from the Commons Codec project and a BufferedReader (JavaDoc) to wrap your InputStream like so:
try(BufferedReader reader = new BufferedReader(new InputStreamReader(new Base64InputStream(is)))) {
String response = reader.readLine();
...
}
Notes:
Try with resources will automatically close the reader when you're done.
The Base64InputStream will decode Base64 encoded characters on the fly
BufferedReader.readLine()considers \n, \r or \r\n to be line separators for the purpose of determining the end of a line.
I am sure other libraries exist that will facilitate the on-the-fly decoding, or you could write a simple InputStreamWrapper yourself.

GZIPInputStream unable to decode at receiver side (invalid code lengths set)

I'm attempting to encode a String in a client using GZIPOutputStream then decoding the String in a server using GZIPOutputStream.
The client's side code (after the initial socket connection establishment) is:
// ... Establishing connection, getting a socket object.
// ... Now proceeding to send data using that socket:
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
String message = "Hello World!";
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(message);
gzip.close();
String encMessage = out.toString();
out.writeInt(encMessage.getBytes().length);
out.write(encMessage.getBytes());
out.flush();
And the server's side code (again, after establishing a connection):
DataInputStream input = new DataInputStream(socket.getInputStream());
int length = input.readInt();
byte[] buffer = new byte[length];
input.readFully(buffer);
GZIPInputStream gz = new GZIPInputStream(new ByteArrayInputStream(buffer));
BufferedReader r = new BufferedReader(new InputStreamReader(gz));
String s = "";
String line;
while ((line = r.readLine()) != null)
{
s += line;
}
I checked and the buffer length (i.e., the coded message's size) is passed correctly, so the right number of bytes is transferred.
However, I'm getting this:
java.util.zip.ZipException: invalid code lengths set
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
at java.util.zip.GZIPInputStream.read(GZIPInputStream.java:117)
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:122)
at parsing.ReceiveResponsesTest$TestReceiver.run(ReceiveResponsesTest.java:147)
at java.lang.Thread.run(Thread.java:745)
Any ideas?
Thanks in advance for any assistance!
You're calling toString() on the ByteArrayOutputStream - that is incorrect, and it opens up all kinds of character encoding problems that are probably biting you here. You need to call toByteArray instead:
byte[] encMessage = out.toByteArray();
out.writeInt(encMessage.length);
out.write(encMessage);
Detail:
if you use toString(), Java will encode your bytes in your platform default character encoding. That could be some Windows codepage, UTF-8, or whatnot.
However not all characters can be encoded properly, and some will be replaced by an alternative character - a question mark perhaps. Without knowing the details, it's hard to tell.
But in any case, encoding the byte array to a String, and then decoding it to a byte array again when you write it out, is very likely to change the data in the byte array. And there is not need to do it, you can just get the byte array straight away as shown in the code above.
Why on earth are you indulging in all this complication? You can reduce it all to this:
GZIPOutputStream gzip = new GZIPOutputStream(socket.getOutputStream());
DataOutputStream out = new DataOutputStream(gzip);
String message = "Hello World!";
out.writeUTF(message);
out.close();
// ...
GZIPInputStream gz = new GZIPInputStream(new ByteArrayInputStream(socket.getInputStream()));
DataInputStream input = new DataInputStream(gz);
String line = input.readUTF();
I further note that your code doesn't actually compile. I would further note that unless the messages are several orders of magnitude larger, there is no benefit to the GZipping.

Read String and bytes from the same file java

I'm looking for a way to switch between reading bytes (as byte[]) and reading lines of Strings from a file. I know that a byte[] can be obtained form a file through a FileInputStream, and a String can be obtained through a BufferedReader, but using both of them at the same time is proving problematic. I know how long the section of bytes are. String encoding can be kept constant from when I write the file. The filetype is a custom one that is still in development, so I can change how I write data to it.
How can I read Strings and byte[]s from the same file in java?
Read as bytes. When you have read a sequence of bytes that you know should be a string, place those bytes in an array, put the array inside a ByteArrayInputStream and use that as the underlying InputStream for a Reader to get the bytes as characters, then read those characters to produce a String.
For the later parts of this process see the related SO question on how to create a String from an InputStream.
Read the file as Strings using a BufferedReader then use String.getBytes().
Why not try this:
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader("testing.txt"));
String line = bufferedReader.readLine();
while(line != null){
byte[] b = line.getBytes();
}
} finally {
if(bufferedReader!=null){
bufferedReader.close();
}
}
or
FileInputStream in = null;
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader("xanadu.txt"));
String line = bufferedReader.readLine();
while(line != null){
//read your line
}
in = new FileInputStream("xanadu.txt");
int c;
while ((c = in.read()) != -1) {
//read your bytes (c)
}
} finally {
if (in != null) {
in.close();
}
if(bufferedReader!=null){
bufferedReader.close();
}
}
Read everything as bytes from the buffered input stream, and convert string sections into String's using constructor that accepts the byte array:
String string = new String(bytes, offset, length, "US-ASCII");
Depending on how the data are actually encoded, you may need to use "UTF-8" or something else as the name of the charset.

Java sockets and file Streaming

I have a basic question on files ... It seems that I am stuck.
I am creating a server-client socket. The client sends a random number of integers to the server using an iterative way and the methods bellow.
//BufferedWriter out = new BufferedWriter(new OutputStreamWriter (sock.getOutputStream()));
out.write(number);
out.flush();
The server accepts them like this:
//BufferedReader in = new BufferedReader (new InputStreamReader (socket.getInputStream()));
number=in.read();
All , I want is the server to store all these integers into a file (myfile.txt for example) and then I want to read this file as a string (with all integers) in order to send it back to the client.
Any ideas? I tried few methods but right now I am totally stuck and I really cant think clear... I would really appreciate it if someone could help me out a bit.
Cheers
EDIT: I tried these methods so far
FileOutputStream fos = new FileOutputStream("myfile.txt");
DataOutputStream dos = new DataOutputStream(fos);
dos.writeInt(number);
And then I tried to read this with
FileInputStream fin=new FileInputStream("myfile.txt");
DataInputStream dis = new DataInputStream(fin);
int numbers = dis.read();
But all I get is the number 0. :S
Writing the file could be achieved like this
FileOutputStream fileOutputStream = new FileOutputStream("test.txt");
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream));
// Make sure to write the data as a String
bufferedWriter.write("" + number);
bufferedWriter.close();
fileOutputStream.close();
Afterwards, reading can be achieved like this
FileInputStream fileInputStream = new FileInputStream("test.txt");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
String line = bufferedReader.readLine();
number = Integer.valueOf(line);
Advantage of using a BufferedWriter and a BufferedReader is that you can read / write Strings and have a human readable file. Using a DataOutputStream, you'd have a binary file, and you'll have do conversion from / to your data format yourself.
Regarding your code example:
dis.read();
will return you the number of bytes read, not the actual data. You'd do that using
dis.readInt();

Categories

Resources