I/O Character stream: BufferedReader vs printWriter construction - java

Why is BufferedReader created as such
BufferedReader br = new BufferedReader(new InputStreamReader(System.in))
while PrintWriter can be simply constructed like these
PrintWriter pw = new PrintWriter(System.out, true);
BufferedReader can't be constructed directly from System.in so it requires InputStreamReader to convert bytes to char, is this to make it human readable? But PrintWriter dosen't require a wrap from char back to bytes why is that so, does Java automate it? Because to a machine everything is 1 & 0 anyway.

so it requires InputStreamReader to convert bytes to char, is this to
make it human readable?
No, it's for performance. Check this to see the difference between them.
And there are BufferedWriter and BufferedReader, they have similar functions and constructors.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufferedWriter = new BufferedWriter(new PrintWriter(System.out));

First:
- Binary data: byte[], InputStream, OutputStream;
- (Unicode) text: String, char, Reader, Writer;
- Bridges where binary data has some encoding/Charset and is actually text: InputStreamReader, OutputStreamWriter (converting from/to given or default Charset).
Now consider:
System.in is a InputStream.
System.out and System.err are a PrintStream extending from OutputStream.
They are conceived as for binary data, which for Unix is quite normal and useful. For a console however not so useful. However PrintStream might be a design mishap/error: it has text support, also for passing a Charset; it is a half OutputStreamWriter.
So see PrintStream as an old unclean class doing what an OutputStreamWriter + BufferedWriter does, however not being a Writer.
BufferedWriter+OutputStreamWriter has the same complexity (though being reversed) as PrintStream. One also sees Scanner: new Scanner(System.in). This is not a Reader, and has superfluous support for tokenizing. It like PrintStream has the advantage of briefness, but is definitely more unclean for its unneeded overhead. (There are quite a lot of bugs mentioned in StackOverflow on Scanner.)

Related

How do buffers work in java IO?

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.
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.

The role of FileReader and BufferedReader - why wrapp FileReader?

