Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use client passed Writer without wrapping it #50

Closed
qtxo opened this issue Jan 12, 2021 · 4 comments
Closed

Use client passed Writer without wrapping it #50

qtxo opened this issue Jan 12, 2021 · 4 comments

Comments

@qtxo
Copy link

qtxo commented Jan 12, 2021

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.

@osiegmar
Copy link
Owner

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

@qtxo
Copy link
Author

qtxo commented Jan 12, 2021

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.

@osiegmar
Copy link
Owner

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).

See: https://github.com/osiegmar/FastCSV/blob/master/src/main/java/de/siegmar/fastcsv/writer/CsvWriter.java#L354

@qtxo
Copy link
Author

qtxo commented Jan 12, 2021

Yes, you are right, I overlooked that method...

@qtxo qtxo closed this as completed Jan 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants