Tutorial :Java: BufferedReader reads more than a line?



Question:

I'm making a program in Java with Sockets. I can send commands to the client and from the client to the server. To read the commands I use a BufferedReader. To write them, a PrintWriter But now I want to transfer a file through that socket (Not simply create a second connection).
First I write to the outputstream how many bytes the file contains. For example 40000 bytes. So I write the number 40000 through the socket, but the other side of the connection reads 78.

So I was thinking: The BufferedReader reads more than just the line (by calling readLine()) and on that way I lose some bytes from the file-data. Because they are in the buffer from the BufferedReader.
So the number 78 is a byte of the file I want to transmit.

Is this way of thinking right, or not. If so, how to sovle this problem.
I hope I've explained well.


Here is my code, but my default language is Dutch. So some variable-name can sound stange.

public void flushStreamToStream(InputStream is, OutputStream os, boolean closeIn, boolean closeOut) throws IOException {      byte[] buffer = new byte[BUFFERSIZE];      int bytesRead;      if ((!closeOut) && closeIn) { // To Socket from File          action = "Upload";          os.write(is.available()); // Here I write 400000          max = is.available();          System.out.println("Bytes to send: " + max);          while ((bytesRead = is.read(buffer)) != -1) {              startTiming(); // Two lines to compute the speed              os.write(buffer, 0, bytesRead);              stopTiming(); // Speed compution              process += bytesRead;          }          os.flush();          is.close();          return;      }      if ((!closeIn) && closeOut) { // To File from Socket          action = "Download";          int bytesToRead = -1;          bytesToRead = is.read(); // Here he reads 78.          System.out.println("Bytes to read: " + bytesToRead);          max = bytesToRead;          int nextBufferSize;          while ((nextBufferSize = Math.min(BUFFERSIZE, bytesToRead)) > 0) {              startTiming();              bytesRead = is.read(buffer, 0, nextBufferSize);              bytesToRead -= bytesRead;              process += nextBufferSize;              os.write(buffer, 0, bytesRead);              stopTiming();          }          os.flush();          os.close();          return;      }      throw new IllegalArgumentException("The only two boolean combinations are: closeOut == false && closeIn == true AND closeOut == true && closeIn == false");  }  

Here is the solution:
Thanks to James suggestion
I think laginimaineb anwser was a piece of the solution.

Read the commands.

DataInputStream in = new DataInputStream(is); // Originally a BufferedReader  // Read the request line  String str;  while ((str = in.readLine()) != null) {      if (str.trim().equals("")) {         continue;      }      handleSocketInput(str);  }  

Now the flushStreamToStream:

public void flushStreamToStream(InputStream is, OutputStream os, boolean closeIn, boolean closeOut) throws IOException {      byte[] buffer = new byte[BUFFERSIZE];      int bytesRead;      if ((!closeOut) && closeIn) { // To Socket from File          action = "Upload";          DataOutputStream dos = new DataOutputStream(os);          dos.writeInt(is.available());            max = is.available();          System.out.println("Bytes to send: " + max);          while ((bytesRead = is.read(buffer)) != -1) {              startTiming();              dos.write(buffer, 0, bytesRead);              stopTiming();              process += bytesRead;          }          os.flush();          is.close();          return;      }      if ((!closeIn) && closeOut) { // To File from Socket          action = "Download";          DataInputStream dis = new DataInputStream(is);          int bytesToRead = dis.readInt();          System.out.println("Bytes to read: " + bytesToRead);          max = bytesToRead;          int nextBufferSize;          while ((nextBufferSize = Math.min(BUFFERSIZE, bytesToRead)) > 0) {              startTiming();              bytesRead = is.read(buffer, 0, nextBufferSize);              bytesToRead -= bytesRead;              process += nextBufferSize;              os.write(buffer, 0, bytesRead);              stopTiming();          }          os.flush();          os.close();          return;      }      throw new IllegalArgumentException("The only two boolean combinations are: closeOut == false && closeIn == true AND closeOut == true && closeIn == false");  }  

Martijn.


Solution:1

DataInputStream is most likely what you want to use. Also, don't use the available() method as it is generally useless.


Solution:2

I'm not sure I've followed your explanation.

However, yes - you have no real control over how much a BufferedReader will actually read. The point of such a reader is that it optimistically reads chunks of the underlying resource as needed to replenish its buffer. So when you first call readLine, it will see that its internal buffer doesn't have enough to serve youthe request, and will go off and read however many bytes it feels like into its buffer from the underlying source, which will generally be much more than you asked for just then. Once the buffer's been populated, it returns your line from the buffered content.

Thus once you wrap an input stream in a BufferedReader, you should be sure to only read that stream through the same buffered reader. If you don't you'll end up losing data (as some bytes will have been consumed and are now sitting in the BufferedReader's cache waiting to be served).


Solution:3

A BufferedReader assumes that it is the only one reading from the underlying input stream.

It's purpose is to minimize the number of reads from the underlying stream (which are expensive, as they can delegate quite deeply). To that end, it keeps a buffer, which it fills by reading as many bytes as possible into it in a single call to the underlying stream.

So yes, your diagnosis is accurate.


Solution:4

Just a wild stab here - 40000 is 1001110001000000 in binary. Now, the first seven bits here are 1001110 which is 78. Meaning, you're writing 2 bytes of information but reading seven bits.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »