PrintWriter vs FileWriter in Java - java

Are PrintWriter and FileWriter in Java the same and no matter which one to use? So far I have used both because their results are the same. Is there some special cases where it makes sense to prefer one over the other?
public static void main(String[] args) {
File fpw = new File("printwriter.txt");
File fwp = new File("filewriter.txt");
try {
PrintWriter pw = new PrintWriter(fpw);
FileWriter fw = new FileWriter(fwp);
pw.write("printwriter text\r\n");
fw.write("filewriter text\r\n");
pw.close();
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

According to coderanch.com, if we combine the answers we get:
FileWriter is the character representation of IO. That means it can be used to write characters. Internally FileWriter would use the default character set of the underlying OS and convert the characters to bytes and write it to the disk.
PrintWriter & FileWriter.
Similarities
Both extend from Writer.
Both are character representation classes, that means they work with characters and convert them to bytes using default charset.
Differences
FileWriter throws IOException in case of any IO failure, this is a checked exception.
None of the PrintWriter methods throw IOExceptions, instead they set a boolean flag which can be obtained using checkError().
PrintWriter has an optional constructor you may use to enable auto-flushing when specific methods are called. No such option exists in FileWriter.
When writing to files, FileWriter has an optional constructor which allows it to append to the existing file when the "write()" method is called.
Difference between PrintStream and OutputStream: Similar to the explanation above, just replace character with byte.
PrintWriter has following methods :
close()
flush()
format()
printf()
print()
println()
write()
and constructors are :
File (as of Java 5)
String (as of Java 5)
OutputStream
Writer
while FileWriter having following methods :
close()
flush()
write()
and constructors are :
File
String
Link: http://www.coderanch.com/t/418148/java-programmer-SCJP/certification/Information-PrintWriter-FileWriter

Both of these use a FileOutputStream internally:
public PrintWriter(File file) throws FileNotFoundException {
this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
false);
}
public FileWriter(File file) throws IOException {
super(new FileOutputStream(file));
}
but the main difference is that PrintWriter offers special methods:
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.
Unlike the PrintStream class, if
automatic flushing is enabled it will
be done only when one of the println,
printf, or format methods is invoked,
rather than whenever a newline
character happens to be output. These
methods use the platform's own notion
of line separator rather than the
newline character.

A PrintWriter has a different concept of error handling. You need to call checkError() instead of using try/catch blocks.

PrintWriter doesn't throw IOException.You should call checkError() method for this purpose.

The java.io.PrintWriter in Java5+ allowed for a convenience method/constructor that writes to file.
From the Javadoc;
Creates a new PrintWriter, without automatic line flushing, with the specified file. This convenience constructor creates the necessary intermediate OutputStreamWriter, which will encode characters using the default charset for this instance of the Java virtual machine.

just to provide more info related to FLUSH and Close menthod related to FileOutputStream
flush() ---just makes sure that any buffered data is written to disk flushed compltely and ready to write again to the stream (or writer) afterwards.
close() ----flushes the data and closes any file handles, sockets or whatever.Now connection has been lost and you can't write anything to outputStream.

The fact that java.io.FileWriter relies on the default character encoding of the platform makes it rather useless to me. You should never assume something about the environment where your app will be deployed.

Related

Read a text file in JAVA

Text file can be directly read using FileReader & BufferedReader classes.
In several technote, it is mentioned to get the text file as a input stream, then convert to Inputstreamreader and then BufferedReader.
Any reasons why we need to use InputStream approach
FileReader is convenience class for reading character files. The constructors of this class assume that the default character encoding and the default byte-buffer size are appropriate. To specify these values yourself, construct an InputStreamReader on a FileInputStream.
Complement to this answer...
There really isn't a need to use a BufferedReader if you don't need to, except that it has the very convenient .readLine() method. That's the first point.
Second, and more importantly:
Use JSR 203. Don't use File anymore.
Use try-with-resources.
Both of them appeared in Java 7. So, the new way to read a text file is as such:
final Path path = Paths.get("path/to/the/file");
try (
final BufferedReader reader = Files.newBufferedReader(path,
StandardCharsets.UTF_8);
) {
// use reader here
}
In Java 8, you also have a version of Files.newBufferedReader() which does not take a charset as an argument; this will read in UTF-8 by default. Also in Java 8, you have Files.lines():
try (
final Stream<String> stream = Files.lines(thePath);
) {
// use the stream here
}
And yes, use try-with-resources for such a stream!

How to write formatted integers to file in i18n-friendly way in Java?

I'm currently using
try {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("open_sites_20,txt"), "UTF-8"));
writer.write(String.format("%4d%4d%n", i, j));
writer.close();
} catch (IOException e) {
System.err.print("error: " + e.toString() + "\n");
};
where i, j are integers.
FindBugs reports that the above has the following bad practice
Reliance on default encoding
Found a call to a method which will perform a byte to String (or String to byte) conversion, and will assume that the default platform encoding is suitable. This will cause the application behaviour to vary between platforms. Use an alternative API and specify a charset name or Charset object explicitly.
Any suggestion how this can be improved?
Platform: IntelliJ IDEA 13.1.1 + FindBugs-IDEA 0.9.992.
In this case, FindBugs seems to be wrong. Please keep in mind that its rules are not carved into stone, so it is necessary to apply your own judgment.
As for improving things. There are few way you can improve this code. First, let's deal with character encoding. Since Java 1.4, OutputStreamWriter contains constructor with the following signature:
OutputStreamWriter(OutputStream stream, Charset charEncoding)
It's better to use this, instead of passing the encoding name as string. Why? Starting with Java 7, you can use StandardCharsets enum to create a Charset class instance. Therefor you can write:
new OutputStreamWriter(new FileOutputStream("open_sites_20,txt"), StandardCharsets.UTF_8)
I don't think FindBugs would argue about that.
Another issue I see here, is the way you close writer. In some circumstances, this method will not be called. The best way to deal with it (if you are using Java 7 and above) is to use try-with-resources and let Java close streams/writers:
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("open_sites_20,txt"), StandardCharsets.UTF_8));) {
writer.write(String.format("%4d%4d%n", i, j));
// It always make sense to flush the stream before closing
writer.flush();
} catch (IOException e) {
System.err.print("error: " + e.toString() + "\n");
};
Now, all you do is write single value to file. If I were you, I would try to avoid all the overhead of creating streams, wrapping it with writers and so on. It's complicated. Fortunately, Java 7 has one fantastic class to help you write things to text files: Files.
The class has two methods that come in handy when you need to write something to a text file:
write(Path path, byte[] bytes, OpenOption... options)
write(Path path, Iterable<? extends CharSequence> lines, Charset cs, OpenOption... options)
The first one could also be used to write binary files. Second could be used to write a collection of strings (array, list, set, ...). Your program could be rewritten as:
try {
Path outputPath = Paths.get("open_sites_20,txt");
String nmbrStr = String.format("%4d%4d%n", i, j);
byte[] outputBytes = nmbrStr.getBytes(StandardCharsets.UTF_8));
Files.write(outputPath, outputBytes, StandardOpenOption.CREATE);
} catch (IOException ioe) {
LOGGER.severe(ioe);
}
That's it!
Simple and elegant. What I used here:
Paths
String.getBytes(Charset charEncoding) - I can't guarantee that FindBugs won't complain about this one
StandardOpenOption
Java Logging API - instead writing exceptions to System.out

