understanding out.println in servlets - java

How in Servlets, out.println writes the html text to container's response object where normally in System.out.println() , it writes the text to the console??
This is creating a problem for me conceptually.

Neither PrintStream nor PrintWriter is specified in terms of a console.
A PrintStream adds functionality to another output stream, namely the ability to print representations of various data values conveniently. PrintStream
Prints formatted representations of objects to a text-output stream. PrintWriter
They are both about formatting data and passing the formatted data to an output stream. Any output stream. By default, in certain environments, the PrintStream objects initially referenced by each of System.out and System.err send their data to some sort of console, but that is just those particular instances.
Even those can be changed. For example, it can be useful in some types of testing to replace System.out with a PrintStream that sends its data to a ByteArrayOutputStream.

It uses a ServletOutputStream from the Javadoc,
Provides an output stream for sending binary data to the client. A ServletOutputStream object is normally retrieved via the ServletResponse.getOutputStream() method.
If you look at System.out you can see that it's a PrintStream which is a different implementation of OutputStream.

If someplace in a servlet an invocation of out.println(...) writes to the response object, then out must be a reference to the response object's OutputStream, or a wrapper stream and it. If System.out sends output someplace else (as normally it would do) then it is a reference to a different OutputStream.
A servlet method's (or any other method's) local variable named out is completely unrelated to System.out, barring you initializing the one as a reference to the other.

Related

Is there any difference between printing statements using PrintStream object and System.out.println() in Java?

I have printed the data by using PrintStream object as below.
PrintStream ps = new PrintStream(System.out);
ps.println("Printing");
And I have also printed the data using System.out.println();
System.out.println(("Printing"));
I see no difference between these two statements. Do anyone clarify about this?
In your example it would work in a similar way, but System.out.println("") is generally used as an easy way to log to the console, while the new PrintStream() could also be used to redirect to a different stream, such as a remote endpoint. Generally the System.out.println is the more commonly used way to print things to the console.
Btw, you can actually redirect the System.out to something else by using the System.setOut(stream), so you wouldn't lose flexibility if you would System.out.println.
I see no difference between these two statements.
I agree, functionally they're the same.
System.out returns a PrintStream, so this is fine:
PrintStream out = System.out;
out.println("Printing");
Creating a new PrintStream using the constructor where you pass in an OutputStream – as you did with this: new PrintStream(System.out) – will create a new PrintStream object wrapped around the constructor argument.
So when you did the code below, you're simply putting a wrapper around the same underlying output stream.
PrintStream ps = new PrintStream(System.out);
ps.println("Printing");
Either way, when you call println("Printing"), it's resolving to the same println() method.

What is "PrintStream target"?

public void print(PrintStream target) {
target.println(this.title);
target.println(this.firstName);
target.print(this.lastName);
}
Given this method, what should the main pass to the method as target? Also, what type of variable is target? What does it mean that it is of type PrintStream?
PrintStream is a Java Object Type used to specify an output stream to which data can be written. In this case, you would probably pass the method the System.out print stream, as this will cause it to print to the main system console. This is the same PrintStream that you would write to when you call System.out.println(). In some cases, a different PrintStream could be used if the output was to go to a file or be uploaded to the web or similar purposes other than simply printing to the console.

How do I choose which of the main Java IO classes I need to write strings to a file?

There are many different classes in the IO package, some seems to only have suble differences.
If you are to write some Strings to a text file, and read them for later use.
Which classes would you use for each of those two purposes and why?
BufferedInputStream
BufferedOutputStream
BufferedWriter
BufferedReader
DataInputStream
DataOutputStream
FileInputStream
FileOutputStream
FileReader
FileWriter
InputStreamReader
OutputStreamReader
Reader
Writer
It all depends on what you want to do.
Output Streams
In case you want to write byte data, you would use some subclass of OutputStream that is used to write bytes in destination defined by concrete subclass.
For example FileOutputStream is used to write data in file byte by byte (or bunch of bytes).
BufferedOutputStream is an optimized extension of FileOutputStream to write blocks of bytes to minimize number of disk operations. So when you call write, actually it may or may not be written in file - depends on buffer's state whether it is full or not. If buffer reaches it's max capacity, all bytes are flushed to file at once.
ByteArrayOutputStream is using just block of memory as a destination instead of file. Current stream content is obtained via toByteArray() method (why would you need such a stream will be explained later).
ObjectOutputStream is used to write objects (class instances) in some destination defined by the underlying OutputStream. For example, ObjectOutputStream(FileOutputStream) would write an objects in file, while ObjectOutputStream(ByteArrayOutputStream) would write an objects in memory. The last option allows you to serialize objects in byte buffer (array of bytes) which can be then send somewhere via network.
Note, that any object you want to write somewhere via ObjectOutputStream has to implement Serializable interface. Since object may contain references to another objects, all the objects that are accessible from the object to be serialized also has to implement Serializable interface as serialization, by default, is process of writting of full graph of objects - assuming you are not using transient keyword to exclude class field from serialization, or you are not defining at object's class a special methods writeObject/readObject that overrides default serialization behaviour. These methods are designed to implement custom serialization i. e. you can define on your own how to write/read class field in/from ObjectOutputStream/ObjectInputStream. Suppose class A for which you are implementing custom serialization contains an object of class B. Instead of writting object b as a full graph, i. e. instead of calling oos.writeObject(b), where oos is an argument of the writeObject method being implemented in class A, you would write in stream only some fields of class B e. g. oos.writeBoolean(b.isEnabled), oos.writeInt(b.value). As long as object b is not written via oos.writeObject(b), it does not have to implement Serializable interface. For more details see Serializable documentation.
DataOutputStream is used to write primitives like boolean, char, int, long, float, double. Since any object can be decomposed to primitives e. g. class A { int i = 0; B b = new B();}, class B {double d = 0.0;} can be written simply as int a, double d, you can use DataOutputStream to serialize objects in compressed way unlike serialization which writes much more data e. g. class path, class version, ... so ClassLoader can identify a given class in runtime, instantiate this class and finally load data to this empty object. Note that instantiating class by it's name + initialising object in this way is much slower than instantiating class on your own and initializing it's fields on your own from "raw" DataOutputStream (that's why OS Android prefers custom Parcelable interface over standard serialization, which works as writting/reading to/from DataOutputStream/DataInputStream).
In case you want to write string data, you would use OutputStreamWriter a higher level of output-stream which writes characters/Strings in destination defined by OutputStream (in case of writting in file, you would pass FileOutputStream, in case of writtin in memory you would pass ByteArrayOutputStream).
FileWriter is an extension of OutputStreamWriter designed for writting in file.
BufferedWriter works the same as BufferedOutputStream except it is designed for work with strings and characters.
CharArrayWriter works the same as ByteArrayOutputStream except characters are stored in char[] which is obtained by calling getCharArray().
StringWriter is similar to CharArrayWriter except it allows you to write strings which are stored in StringBuffer that is obtained by calling getBuffer().
PrintWriter allows you to write formatted strings in specified destination defined by OutputStream (this writer is designed for easy logging).
Input Streams
The same concept is applied to input-streams (readers) associated with given output-streams (writers) mentioned above.
Readers and InputStreams are for input while Writers and OutputStreams are for output.
Readers and Writers are for text (with a character set) while InputStreams and OutputStreams are for binary data (such as images).
Buffering helps with performance because reads and writes are batched rather than making a system call each time any method is used.
If it has "File" in the name, it is used for files.
So for your specific case you want to write text to a file, the most obvious candidate is a FileWriter:
Writer out = new FileWriter(
new File("foo.txt")
);
If you want better performance for making many small writes to it, you could wrap it in a buffer:
Writer out = new BufferedWriter(
new FileWriter(
new File("foo.txt")
)
);
The FileWriter assumes the default character encoding when writing text. If you want to choose the encoding, or ensure that it is consistent on all platforms, you could create the writer from an OutputStream specifying the encoding explicitly:
Writer out = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(
new File("foo.txt")
), "UTF-8"
)
);

Java writing to File or System.out

