Java: BufferedReader reading more lines?

I am making a Java program using Sockets. I can send commands to the client and client to the server. To read commands I use BufferedReader . To write them, PrintWriter But now I want to transfer the file through which socket (not just create a second connection).
First I write to the output stream how many bytes are in the file, For example, 40,000 bytes. Therefore, I am writing the number 40000 through the socket, but 78 is read on the other side of the connection.

So, I thought: BufferedReader reads more than just a line (by calling readLine() ), and so I lose a few bytes from the data files. Because they are in the buffer from the BufferedReader .
So the number 78 is the byte of the file I want to transfer.

Is this way of thinking right or wrong. If yes, then how to solve this problem.
I hope I have a good explanation.


Here is my code, but my default language is Dutch. Therefore, some variable name may sound non-standard.

 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 the suggestion of James
I think laginimaineb anwser was part 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 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"); } 

Martine.

+4
source share
4 answers

The DataInputStream is most likely what you want to use. Also, do not use the available () method, as it is usually useless.

+1
source

I'm not sure I followed your explanation.

However, yes, you have no real control over how much BufferedReader will actually read. The point of such a reader is that he optimistically reads fragments of the base resource as necessary to replenish his buffer. Therefore, when you first call readLine , it will see that its internal buffer is not enough to serve your request, and will go away and read, but how many bytes it considers in its buffer from the main source, which, as a rule, will be much larger than you asked for it then. After filling the buffer, it returns your string from the buffered contents.

Thus, as soon as you complete the input stream in the BufferedReader, you must be sure to read this stream only through the same buffer reader. If you do not, you will lose data (since some bytes will be consumed and are now in the BufferedReader cache, which is waiting for service).

+4
source

Just a wild hit here - 40000 - 1001110001000000 in binary format. Now the first seven bits are 1001110 here, which is 78. Meaning, you write 2 bytes of information, but you read seven bits.

0
source

BufferedReader assumes this is only one read from the main input stream.

The goal is to minimize the number of reads from the underlying stream (which are expensive since they can delegate deep enough). To this end, it stores a buffer that it fills by reading as many bytes as possible in one call to the underlying stream.

So, your diagnosis is accurate.

0
source

All Articles