Skip to content

Commit 9db2277

Browse files
committed
fix(writer): Fix double-delimiter bug in QuoteMode.All
Critical bug fix: When QuoteMode.All was set, numeric field writers were calling WriteDelimiterIfNeeded() then delegating to WriteField(string) which called WriteDelimiterIfNeeded() AGAIN, resulting in double commas. Example broken output: "Alice",,"30","NYC" (extra comma after Alice) Expected output: "Alice","30","NYC" Fix: Call WriteQuotedField() directly instead of WriteField(string) to avoid the second delimiter write. Affected methods: - WriteField(int) - WriteField(long) - WriteField(double) - WriteField(decimal) - WriteField(DateTime) - WriteField(DateTimeOffset) - WriteField(bool) This fixes all QuoteMode.All test failures.
1 parent 5e40d86 commit 9db2277

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

src/CsvHandler/Core/Utf8CsvWriter.cs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,10 @@ public void WriteField(int value)
162162
// Check if we need to quote this field
163163
if (_options.QuoteMode == CsvQuoteMode.All)
164164
{
165-
// For QuoteMode.All, always quote - convert to string first
166-
WriteField(value.ToString(CultureInfo.InvariantCulture));
165+
// For QuoteMode.All, always quote - write directly to avoid double-delimiter
166+
var str = value.ToString(CultureInfo.InvariantCulture);
167+
var bytes = Encoding.UTF8.GetBytes(str);
168+
WriteQuotedField(bytes);
167169
_isFirstFieldInRecord = false;
168170
return;
169171
}
@@ -192,7 +194,9 @@ public void WriteField(long value)
192194

193195
if (_options.QuoteMode == CsvQuoteMode.All)
194196
{
195-
WriteField(value.ToString(CultureInfo.InvariantCulture));
197+
var str = value.ToString(CultureInfo.InvariantCulture);
198+
var bytes = Encoding.UTF8.GetBytes(str);
199+
WriteQuotedField(bytes);
196200
_isFirstFieldInRecord = false;
197201
return;
198202
}
@@ -221,7 +225,9 @@ public void WriteField(double value)
221225

222226
if (_options.QuoteMode == CsvQuoteMode.All)
223227
{
224-
WriteField(value.ToString("G", CultureInfo.InvariantCulture));
228+
var str = value.ToString("G", CultureInfo.InvariantCulture);
229+
var bytes = Encoding.UTF8.GetBytes(str);
230+
WriteQuotedField(bytes);
225231
_isFirstFieldInRecord = false;
226232
return;
227233
}
@@ -250,7 +256,9 @@ public void WriteField(decimal value)
250256

251257
if (_options.QuoteMode == CsvQuoteMode.All)
252258
{
253-
WriteField(value.ToString(CultureInfo.InvariantCulture));
259+
var str = value.ToString(CultureInfo.InvariantCulture);
260+
var bytes = Encoding.UTF8.GetBytes(str);
261+
WriteQuotedField(bytes);
254262
_isFirstFieldInRecord = false;
255263
return;
256264
}
@@ -279,7 +287,9 @@ public void WriteField(DateTime value)
279287

280288
if (_options.QuoteMode == CsvQuoteMode.All)
281289
{
282-
WriteField(value.ToString("O", CultureInfo.InvariantCulture));
290+
var str = value.ToString("O", CultureInfo.InvariantCulture);
291+
var bytes = Encoding.UTF8.GetBytes(str);
292+
WriteQuotedField(bytes);
283293
_isFirstFieldInRecord = false;
284294
return;
285295
}
@@ -308,7 +318,9 @@ public void WriteField(DateTimeOffset value)
308318

309319
if (_options.QuoteMode == CsvQuoteMode.All)
310320
{
311-
WriteField(value.ToString("O", CultureInfo.InvariantCulture));
321+
var str = value.ToString("O", CultureInfo.InvariantCulture);
322+
var bytes = Encoding.UTF8.GetBytes(str);
323+
WriteQuotedField(bytes);
312324
_isFirstFieldInRecord = false;
313325
return;
314326
}
@@ -337,7 +349,9 @@ public void WriteField(bool value)
337349

338350
if (_options.QuoteMode == CsvQuoteMode.All)
339351
{
340-
WriteField(value ? "true" : "false");
352+
var str = value ? "true" : "false";
353+
var bytes = Encoding.UTF8.GetBytes(str);
354+
WriteQuotedField(bytes);
341355
_isFirstFieldInRecord = false;
342356
return;
343357
}

0 commit comments

Comments
 (0)