I need to write characters to a file or to standard output. And I am curious if it could be done with one method.
Now I have something like this:
OutputStream out;
if(toConsole)
out = System.out;
else
out = new FileOutputStream(file);
write(out);
}
void write (OutputStream str){
....
str.write(string);
But it is a problem that I am using (in case when "str" is System.out) write instead print?
(print java doc: "string's characters are converted into bytes according to the platform's default character encoding")
In case if I would use PrintWriter(or PrintStream) as a parameter then i cannot use BufferedWriter and writing to the file would be slower.
It is possible to use a same code (and same methods) for writing to a file and to System.out?
(This is for my school project so I want it to be a "pure" and fully correct)
What you're trying to accomplish, is to treat the fileoutput and the consoleoutput the same. This is possible, because System.out is a PrintStream, and you can create a PrintStream for a file like this
new PrintStream(yourFile)
or insert a BufferedOutputStream in between
new PrintStream(new BufferedOutputStream(new FileOutputStream(yourFile))).
Note that this is not needed, because PrintStream does buffer its output itself.
I would create a variable (global or not), representing the current output.
This might be a PrintStream, either System.out, or a PrintStream around a FileOutputStream, whatever you desire. You would then pass this stream to the write method or call the print methods on it directly.
The advantage is that you can easily switch this without much code modification, you can redirect it wherever you wan't. It's no problem to redirect it to a file and System.out! You wouldn't get that pure flexibility with the way you're writing the method currently.
You could (not saying you should), also redirect System.out directly, using System.setOut. This however is bad style, because it is quite uncommon and might confuse everyone else, if they have not seen the call to System.setOut.
System.out is an object of type PrintStream. So yes, you can write to
System.out and/or to another file using exactly the same methods. Just
construct a PrintStream object and direct it to your file. So declare
your out variable as PrintStream to start with.
See also:
http://docs.oracle.com/javase/7/docs/api/java/lang/System.html
http://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html

PrintWriter autoflush puzzling logic

public PrintWriter(OutputStream out, boolean autoFlush):
out - An output stream
autoFlush - A boolean; if true, the println, printf, or format methods
will flush the output buffer
public PrintStream(OutputStream out, boolean autoFlush):
out - The output stream to which values and objects will be printed
autoFlush - A boolean; if true, the output buffer will be flushed
whenever a byte array is written, one of the println methods is invoked,
or a newline character or byte ('\n') is written
What was the reason for changing autoflush logic between these classes?
Because they are always considered as identical except for encoding moments and "autoflush" without flushing on print() hardly corresponds to principle of least astonishment, silly bugs occur:
I created a PrintWriter with autoflush on; why isn't it autoflushing?
I think the answer lies in the history of Java. The trio InputStream, OutputStream and PrintStream in java.io date back to Java 1.0. That is before serious support for file encodings and character sets were built into the language.
To quote the Javadoc:
"A PrintStream adds functionality to
another output stream, namely the
ability to print representations of
various data values conveniently. Two
other features are provided as well.
Unlike other output streams, a
PrintStream never throws an
IOException; instead, exceptional
situations merely set an internal flag
that can be tested via the checkError
method..."
To summarize, it is a convenience for generating textual output, grafted on top of lower level IO.
In Java 1.1, Reader, Writer and PrintWriter were introduced. Those all support character sets. While InputStream and OutputStream still had a real uses (raw data processing), PrintStream became far less relevant, because printing by nature is about text.
The Javadoc for PrintWriter explicitly states:
Unlike the PrintStream class, if
automatic flushing is enabled it will
be done only when one of the println()
methods is invoked, rather than
whenever a newline character happens
to be output. The println() methods
use the platform's own notion of line
separator rather than the newline
character.
Put another way, PrintWriter should only be used through the print*(...) APIs, because writing newline characters etc should not be the caller's responsibility, the same way dealing with file encodings and character sets are not the caller's responsibility.
I would argue that PrintWriter should have been java.io.Printer instead, and not have extended Writer. I don't know whether they extended to mimic PrintStream, or because they were stuck on maintaining the pipe design idiom.
The reason it wasn't the same at start was probably just an accident. Now it's backwards compatibility.

Categories

Resources