what about one BufferedOutputStream wrap another BufferedOutputStream? this question is simple. but confused.
As the following code,
OutputStream file = new FileOutputStream("test.txt");
OutputStream buffer = new BufferedOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(buffer); //wrap buffer twice
OutputStream outputStream = new ObjectOutputStream(bufferedOutputStream); // wrap as ObjectOutputStream
BufferedOutputStream bufferedOutputStream1 = new BufferedOutputStream(outputStream); //wrap back as BufferedOutputStream
ObjectOutput output = new ObjectOutputStream(bufferedOutputStream1);
What about it? Question?
If you're asking whether an inefficiency is introduced, the answer is 'no'. The code is optimised to handle that case, or rather the case where the transfer size >= the buffer size.
Related
I have a serializable object and I want to write it down to file. Should I use ObjectOutputStream.writeObject() or convert it into a byte[] (using ObjectOutputStream) then use FileOutputStream.write()?
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file))
objectOutputStream.writeObject(myObject);
or
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out;
out = new ObjectOutputStream(byteOut);
out.writeObject(myObject);
new FileOutputStream(file).write(byteOut.toByteArray());
Buffering can improve performance by coalescing small writes into larger bulk writes. If you want to introduce buffering use a BufferedOutputStream, which does what you're doing with the byte array stream without changing downstream code.
// Unbuffered
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
// Buffered
ObjectOutputStream outputStream = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
This way you can continue to use ObjectOutputStream without the rest of the code having to know whether the stream is buffered or unbuffered.
As with any performance-related change, you should benchmark both approaches to see which performs better. Don't make changes like this without empirical testing. If you don't test, you're just guessing.
recently i had troubles working with InputStreams and OutputStreams when i was trying to implement a basic file downloader in my android application.. to elaborate things this is how i did it..
i get an InputStream object using the apache HttpClient classes then tried writing the stream to a file.. but strangely when i buffer the InputStream or the OutputStream i get an unreadable file.... this is the code..
//to make the code concise i removed exceptions and stream closing..
private void download(InputStream in,String fileName){
//if i dont use the buffered thing and read directly from in everything is ok
// same is the buffered out i had to use in/outstream
BufferedInputStream bufferedIn = new BufferedInputStream(in);
FileOutputStream fout = new FileOutputStream(new File(fileName));
BufferedOutputstream bufferedOut = new BufferedOutputstream(fout);
int read = -1;
while((read = bufferedIn.read()) != -1){
bufferedOut.write(read);
}
//close the buffers
}
You have to flush the buffered outputstream when you're done with it.
In any case you probably want to flush() your output (done implicitly by close()), but with BufferedOutputStream this is even more important than with a other OutputStreams. If you have a FileOutputStream, the only buffering performed is that of the OS. If you have a BufferedOutputStream, Java performs its own buffering on top of it.
If you use Java 7 or newer, I'd recommend to write the code like this:
try (BufferedInputStream bIn = new BufferedInputStream(in);
BufferedOutputStream bOut = new BufferedOutputStream(new FileOutputStream(fileName))) {
for (int read; ((read = bIn.read()) != -1; )
bOut.write(read);
}
In your case I suspect you were closing the FileOutputStream but not the BufferedOutputStream. Therefore the file was truncated or even empty because the data buffered in the BufferedOutputStream was not flushed.
I've the necessity to share a streaming of data between two instances as below:
// get EClasses which should be connected
final uk.man.xman.xcore.Parameter source = getParameter(sourceAnchor);
final uk.man.xman.xcore.Parameter target = getParameter(targetAnchor);
// Set data channels
//Output stream
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(new BufferedOutputStream(outputStream));
source.setOutputStream(dataOutputStream);
//Input stream
DataInputStream inpuDataStream = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(outputStream.toByteArray())));
target.setInputStream(inpuDataStream);
Everything works ok if I write, during those lines of code. Strangely, when I need to use the data channel to write something in another class, like here:
DataOutputStream dataOutputStream = (DataOutputStream) inputParameter.getOutputStream();
System.out.println("WRITE:" + attributes.getValue("value"));
dataOutputStream.writeUTF(attributes.getValue("value"));
dataOutputStream.flush();
I am not able to read, and I really do not know why. Am I missing something?
Thanks for your time
Not sure if that's what you're asking, but you're creating an InputStream that reads from an empty byte array. That doesn't make much sense:
// create an Output stream that will write in memory
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
...
// transform what has been written to the output stream into a byte array.
// Since othing has been written yet, outputStream.toByteArray() returns
// an empty array
DataInputStream inpuDataStream = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(outputStream.toByteArray())));
I know that java I/O uses decorator pattern. But I feel that I understand its wrong.
Please clarify difference between two code snippets:
snippet 1:
PipedInputStream pipedInputStream = new PipedInputStream();
PipedOutputStream pipedOutputStream = new PipedOutputStream();
pipedOutputStream.connect(pipedInputStream);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(pipedOutputStream);
objectOutputStream.writeObject("this is my string");
ObjectInputStream objectInputStream = new ObjectInputStream(pipedInputStream);
System.out.println(objectInputStream.readObject());
This application works according my expectations and I see result in console.
snippet 2:
I try to wrap ObjectInputStream and ObjectOutputStream twice:
PipedInputStream pipedInputStream = new PipedInputStream();
PipedOutputStream pipedOutputStream = new PipedOutputStream();
pipedOutputStream.connect(pipedInputStream);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(pipedOutputStream);
ObjectOutputStream objectOutputStreamWrapper = new ObjectOutputStream(objectOutputStream); //double wrapping
objectOutputStreamWrapper.writeObject("this is my string");
ObjectInputStream objectInputStream = new ObjectInputStream(pipedInputStream);
ObjectInputStream objectInputStreamWrapper = new ObjectInputStream(objectInputStream);
System.out.println(objectInputStreamWrapper.readObject());
This code just hangs up. I don't understand why. please clarify.
P.S.
It is theoretical question only.
UPDATE
Really hangs up behaviour happens because of I use pipes (According EJP answer).
for example this code works according expectations.
OutputStream outputStream = new FileOutputStream("2.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
ObjectOutputStream objectOutputStreamWrapper = new ObjectOutputStream(objectOutputStream); //double wrapping
objectOutputStreamWrapper.writeObject("this is my string");
objectOutputStream.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("2.txt"));
ObjectInputStream objectInputStreamWrapper = new ObjectInputStream(objectInputStream);
System.out.println(objectInputStreamWrapper.readObject());
objectInputStream.close();
looks like if I wrap input by 10 decorators I should wrap output by 10 decorators at the same order. Is it true ?
UPDATE + 1
I noticed that problem with flushing only:
PipedInputStream pipedInputStream = new PipedInputStream();
PipedOutputStream pipedOutputStream = new PipedOutputStream();
pipedOutputStream.connect(pipedInputStream);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(pipedOutputStream);
ObjectOutputStream objectOutputStreamWrapper = new ObjectOutputStream(objectOutputStream); //double wrapping
objectOutputStreamWrapper.writeObject("this is my string");
objectOutputStreamWrapper.flush();
ObjectInputStream objectInputStream = new ObjectInputStream(pipedInputStream);
ObjectInputStream objectInputStreamWrapper = new ObjectInputStream(objectInputStream);
System.out.println(objectInputStreamWrapper.readObject());
You're misusing piped streams. They are intended to be used by a producer thread doing writes and a consumer thread doing reads. See the Javadoc.
The piped streams share a buffer which can fill if the reading thread isn't reading, which stalls your writing thread.
Wrapping streams twice doesn't have anything to do with it, although in this case it is certainly both pointless and problematic.
PipedInputStream pipedInputStream = new PipedInputStream();
PipedOutputStream pipedOutputStream = new PipedOutputStream();
pipedOutputStream.connect(pipedInputStream);
//writing
ObjectOutputStream objectOutputStream = new ObjectOutputStream(pipedOutputStream);
//ObjectOutputStream objectOutputStreamWrapper =new ObjectOutputStream(objectOutputStream);
//ObjectOutputStream objectOutputStreamWrapper1=new ObjectOutputStream(objectOutputStreamWrapper);
//objectOutputStreamWrapper1.writeObject("this is my string");
//objectOutputStreamWrapper1.flush();
objectOutputStream.writeObject("this is my string");
//reading
ObjectInputStream objectInputStream = new ObjectInputStream(pipedInputStream);
//ObjectInputStream objectInputStreamWrapper = new ObjectInputStream(objectInputStream);
//ObjectInputStream objectInputStreamWrapper1=new ObjectInputStream(objectInputStreamWrapper);
//System.out.println("going to read from piped source");
//System.out.println(objectInputStreamWrapper1.readObject());
System.out.println(objectInputStream.readObject());
Snippet 1 - OutputStream created with Piped stream, then the input stream directly receive the data from the pipe through buffer without flushing.
Update + 1 - OutputStream created with outputstream wrapper in turn with another wrapper(commented the wrapper statments) and so on works after flush statment. Flush explicitlty flushes the buffered data to the underlying stream, in our case a piped output stream or the output stream .
Nested stream can be used like FilterOutputStream can be used on top of ObjectOutputStream also.
Which is the fast way to write text file in java?
At the moment i use this way to write a text file:
FileOutputStream fos = new FileOutputStream('FileName');
DataOutputStream dos = new DataOutputStream(fos);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(dos, Charset.forName(this.config.getCharset())));
My file size will be up 3 GB.
Flush the buffer after significant chunk of data is written. FileOutputStream should be just enough for text files. There is no need for using DataOutputStream.
how about
FileOutputStream fos = new FileOutputStream('FileName');
BufferedOutputStream bof = new BufferedOutputStream(fos);
bof.write("some text".getBytes()); // or just byte array
or
FileWriter fstream = new FileWriter("out.txt");
BufferedWriter out = new BufferedWriter(fstream);
out.write("Some text");
You do not need to use DataOutputStream here.