Java - Possible to pipe PrintWriter to InputStream/Reader?

I want to pipe JSP PrintWriter out to another support class that takes InputStream or Writer as argument. I wonder if it's possible to simplify the process.
Of course I can write the output to a file, then use InputStream to read that file.
The "other" end of the JSP-provided PrintWriter is connected to the client (through the network, of course). You could create a new PrintWriter, pipe that to the support class and have the support class' output written to the original JSP PrintWriter.

writing to file: the difference between stream and writer

Hi I have a bit of confusion about the stream to use to write in a text file
I had seen some example:
one use the PrintWriter stream
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(fname)));
out.println(/*something to write*/);
out.close();
this instead use:
PrintStream out = new PrintStream(new FileOutputStream(fname));
out.println(/*something to write*/)
but which is the difference?both write in a file with the same result?
PrintWriter is new as of Java 1.1; it is more capable than the PrintStream class. You should use PrintWriter instead of PrintStream because it uses the default encoding scheme to convert characters to bytes for an underlying OutputStream. The constructors for PrintStream are deprecated in Java 1.1. In fact, the whole class probably would have been deprecated, except that it would have generated a lot of compilation warnings for code that uses System.out and System.err.
PrintWriter is for writing text, whereas PrintStream is for writing data - raw bytes. PrintWriter may change the encoding of the bytes to make handling text easier, so it might corrupt your data.
PrintWriter extends the class Writer, a class thinked to write characters, while PrintStream implements OutputStream, an interface for more generic outputs.

Write string to output stream

I have several output listeners that are implementing OutputStream.
It can be either a PrintStream writing to stdout or to a File, or it can be writing to memory or any other output destination; therefore, I specified OutputStream as (an) argument in the method.
Now, I have received the String. What is the best way to write to streams here?
Should I just use Writer.write(message.getBytes())? I can give it bytes, but if the destination stream is a character stream then will it convert automatically?
Do I need to use some bridge streams here instead?
Streams (InputStream and OutputStream) transfer binary data. If you want to write a string to a stream, you must first convert it to bytes, or in other words encode it. You can do that manually (as you suggest) using the String.getBytes(Charset) method, but you should avoid the String.getBytes() method, because that uses the default encoding of the JVM, which can't be reliably predicted in a portable way.
The usual way to write character data to a stream, though, is to wrap the stream in a Writer, (often a PrintWriter), that does the conversion for you when you call its write(String) (or print(String)) method. The corresponding wrapper for InputStreams is a Reader.
PrintStream is a special OutputStream implementation in the sense that it also contain methods that automatically encode strings (it uses a writer internally). But it is still a stream. You can safely wrap your stream with a writer no matter if it is a PrintStream or some other stream implementation. There is no danger of double encoding.
Example of PrintWriter with OutputStream:
try (PrintWriter p = new PrintWriter(new FileOutputStream("output-text.txt", true))) {
p.println("Hello");
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
OutputStream writes bytes, String provides chars. You need to define Charset to encode string to byte[]:
outputStream.write(string.getBytes(Charset.forName("UTF-8")));
Change UTF-8 to a charset of your choice.
You can create a PrintStream wrapping around your OutputStream and then just call it's print(String):
final OutputStream os = new FileOutputStream("/tmp/out");
final PrintStream printStream = new PrintStream(os);
printStream.print("String");
printStream.close();
By design it is to be done this way:
OutputStream out = ...;
try (Writer w = new OutputStreamWriter(out, "UTF-8")) {
w.write("Hello, World!");
} // or w.close(); //close will auto-flush
Wrap your OutputStream with a PrintWriter and use the print methods on that class. They take in a String and do the work for you.
You may use Apache Commons IO:
try (OutputStream outputStream = ...) {
IOUtils.write("data", outputStream, "UTF-8");
}
IOUtils.write(String data, OutputStream output, String encoding)

Categories

Resources