I cannot really grasp what the purpose is for the FileReader and BufferedReader classes in Java.
At docs.oracle one is recommended to wrap a buffered reader around a FileReader object because it's not efficient to use the FileReader directly. Where does the cost or overhead come from?
Let say I have a text file that I want to read into my java program using these classes:
I use FileReader and BufferedReader
FileReader fileReader = new FileReader(new File("text.txt)"); // probably correct???
BufferedReader bufferedReader = new BufferedReader(fileReader);
1) What is the task of the FileReader object here? Is it responsible to make an I/O-request via the OS to the file, and thereafter read bytes? What is the cost with this?
Is it true that the FileReader makes several I/O-requests? Or is the cost when the FileReader object has to converting bytes to characters, character by character?
2) The task of the BufferedReader-object - to refer to the last sentence above. - Is the role for the BufferedReader-object to simply buffer arrays of incoming bytes and THEN convert those to character?
Very grateful for answers
Edit: first of all thanks for incoming answers. But I should have mentioned that its exactly this documentation I have studied. Call me stupid or something - but what is meant by "each read request". WHEN is each read request made? how often?
In general, each read request made of a Reader causes a corresponding read request to be made of the underlying character or byte stream. It is therefore advisable to wrap a BufferedReader around any Reader whose read() operations may be costly, such as FileReaders and InputStreamReaders. For example,
This is mostly why a launched this question - It sounds that the FileReader causes a lot of I/O-request which slows erverthing down.
From oracle docs :
In general, each read request made of a Reader causes a corresponding
read request to be made of the underlying character or byte stream. It
is therefore advisable to wrap a BufferedReader around any Reader
whose read() operations may be costly, such as FileReaders and
InputStreamReaders. For example,
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
will buffer the input from the specified file. Without buffering, each
invocation of read() or readLine() could cause bytes to be read from
the file, converted into characters, and then returned, which can be
very inefficient.
So, as the document clearly suggests, Wrapping a BufferedReader around a FileReader prevents reading of data from the file over and over again. BufferedReader buffers the input.
Java has many I/O classes which may be combined. So you might see something like:
BufferedReader in = new BufferedReader(new InputStreamReader(
new FileInputStream(new File("..."), "UTF-8"));
...
in.close(); // Closes all.
This allows flexible combination. So an XML parser could use Reader, and not care where the text comes from: file, URL, memory. This as opposed to "simpler" languages, where there is no choice of implementation (Map with implementations HashMap, TreeMap).
Now, FileReader and FileWriter are old utility classes to read from and write to a file in the default operating system encoding. So for local files. Not portable (!) to other operating systems, or requiring a fixed encoding.
For this FileReader extends InputStreamReader which reads binary data (an InputStream) using a FileInputStream. It does just that.
However it makes sense to use a larger memory buffer to read, hence the advice; which also is long-standing. Remember performance was an issue in the early times of java.
The only advantage of FileReader-standalone would be for tight memory situations, maybe on a smart phone.

FileWrite BufferedWriter and PrintWriter combined

Ok so I am learning about I/O, and I found the following code in one of the slides. can someone please explain why there is a need to have a FileWrite, BufferedWriter and PrintWriter? I know BufferedWriter is to buffer the output and put it all at once but why would they use FileWriter and PrintWriter ? dont they pretty much do the same with a bit of difference in error handling etc?
And also why do they pass bw to PrintWriter?
FileWriter fw = new FileWriter (file);
BufferedWriter bw = new BufferedWriter (fw);
PrintWriter outFile = new PrintWriter (bw);
Presumably they're using a FileWriter because they want to write to a file. Both BufferedWriter and PrintWriter have to be given another writer to write to - you need some eventual destination.
(Personally I don't like FileWriter as it doesn't let you specify the encoding. I prefer to use FileOutputStream wrapped in an OutputStreamWriter, but that's a different matter.)
BufferedWriter is used for buffering, as you say - although it doesn't buffer all the output, just a fixed amount of it (the size of the buffer). It creates "chunkier" writes to the underlying writer.
As for the use of PrintWriter - well, that exposes some extra methods such as println. Personally I dislike it as it swallows exceptions (you have to check explicitly with checkError, which still doesn't give the details and which I don't think I've ever seen used), but again it depends on what you're doing. The PrintWriter is passed the BufferedWriter as its destination.
So the code below the section you've shown will presumably write to the PrintWriter, which will write to the BufferedWriter, which will (when its buffer is full, or it's flushed or closed) write to the FileWriter, which will in turn convert the character data into bytes on disk.
From the Docs:
In general, a Writer sends its output immediately to the underlying character or byte stream. Unless prompt output is required, it is advisable to wrap a BufferedWriter around any Writer whose write() operations may be costly, such as FileWriters and OutputStreamWriters. For example,
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
will buffer the PrintWriter's output to the file. Without buffering, each invocation of a print() method would cause characters to be converted into bytes that would then be written immediately to the file, which can be very inefficient.
You can understand from this that a BufferedWriter is an efficient way to write stuff.
Writes text to a character-output stream, buffering characters so as to provide for the efficient writing of single characters, arrays, and strings.
A FileWriter object is passed to the BufferedWriter as the intent here is to write to some output file using a BufferedWriter.
And finally, a PrintWriter is used for print* methods like println().
PrintWriter from here
Prints formatted representations of objects to a text-output stream.
This class implements all of the print methods found in PrintStream.
It does not contain methods for writing raw bytes, for which a program
should use unencoded byte streams.
from the above statement it seems the main reason to use PrintWriter is to get the access of all the methods of PrintStream like println(),println(char [] x) etc.
BufferedWriter, You are right It's one of the best way to write to a file because it will buffered the character into the virtual memory before writing to a file directly and came up with a newLine() method.
FileWriter from here
FileWriter is meant for writing streams of characters. For writing
streams of raw bytes, consider using a FileOutputStream
.
FileWriter is simply to write plain text(without formatting) it doesn't use any buffer mechanism, whatever comes its way it just writes.
BufferedWriter is a wrapper for Writer classes to allow it to be able to use buffer functionality (to optimize IO).
PrintWriter prints formatted text, you can provide format string along with the data to be printed, though it can directly work with any Writer/OutputStream, just to provide buffering, Writer/OutputStream is 1st passed to BufferedWriter then to have formatted text is passed to PrintWriter
Usually, this kind of Writer chaining is about abstraction. PrintWriter have some useful print and println methods that can be convenient if you want to print Strings and lines to a File. Working directly with FileWriter, you would have to use a more "low level" API. And as you say BufferedWriter is about buffering. So it's basically a matter of what you want to output to the file, and what level of abstraction you prefer.
The objects are wrapped in this order because you want to use the outermost PrintWriter for its more sophisticated formatting. BufferedWriter must be wrapped on something. So FileWriter, as a result, is what BufferedWriter wraps and is the innermost object.

Need for Data Input Stream

What is the difference between
FileInputStream fstream = new FileInputStream ("file1.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
and
FileInputStream fstream = new FileInputStream ("file1.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
Do we really need a DataInputStream here?
The use of DataInputStream is a common mistake which I believe comes from copy-and-paste from different pieces of code. You want to read the files as either text e.g. BufferedReader OR binary e.g. DataInputStream. Its highly unlikely you want to use both and trying to is likely to lead to confusion.
For Text which is buffered
BufferedReader br = new BufferedReader(new FileReader(file));
For binary which is buffered
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
The significant thing about the object passed to the InputStreamReader() constructor is that it will be the object that will bear the weight of any synchronization holds. If you don't want your FileInputStream to potentially be held up by many calls to it, then the second option is the way to go. See the source of Reader.
FileInputStream is meant for reading streams of raw bytes such as
image data. For reading streams of characters, consider using
FileReader.
A data input stream lets an application read primitive Java data types
from an underlying input stream in a machine-independent way. An
application uses a data output stream to write data that can later be
read by a data input stream.
DataInputStream is not necessarily safe for multithreaded access.
FileInputStream only gives you a very basic interface.
When you're wanting to read numbers, Strings (or even complex Objects) rather than just bytes, that's a pain. So you use a second input stream "wrapping" the first, which gives you a more useful interface. DataInputStream is one of these.
It depends, A data input stream lets an application read primitive Java data types from an underlying input stream in a machine-independent way. An application uses a data output stream to write data that can later be read by a data input stream. Check JavaDoc
BufferedReader : Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines.
FileInputStream : Using FileInputStream, you will read file data in bytes.
No, there is no need for DataInputStream in your example because you are finally getting a BufferedReader to read data.
What would instead make sense is:
FileInputStream fstream = new FileInputStream ("file1.txt");
BufferedInputStream br = new BufferedInputStream(fstream);
DataInputStream dis = new DataInputStream(br);
Usually this would go hand in hand when you have created "file1.txt" using:
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("file1.txt")));
Edit:
Why is it allowed by Java if it doesn't really make sense? Because this is Decorator pattern and this is one of the disadvantages of Decorator pattern.

Difference between java.io.PrintWriter and java.io.BufferedWriter?

Please look through code below:
// A.class
File file = new File("blah.txt");
FileWriter fileWriter = new FileWriter(file);
PrintWriter printWriter = new PrintWriter(fileWriter);
// B.class
File file = new File("blah.txt");
FileWriter fileWriter = new FileWriter(file);
BufferedWriter bWriter = new BufferedWriter(fileWriter);
What is the difference between these two methods?
When should we use PrintWriter over BufferedWriter?
PrintWriter gives more methods (println), but the most important (and worrying) difference to be aware of is that it swallows exceptions.
You can call checkError later on to see whether any errors have occurred, but typically you'd use PrintWriter for things like writing to the console - or in "quick 'n dirty" apps where you don't want to be bothered by exceptions (and where long-term reliability isn't an issue).
I'm not sure why the "extra formatting abilities" and "don't swallow exceptions" aspects are bundled into the same class - formatting is obviously useful in many places where you don't want exceptions to be swallowed. It would be nice to see BufferedWriter get the same abilities at some point...
The API reference for BufferedWriter and PrintWriter detail the differences.
The main reason to use the PrintWriter is to get access to the printXXX methods like println(). You can essentially use a PrintWriter to write to a file just like you would use System.out to write to the console.
A BufferedWriter is an efficient way to write to a file (or anything else), as it will buffer the characters in Java memory before (probably, depending on the implementation) dropping to C to do the writing to the file.
There is no such concept as a "PrintReader"; the closest you will get is probably java.util.Scanner.
As said in TofuBeer's answer both have their specialties. To take the full advantage of PrintWriter (or any other writer) but also use buffered writing you can wrap the BufferedWriter with the needed one like this:
PrintWriter writer = new PrintWriter(
new BufferedWriter (
new FileWriter("somFile.txt")));
PrintWriter just exposes the print methods on any Writer in character mode.
BufferedWriter is more efficient than , according to its buffered methods.
And it comes with a newLine() method, depending of your system platform, to manipulate text files correctly.
The BufferedReader permits to read a text from file, with bytes converted in characters. It allows to read line by line.
There is no PrintReader, you have to choose another Reader implementation according to the format of your input.
PrintWriter is the most enhanced Writer to write Character data to a file.
The main advantage of PrintWriter over FileWriter and BufferedWriter is:
PrintWriter can communicate directly with the file, and can communicate via some Writer object also.
PrintWriter printwriter = new PrintWriter("blah.txt");
(or)
FileWriter filewriter = new FileWriter("blah.txt");
PrintWriter printwiter = new PrintWriter(filewriter);
We can write any type of Primitive data directly to the file (because we have additional overloaded versions of PrintWriter methods i.e., print() and println()).
printwriter.print(65); //65
bufferedwriter.write(65); //A
printwriter.println(true); //true
In general, a Writer sends its output immediately to the underlying character or byte stream. Unless prompt output is required, it is advisable to wrap a BufferedWriter around any Writer whose write() operations may be costly, such as FileWriters and OutputStreamWriters. For example,
Note: Text content in the code blocks is automatically word-wrapped
PrintWriter out =
new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
will buffer the PrintWriter's output to the file. Without buffering, each invocation of a print() method would cause characters to be converted into bytes that would then be written immediately to the file, which can be very inefficient.
BufferedWriter - Writes text to an output character stream, buffering characters from a character stream.
PrintWriter - Prints formatted representations of objects to a text output stream.
I think that the reason behind using PrintWriter is already mentioned above but one of the important reason is you an pass a file object directly to the PrintWriter constructor which makes it easy to use it.
File file=new File(“newfile.txt”);
PrintWriter pw=new PrintWriter(file);

Categories