BufferedWriter is not writing to ByteArrayOutputStream - java

I want to convert an input stream to byte array. I know I can use IOUtils from commons-io. But I am practicing some basics in java io. I read an xml file using BufferedReader and tried writing it to a ByteArrayOutputStream using BufferedWriter. But its not working.
When I write directly to the ByteArrayOutputStream its working. Whats wrong in my code?
try (InputStream inputStream = getClass().getResourceAsStream(
"/productInventory.xml");
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(arrayOutputStream));
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(inputStream));) {
String line = "";
while ((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line);
}
System.out.println(arrayOutputStream.size());
} catch (IOException e) {
e.printStackTrace();
}
When I include below line in the loop its working
arrayOutputStream.write(line.getBytes(), 0, line.getBytes().length);
What is wrong while using BufferedWriter?

Nothing's wrong - it's just buffering! :D
The BufferedWriter works by filtering everything you send into it into a buffer - when the buffer is full, or when the writer is closed, or flushed, (It's a Closeable, so you should absolutely close it), it sends along those buffered characters to the underlying writer.
If you want to see the underlying writer update you have to either:
1) Fill up the buffer (default size is 8k in Java)
2) Call .flush()
3) Call .close()
4) As mentioned in comments, you can do a try-with-resources to make the close implicit:
try (BufferedWriter writer = new BufferedWriter(underlyingWriter)) {
// doStuff
}

Related

Java program is not writing all the records to the output file using the BufferedWriter

This below code is not able to write more than 29499 lines in the output file. More over the last line was printed only half. I have verified there is no issue with the program as the program is print all the 25000 lines in console.
FileReader fr = new FileReader(System.getProperty("user.dir") + "/json/Sample.json");
FileWriter fw = new FileWriter(System.getProperty("user.dir") + "/json/output.json");
BufferedReader br = new BufferedReader(fr);
BufferedWriter bw = new BufferedWriter(fw);
String line=br.readLine();
if (line == null)
{
br.close();
fr.close();
bw.flush();
bw.close();
fw.close();
}
while (line!=null) {
Gson gson = new Gson();
bw.write(record+"\n");
line=br.readLine();
}
You only close and flush your readers & writers if the first line is null. You presumably instead want to do this after your loop completes, which will ensure that (exceptions aside) they'll always close.
Even better, use the try with resources statement to avoid having to close / flush them manually at all - this will also handle the case where an exception it thrown.

Java IO, are these resources automatically closed?

In this code I read a text file, when BufferedReader is closed by "try-resource" block so the InputStreamReader does, then can I guarantee all the resources are closed like this?
try(final BufferedReader br = new BufferedReader(new InputStreamReader(new
FileInputStream(file), charset))) {
String line = null;
while((line = br.readLine()) != null) {
builder.append(line);
}
}
In this other example, I write a text file, as is written, are all the resources closed in the end? Is it mandatory to call flush()?
try(final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new
FileOutputStream(file), charset))) {
bw.write(text);
bw.flush();
}
Yes, the outermost streams call their inner streams' close() methods, so you only need to call the outermost stream.
You don't need to call flush(), the streams will flush when necessary and before being closed. Remove that and the code will look perfect.

Why output is incomplete using OutputStreamWriter with GZIPOutputStream?

