🦁
CSVHelperで空白をダブルクォーテーションで囲まないようにする
CSVHepler(C#)でCSVを書き込む場合に値の文頭・文末が空白の場合にダブルクォーテーションで囲む既定動作になっています。これを変更する方法を記載します。
C# のライブラリである CSVHelper に関して値の文頭・文末が空白の場合にダブルクォーテーションで囲まれるという現象を発見しました。
調べたところ、公式のIssue からCSVHelperの仕様であることが分かりました。
「,」、「"」、改行以外に文頭、文末がスペースで始まる場合はダブルクォーテーションで囲むようになっていました。
Yes. The default criteria for a field being quoted is:
- Contains a quote
- Starts with a space
- Ends with a space
- Contains any chars that require quotes (\r and \n by default)
- Contains the delimiter
扱うプログラムの仕様上文頭・文末が空白の場合はダブルクォーテーションで囲まないようにする必要がありました。
そのため、上記のIssueの回答を元に csv.Configuration.ShouldQuote
を使ってダブルクォーテーションで囲むルールを変更することにしました。
.net6向けのサンプルコード
using CsvHelper;
using CsvHelper.Configuration;
using System.Globalization;
public class Foo
{
public int Id { get; set; }
public string? Name { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
var records = new List<Foo>
{
new Foo { Id = 1, Name = "one" },
new Foo { Id = 2, Name = " two" },
new Foo { Id = 3, Name = "three " },
};
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
ShouldQuote = MyShouldQuote
};
using (var writer = new StreamWriter("foo.csv"))
using (var csv = new CsvWriter(writer, config))
{
csv.WriteRecords(records);
}
}
private static readonly char[] lineEndingChars = new char[] { '\r', '\n' };
// ConfigurationFunctions.ShouldQuote 参照
private static bool MyShouldQuote(ShouldQuoteArgs args)
{
var config = args.Row.Configuration;
var shouldQuote = !string.IsNullOrEmpty(args.Field) &&
(
args.Field.Contains(config.Quote) // Contains quote
// || args.Field[0] == ' ' // Starts with a space
// || args.Field[args.Field.Length - 1] == ' ' // Ends with a space
|| (config.Delimiter.Length > 0 && args.Field.Contains(config.Delimiter)) // Contains delimiter
|| !config.IsNewLineSet && args.Field.IndexOfAny(lineEndingChars) > -1 // Contains line ending characters
|| config.IsNewLineSet && args.Field.Contains(config.NewLine) // Contains newline
);
return shouldQuote;
}
}
出力結果(設定前) Foo.csv
Id,Name
1,one
2," two"
3,"three "
出力結果(設定後) Foo.csv
Id,Name
1,one
2, two
3,three
Discussion