Use client passed Writer without wrapping it
qtxo opened this issue · 4 comments
Is your feature request related to a problem? Please describe.
Basically CsvWriter fails the Single Responsibility Principle by tackling both high level csv formatting and low level IO buffering, creating problems for non trivial uses.
Some use cases rely on a Writer obtained previously which is used to write more data than just a single CSV file. For example the same stream can contain multiple CSVs or some other data at the end.
The user can not do a writer.flush() because the writer is internally wrapped with CachingWriter so the last bytes may never get written until a csvWriter.close() is issued which closes the writer as well.
Once a Writer is passed its state is unknown until a call to CavWriter.close() is made!
Describe the solution you'd like
Let construct a CsvWriter without messing in any way with the writer passed. Let CsvWriter deal with building the csv data structure, and let the passed Writer deal with the low level stuff.
Describe alternatives you've considered
No alternative possible except a source code modification.
RFC 4180 compliance
Would this feature comply to RFC 4180?
Yes, but the important part is that the code will be more correct, because it won't mess with external code passed to it.
Your assumption about the usage of an user provided Writer by CsvWriter is incorrect.
If the user creates a CsvWriter using the CsvWriter.CsvWriterBuilder#build(Writer)
method, the writeRow
method of CsvWriter flushes its internal buffer to the provided writer on every call. This is documented in the JavaDoc of the build
method.
Because of that, this works totally fine (exception handling omitted):
PrintWriter printWriter = new PrintWriter(System.out);
CsvWriter csvWriter = CsvWriter.builder().build(printWriter);
csvWriter.writeRow("foo", "bar");
printWriter.println("# my comment");
csvWriter.writeRow("1", "2");
printWriter.close();
And prints:
foo,bar
# my comment
1,2
CsvWriter flushes its internal buffer to the provided writer on every call
Correct, but how to opt out of that? The only way is to pass a wrapped Writer that ignores flush() to leave the responsibility to the "real" writer ( OutputStreamWriter(GZIPOutputStream(CipherOutputStream))
in my use case)
My point is that this library should allow a "transparent" writer functionality where the Writer is used to only to write data, and leave the buffering and flushing to the application code that owns the Writer.
The only way is to pass a wrapped Writer that ignores flush() to leave the responsibility to the "real" writer
Nope. CsvWriter does not call flush in the provided Writer. As I said, CsvWriter flushes its internal buffer. In other words, if enough internal capacity exists, CsvWriter writes to the provided Writer only once (at the end of writeRow).
Yes, you are right, I overlooked that method...