Does a PrintWriter / PrintStream need to be flushed? - java

I'd like to use a PrintWriter or PrintStream to write formatted strings out to an outputstream (for which I have no control over the creation). However flushing the underlying OutputStream has a big performance hit.
Does a PrintWriter / PrintStream need to be flushed.
If I need to flush the PrintStream / PrintWriter; can I do so without flushing the underlying OutputStream, or will I need to create a "flush protecter" OutputStream to wrap the underlying stream?
To try to be a little clearer on this I want to implement
public void writeSomeString(OutputStream foo);
But this method may be called many times for the same OutputStream (foo). Each call will have to construct its own PrintWriter. I know it's ugly to do so but I have no control over the interface or the creation of foo.
I'm trying to avoid each method having to flush foo just to flush its own PrintWriter / PrintStream.
So I want to:
public void writeSomeString(OutputStream foo) {
PrintStream s = new PrintStream(foo);
s.println("bar");
// other code
}
I want to completely avoid this method flushing foo

PrintWriter needs to be flushed in the following condition:
ServerSocket s = new ServerSocket(4444);
Socket incoming = s.accept();
OutputStream output = s.getOutputStream();
PrintWriter pw = new PrintWriter(output,true);
System.out.println(pw.write(new Scanner(System.in).nextLine()));
2nd parameter in PrintWriter constructor is flush which accepts boolean datatype, we need to flush the data, so it gets thrown on the Console even if the buffer is not full.

Related

Compare DataOutputStream to String in Java

I have a DataOutputStream I would like to copy into a string. I've found a lot of tutorials on converting DataOutputStreams by setting it to a new ByteArrayOutputStream, but I just want to read the string it sends when it flushes, and my DataOutputStream is already assigned to an output stream though a socket.
output.writeUTF(input.readLine());
output.flush();
If the context is helpful, I'm trying to read the output stream of a server and compare it to a string.
the flush method will flush, i.e. force write, anything buffered, but not yet written.
In the code below, try putting a breakpoint on the second call to writeUTF - if you navigate to your file system you should see the created file, and it will contain "some string". If you put the break point on flush, you can verify that the content has already been written to file.
public static void test() throws IOException {
File file = new File("/Users/Hervian/tmp/fileWithstrings.txt");
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new FileOutputStream(file));
dos.writeUTF("some string");
dos.writeUTF("some other string");
dos.flush();//Flushes this data output stream. This forces any buffered output bytes to be written out to the stream.
} finally {
if (dos!=null) dos.close();
}
}
As such, you cannot extract the data from the DataOutputStream object, but in the example above we off course have those strings in the write calls.

Closing a Socket with Streams

