2

I'm having trouble understanding how do buffers work in Java IO.

Excuse me if I don't express myself as clearly as I would like, I'm not strong on all these concepts.

As I undestand it, in Java there are readers/writers, for chars (meaning the possibility of more than one byte per char and encoding options), and streams for bytes.

Then there are some classes that use buffers.

I believe that a buffer is used mainly so that we can avoid unnecessary system calls that would involve expensive operations, like accesing a slower device, by storing more in memory and making the system call useful for more data.

The issue I have is that there seem to be buffering classes for both readers/writers and streams.

I would like to know if buffering characters is enough, or if, by the time those bytes get to the streaming class, they would be flushed on for example newlines, as some classes state.

The best I've found about this is this post

How do these different code snippets compare in regard to buffering? Does autoflush thwart the intent of buffering? Should there be only one buffer in play, and if so, where (writer or stream) and why?:

// resolveSocket is some socket

PrintWriter out = new PrintWriter(
    resolveSocket.getOutputStream(),
    true); 

// vs

PrintWriter out = new PrintWriter(
    new OutputStreamWriter(
        new BufferedOutputStream(resolveSocket.getOutputStream()),
        StandardCharsets.UTF_8),
    true)

My interest is first and foremost to understand buffering better, and practical only after that.

Thak you all in advance.

EDIT: Found this other stack overflow question interesting and related.

Also this other one talks about BufferedOutputStream.

Community
  • 1
  • 1
ferhtgoldaraz
  • 1,693
  • 3
  • 15
  • 20

1 Answers1

1

It may help you to understand the difference between a writer and a stream. An OutputStream is a binary sink. A Writer has a character encoding and understands about newlines. The OutputStreamWriter allows you to send character encoded data, and have it correctly translated to binary for consumption by an OutputStream. What you probably want is:

PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(resolveSocket.getOutputStream())));

This will allow you to use your PrintWriter to output chars, have it buffered by the BufferedWriter, and then translated by the OutputStreamWriter for consumption by the socket output stream.

  • BufferedWriter buffers chars (I think). I am still a bit confsed, since there seems to be some kind of char buffering in PrintWriter. But mainly, what about BufferedOutputStream for buffering the bytes instead, or maybe also? how do these compare? – ferhtgoldaraz Feb 22 '15 at 19:40
  • 1
    Generally buffering closer to the object you are actually inserting characters into is best. PrintWriter may have some buffering to enable correctly formatting data. The Java API still recommends that use a buffering wrapper: http://docs.oracle.com/javase/7/docs/api/java/io/BufferedWriter.html – Randy Kamradt Sr. Feb 22 '15 at 19:53
  • Hi, Randy. Could you please explain why "buffering close to the object you are actually inserting characters into is best"? What is closer to the object? Thanks. – Unheilig Feb 26 '15 at 10:54
  • It seems reasonable that starting buffering as soon as possible would be most effective. In my example in the answer, the BufferedWriter is the immediate delegate of the PrintWriter, rather waiting until after the OutputStreamWriter to add a BufferedOutputStream. The Java API docs seem to back me up on this: http://docs.oracle.com/javase/7/docs/api/java/io/OutputStreamWriter.html – Randy Kamradt Sr. Feb 26 '15 at 13:50
  • After thinking about it further, it may be better to have a buffering class ahead of any 'constriction point', so one before the OutputStreamWriter, and one just before the SocketOutputStream. That way the buffer can act on the immediately delegated class directly. – Randy Kamradt Sr. Feb 26 '15 at 14:52