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()
Related
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
}
I am writing some code for a programming contest in java. The input to the program is given using stdin and output is on stdout. How are you folks testing programs that work on stdin/stdout? This is what I am thinking:
Since System.in is of type InputStream and System.out is of type PrintStream, I wrote my code in a func with this prototype:
void printAverage(InputStream in, PrintStream out)
Now, I would like to test this using junit. I would like to fake the System.in using a String and receive the output in a String.
#Test
void testPrintAverage() {
String input="10 20 30";
String expectedOutput="20";
InputStream in = getInputStreamFromString(input);
PrintStream out = getPrintStreamForString();
printAverage(in, out);
assertEquals(expectedOutput, out.toString());
}
What is the 'correct' way to implement getInputStreamFromString() and getPrintStreamForString()?
Am I making this more complicated than it needs to be?
Try the following:
String string = "aaa";
InputStream stringStream = new java.io.ByteArrayInputStream(string.getBytes())
stringStream is a stream that will read chars from the input string.
OutputStream outputStream = new java.io.ByteArrayOutputStream();
PrintStream printStream = new PrintStream(outputStream);
// .. writes to printWriter and flush() at the end.
String result = outputStream.toString()
printStream is a PrintStream that will write to the outputStream which in turn will be able to return a string.
EDITED: Sorry I misread your question.
Read with scanner or bufferedreader, The latter is much faster than the former.
Scanner jin = new Scanner(System.in);
BufferedReader reader = new BufferedReader(System.in);
Write to stdout with print writer. You can also print directly to Syso but this is slower.
System.out.println("Sample");
System.out.printf("%.2f",5.123);
PrintWriter out = new PrintWriter(System.out);
out.print("Sample");
out.close();
I am writing some code for a programming contest in java. The input to the program is given using stdin and output is on stdout. How are you folks testing programs that work on stdin/stdout?
Another way to send characters to System.in is to use PipedInputStream and PipedOutputStream. Maybe something like the following:
PipedInputStream pipeIn = new PipedInputStream(1024);
System.setIn(pipeIn);
PipedOutputStream pipeOut = new PipedOutputStream(pipeIn);
// then I can write to the pipe
pipeOut.write(new byte[] { ... });
// if I need a writer I do:
Writer writer = OutputStreamWriter(pipeOut);
writer.write("some string");
// call code that reads from System.in
processInput();
On the flip side, as mentioned by #Mihai Toader, if I need to test System.out then I do something like:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
System.setOut(new PrintStream(baos));
// call code that prints to System.out
printSomeOutput();
// now interrogate the byte[] inside of baos
byte[] outputBytes = baos.toByteArray();
// if I need it as a string I do
String outputStr = baos.toString();
Assert.assertTrue(outputStr.contains("some important output"));
I have a method which accepts an InputStream (of binary data) and serializes it to XML. In order to do so, it wraps the stream with a base64 encoder and a Reader to convert it to character data. However, since the InputStream is passed in as a parameter, I would consider it a harmful side effect to close the stream, and the contract for Reader.close() says it would do just that. If I don't close the reader, the compiler warns me that I have a
Resource leak: reader is never closed
So, I can add a #SuppressWarnings( "resource" ) to the reader declaration, but is that the right thing to do? Am I missing something?
Here is the actual code:
/**
* Writes base64 encoded text read from the binary stream.
*
* #param binaryStream
* The binary stream to write from
* #return <code>this</code> XmlWriter (for chaining)
* #throws IOException
*/
public XmlWriter binary( InputStream binaryStream ) throws IOException {
Reader reader = new InputStreamReader(
new Base64InputStream( binaryStream, true, base64LineLength, base64LineSeparator.getBytes( charset ) ) );
int bufferSize = 2048;
int charsRead;
char[] buffer = new char[bufferSize];
while ( (charsRead = reader.read( buffer, 0, bufferSize )) >= 0 ) {
writer.write( buffer, 0, charsRead );
}
return this;
}
If you are a happy Java 7 user, try this:
try(InputStream binaryStream = /* ... */) {
xmlWriter.binary(binaryStream);
}
and stream is closed for you. If you can't use Java 7, I agree that it's not the responsibility of binary() method to close() the stream. Just ignore the warning and don't let tools drive your design. It's fine.
As a last resort you can write a lightweight Reader wrapper ignoring close(), but I don't advice it as it makes following the program flow harder.
Also let Apache Commons IO help you with IOUtils.copy():
public XmlWriter binary( InputStream binaryStream ) throws IOException {
Reader reader = new InputStreamReader(
new Base64InputStream( binaryStream, true, base64LineLength, base64LineSeparator.getBytes( charset ) ) );
IOUtils.copy(reader, writer);
return this;
}
This is a perhaps a "feature" in the way Base64InputStream work that even though you specify the length to read, it will close the underlying stream if you close it when clearly you intended not to read the whole stream.
You could wrap the binaryStream in an InputStream which ignores the close, or you could suppress the warning as you have.
I'm writing an InputStream that supplies lines from a file in constant intervals. I used BufferedReader before, but ran into buffering issues with it (wasn't getting anything until the entire file was read), and speed isn't an issue anyways (the intervals are something like every second, or every half second - along those lines). Is there a class with a readLine method like in BufferedReader, except unbuffered?
(Edit: I just checked - my class seems to work, apparently the problem was with the output)
Here's the code where I used the stream (OnlineDataSimulator). I already checked, the stream does exactly what I want, so apparently I'm doing something wrong with the output. (The actual problem is, I want output to occur every X milliseconds - X being the second parameter to OnlineDataSimulator. What happens when I run this code is, that I first get an X*lines wait and then the entire output at once instead.)
System.out.println("Testing:");
PrintStream fout = new PrintStream(new FileOutputStream("testfile"));
for(int i=0; i<20; ++i) {
fout.println(i);
}
fout.close();
BufferedReader fin = new BufferedReader(new InputStreamReader(
new OnlineDataSimulator("testfile",250)));
String line;
while((line=fin.readLine())!= null){
System.out.println(line);
System.out.flush();
}
fin.close();
(new File("testfile")).delete();
Try it this way.... This worked for me..
File f = new File("path");
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
String s = null;
while ((s=br.readLine())!=null)
{
System.out.println(s);
}
No, there is no other non-buffered option.
A solution would be to write your own Reader which has a InputStreamReader as an underlying stream and in the readLine() method you should call read() of the underlying input stream reader until "\n" is found. Aggregate all these and return them as a string.
If you don't want to have a real buffer but want to use the functionality of BufferedReader you could initialize it with buffer size 1. As you commented that speed isn't an issue maybe is the most reliable solution.
new BufferedReader(reader, 1)
public BufferedReader(Reader in, int sz)
and you can check the readLine() method source code here, in case you want to implement your own.
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.