The following question I have is pretty straightforward.
Here is my code:
public class Protocol implements Runnable {
private SSLSocket socket = null;
private InputStream is = null;
private OutputStream os = null;
...
public Protocol(Socket s) {
socket = (SSLSocket)s;
is = socket.getInputStream();
os = socket.getOutputStream();
}
#Override
public void run() {
...
ping();
socket.close();
...
}
public void ping() {
BufferedWriter writer;
try {
writer = new BufferedWriter(new OutputStreamWriter(os));
writer.write("OK");
}
catch (IOException e) { System.out.println("ERROR: " + e.getLocalizedMessage()); }
finally { writer = null; }
}
I understand I didn't include a lot of source code, but this should be enough to answer the question. As you can see, in the "ping" method I have a BufferedWriter which I create to write an "OK" string to the remote source. Later on, I close the Socket.
So my simple question is this - From what I understand, since I close the socket, the chain should go like this:
Close socket ----> which closes is and os ----> closes writer
So, by closing the Socket, I am also closing and allowing the BufferedWriter to be freed by the GC. Am I understanding this correctly or doing something wrong? Is this true for all writers and readers that I initialize in other methods (i.e. BufferedInputStream). And by setting these variables null at the end of the method, am I helping the GC to distinguish between what should be freed? Or should I not do this?
Thanks!
From what I understand, since I close the socket, the chain should go like this:
Close socket ----> which closes is and os ----> closes writer
No. The BufferedWriter is wrapped around the socket output stream, but the socket doesn't know that. It has no way of closing it.
So, by closing the Socket, I am also closing and allowing the BufferedWriter to be freed by the GC.
No and no. The BufferedWriter is available for GC as soon as ping() returns, and it is never closed at all.
Am I understanding this correctly
No.
or doing something wrong?
Yes. You shouldn't create a new BufferedWriter per message. You should use the same one for the life of the socket, and close it instead of the socket. Similarly you should only use one input stream or Reader for the life of the socket. Otherwise you can lose data in their buffers.
Is this true for all writers and readers that I initialize in other methods (i.e. BufferedInputStream).
No.
And by setting these variables null at the end of the method, am I helping the GC to distinguish between what should be freed?
No. You are just wasting time and space. The method is about to exit anyway, so all its local variables disappear.
Or should I not do this?
You should not do any of it.

PrintWriter not appending in Java, using FileOutputStream

This is my method to write to a file, this method belongs to a class
public void write(FileOutputStream fo) throws IOException
{
PrintWriter out=new PrintWriter(fo);
for (int i = 0; i < size; i++) {
String formatted="%3d";
for (int j=0;j<size;j++)
{
out.append(String.format(formatted,arr[i][j]));
}
out.append(System.getProperty("line.separator"));
}
out.append(System.getProperty("line.separator"));
out.close();
}
I want to write my results into many different files, corresponding to input files read by appropriate created object, so I pass the to-be-written file as a parameter to this method
It doesn't append at all
After spending hours searching for solution of this problem, I only got results of appending using PrintWriter with a specified path of file, for example:
PrintWriter out=new PrintWriter(new FileWriter("output1.txt",true));
If I use
PrintWriter out=new PrintWriter(new FileWriter(fo,true));
I encounter error
It doesn't append when write method of my 2 instances of that object is called
public void writeSolution() throws IOException
{
fo=new FileOutputStream("output\\output1.txt",true);
start.write(fo);
goal.write(fo);
fo.close();
}
Please help me solve this problem
When you close a PrintWriter, the close() method also closes the underlying stream/writer.
In every call to your write method, you open your PrintWriter and then you close it at the end. This means the stream is closed. Next time you open a PrintWriter to it, it is a closed file. You can't write to a closed file.
A PrintWriter does not throw exceptions when you do something like this, so it silently does nothing. And you are not calling its checkError() method, so you don't know that there was an error there.
What you should do is declare the PrintWriter as a field (so that it maintains its state between calls to write(), open it before you start calling the write() method, and close it after you finish calling the write() method for the last time. And remember to check errors.

What happens internally when the outermost Stream is closed?

I know that to close all the internal and enclosing streams you can close the outermost Stream and it will take care of the enclosing Streams but do it waits to read and write data completely before closing the internal streams or just perform the required operations.
I just want to figure out what happens and how internal functions are called on the inner streams when we close an enclosing Stream? Just like in the below code
public static void serialize(Object obj, String fileName)
throws IOException {
FileOutputStream fos = new FileOutputStream(fileName);
BufferedOutputStream bos = new BufferedOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(bos);
bos.flush();
oos.writeObject(obj);
oos.close();
}
When I close the Object Stream will it wait for File Stream to perform its function?
Yes, if you close the ObjectOutputStream, all pending write operations will be performed.
That is because ObjectOutputStream calls innerStream.flush() wenn you call close() on it.
And BufferedOutputStream also calls innerStream.flush() in its own flush method.
All buffering stream classes I know do so.

BufferedReader to BufferedWriter

How can I obtain a BufferedWriter from a BufferedReader?
I'd like to be able to do something like this:
BufferedReader read = new BufferedReader(new InputStreamReader(...));
BufferedWriter write = new BufferedWriter(read);
You can use the following from Apache commons io:
IOUtils.copy(reader, writer);
site here
JAVA 9 Updates
Since Java 9, Reader provides a method called transferTo with the following signature:
public long transferTo(Writer out) throws IOException
As the documentation states, transferTo will:
Reads all characters from this reader and writes the characters to the given writer in the order that they are read. On return, this reader will be at end of the stream. This method does not close either reader or writer.
This method may block indefinitely reading from the reader, or writing to the writer. The behavior for the case where the reader and/or writer is asynchronously closed , or the thread interrupted during the transfer, is highly reader and writer specific, and therefore not specified.
If an I/O error occurs reading from the reader or writing to the writer, then it may do so after some characters have been read or written. Consequently the reader may not be at end of the stream and one, or both, streams may be in an inconsistent state. It is strongly recommended that both streams be promptly closed if an I/O error occurs.
So in order to write contents of a Java Reader to a Writer, you can write:
reader.transferTo(writer);
If you want to know what happens:
All input from the reader is copied to the inputstream
Something similar too:
private final void copyInputStream( InputStreamReader in, OutputStreamWriter out ) throws IOException
{
char[] buffer=new char[1024];
int len;
while ( ( len=in.read(buffer) ) >= 0 )
{
out.write(buffer, 0, len);
}
}
More on input and output on The Really big Index
BufferedWriter constructor is not overloaded for accept readers right? what Buhb said was correct.
BufferedWriter writer = new BufferedWriter(
new FileWriter("filename_towrite"));
IOUtils.copy(new InputStreamReader(new FileInputStream("filename_toread")), writer);
writer.flush();
writer.close();
You could use Piped Read/Writers (link). This is exactly what they're designed for. Not sure you could retcon them onto an existing buffered reader you got passed tho'. You'd have to construct the buf reader yourself around it deliberately.

Categories