I'm hoping someone can shed light on a problem I'm having with the code below.
private static String encode(String data) throws IOException {
try (
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream is = new ByteArrayInputStream(data.getBytes());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
OutputStreamWriter writer = new OutputStreamWriter(new GZIPOutputStream(out));
) {
char[] charBuffer = new char[data.length()];
while (br.read(charBuffer) != -1) {
writer.write(charBuffer);
}
// writer.close();
return new String(Base64.encodeBase64(out.toByteArray()));
}
}
My test value is
This is some text that I can test some base64 encoding with.
I am getting a strange problem with the encoded value
when writer.close is commented out, my output is
H4sIAAAAAAAAAA==
When it's not commented, my output is
H4sIAAAAAAAAACWMzQ2DMBSD70jdwRP0VLED9y7wACuJRJKKZ37GJxTJF/uz/Y3J0eQ1E+IpKJowYLLSvOshozn7D1imOqcScCTF96sbYBmB0p0ZXKuVQPzWOi7M/1b747PjjN2WjRd08DfZcwAAAA==
This second output is the correct value and can be decoded back into the original value.
It is my understanding that the process is as follows:
Try code is executed
Return value is evaluated and stored
Resources are all closed
The return value is returned.
Why then does the writer need to be closed for the output to be correct?
A GZIP output stream has to be told when to finish the compression and write the result to the underlying stream. close() implicitely flushes the writer and calls finish() on the GZIP stream.
So, call at least flush() on the writer and finish() or close() of the GZIP stream, or close the writer, which will do all that and won't hurt anyway.
Its because when we close the writer it flushes the stream. When you dont close the writer it does not get flushed (Buffer is flushed automatically only when it gets full or it is closed). So u can do it explicitly by writing
writer.flush()

BufferedReader then write to txt file?

Is it possible to use BufferedReader to read from a text file, and then while buffered reader is reading, at the same time it also storing the lines it read to another txt file using PrintWriter?
If you use Java 7 and want to copy one file directly into another, it is as simple as:
final Path src = Paths.get(...);
final Path dst = Paths.get(...);
Files.copy(src, dst);
If you want to read line by line and write again, grab src and dst the same way as above, then do:
final BufferedReader reader;
final BufferedWriter writer;
String line;
try (
reader = Files.newBufferedReader(src, StandardCharsets.UTF_8);
writer = Files.newBufferedWriter(dst, StandardCharsets.UTF_8);
) {
while ((line = reader.readLine()) != null) {
doSomethingWith(line);
writer.write(line);
// must do this: .readLine() will have stripped line endings
writer.newLine();
}
}
To directly answer your question:
you can, and you can also use BufferedWriter to do so.
BufferedReader br = new BufferedReader(new FileReader(new File("Filepath")));
BufferedWriter bw = new BufferedWriter(new FileWriter(new File("Filepath")));
String l;
while((l=br.readLine())!=null){
... do stuff ...
bw.write("what you did");
}
bw.close();
If you just need to copy without inspecting the data, then it's a one liner:
IOUtils.copy(reader, printWriter);
Yes. Open the BufferedReader, and then create a PrintWriter. You can read from the stream as you write to the writer.

Convert InputStreamReader to InputStream

How can I convert InputStreamReader to InputStream? I have an InputStream which contains some string and byte data and I want to parse it. So I wrap my InputStream to BufferedReader. Then I read 3 lines from it. After that I want to get the rest of data(bytes) as is. But if I try to get it nothing happens.
Code snippet:
BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
String endOfData = br.readLine();
String contentDisposition = br.readLine();
String contentType = br.readLine();
file = new File(filename);
if(file.exists()) file.delete();
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
byte[] data = new byte[8192];
int len = 0;
while (-1 != (len = is.read(data)) )
{
fos.write(data, 0, len);
Log.e("len", len+"");
}
fos.flush();
fos.close();
is.close();
The file is empty. If I don't wrap InputStream it works fine, but I need to read 3 lines and remove it.
Thanks.
If you want to mix text and byte data together, you should use OutputStream.writeUTF to write out those 3 lines, this way one single InputStream will be able to retrieve all the data that you need.
Take a look at commons-io's ReaderInputStream: it is a little heavy handed, but you can wrap the BufferedReader with that and read it as an input stream again.
It's pretty hard to mix byte and character input correctly, especially once you start throwing buffered readers / streams into the mix. I'd suggest that you either pick one and stick with it (converting your bytes to strings as necessary; care with the encoding!) or wrap the entire thing in a ZipOutputStream so you can have multiple logical "files" with different contents.

Categories