1

I have a simple servlet class returns CSV file to a client (browser). When I tried to write string to stream. Initially I have followed example A) however I noticed that subset of expected data are appended.

Let's say I expect exact 100 records to be captured in a csv file. Each record represent "first name/last name/age". In the example A) I got 120. First 100 records are correct but subset of 100 in this case 20 (duplicates) are appended.

example A)

public void returnCSV(HttpServletResponse resp, String data) {
    ServletOutputStream out = resp.getOutputStream();
    InputStream in = new ByteArrayInputStream(data.getBytes("UTF-8"));
    byte[] bytes = new byte[4096];
    while (in.read(bytes,0,4096) != -1) {
        out.write(bytes,0,4096);
    }
    in.close();
    out.flush();
    out.close();
 }

After reading more threads in regards to converting string to stream. I decided to follow example B) which produced correct output 100 records. But I do not understand why first example A) would add duplicate data.

example B)

public void returnCSV(HttpServletResponse resp, String data) {
    ServletOutputStream out = resp.getOutputStream();
    out.write(data.getBytes("UTF-8"));        
    out.flush();
    out.close();
 }

1 Answer 1

1

Look at this loop:

while (in.read(bytes,0,4096) != -1) {
    out.write(bytes,0,4096);
}

However much data is read by read, you're always writing out 4096 bytes. You only want to copy the same amount of data you've read, e.g.

int bytesRead;
while ((bytesRead = in.read(bytes)) != -1) {
    out.write(bytes, 0, bytesRead);
}

There are plenty of third-party libraries which have code to copy from an input stream to an output stream, mind you - and you should be using try-with-resources statements to close the streams anyway.

Additionally, instead of calling getOutputStream, you should be calling ServletResponse.getWriter, potentially after calling ServletResponse.setCharacterEncoding to ensure that it's using UTF-8. Then you can just call:

writer.write(data);

Writers are designed to write text data; output streams are designed to write binary data. You can create a writer on top of a stream using OutputStreamWriter, but as the servlet API will do that for you, you might as well let it...

Sign up to request clarification or add additional context in comments.

1 Comment

resp.setCharacterEncoding("UTF-8"); resp.getWriter().write(data); worked great! Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.