[解決済み] CSVファイル内のカンマの扱いについて
2022-03-20 18:23:37
質問
顧客によって作成され、アップロードされるcsvファイルで、会社名のような値にカンマがある場合の処理方法について、提案を探しています。
引用符で囲まれた識別子(値 "、"、値 "、"など)、カンマの代わりに|を使用するなどのアイデアを検討しています。 最大の問題は、それを簡単にしなければならないことで、そうしなければお客様はそれをしないでしょう。
どのように解決するの?
他の方もおっしゃっているように、引用符を含む値をエスケープする必要があります。 ここに、埋め込み引用符やキャリッジリターンを含む引用符付きの値をサポートするC♯の小さなCSVリーダがあります。
ちなみに、これはユニットテスト済みのコードです。 この質問はよく出てくるし、単純なCSVのサポートで十分なのに、ライブラリ全体を必要としない人もいるかもしれないので、今投稿しているのです。
以下のように使用することができます。
using System;
public class test
{
public static void Main()
{
using ( CsvReader reader = new CsvReader( "data.csv" ) )
{
foreach( string[] values in reader.RowEnumerator )
{
Console.WriteLine( "Row {0} has {1} values.", reader.RowIndex, values.Length );
}
}
Console.ReadLine();
}
}
以下はそのクラスです。 なお、このクラスでは
Csv.Escape
関数を使って、有効なCSVも書くことができます。
using System.IO;
using System.Text.RegularExpressions;
public sealed class CsvReader : System.IDisposable
{
public CsvReader( string fileName ) : this( new FileStream( fileName, FileMode.Open, FileAccess.Read ) )
{
}
public CsvReader( Stream stream )
{
__reader = new StreamReader( stream );
}
public System.Collections.IEnumerable RowEnumerator
{
get {
if ( null == __reader )
throw new System.ApplicationException( "I can't start reading without CSV input." );
__rowno = 0;
string sLine;
string sNextLine;
while ( null != ( sLine = __reader.ReadLine() ) )
{
while ( rexRunOnLine.IsMatch( sLine ) && null != ( sNextLine = __reader.ReadLine() ) )
sLine += "\n" + sNextLine;
__rowno++;
string[] values = rexCsvSplitter.Split( sLine );
for ( int i = 0; i < values.Length; i++ )
values[i] = Csv.Unescape( values[i] );
yield return values;
}
__reader.Close();
}
}
public long RowIndex { get { return __rowno; } }
public void Dispose()
{
if ( null != __reader ) __reader.Dispose();
}
//============================================
private long __rowno = 0;
private TextReader __reader;
private static Regex rexCsvSplitter = new Regex( @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))" );
private static Regex rexRunOnLine = new Regex( @"^[^""]*(?:""[^""]*""[^""]*)*""[^""]*$" );
}
public static class Csv
{
public static string Escape( string s )
{
if ( s.Contains( QUOTE ) )
s = s.Replace( QUOTE, ESCAPED_QUOTE );
if ( s.IndexOfAny( CHARACTERS_THAT_MUST_BE_QUOTED ) > -1 )
s = QUOTE + s + QUOTE;
return s;
}
public static string Unescape( string s )
{
if ( s.StartsWith( QUOTE ) && s.EndsWith( QUOTE ) )
{
s = s.Substring( 1, s.Length - 2 );
if ( s.Contains( ESCAPED_QUOTE ) )
s = s.Replace( ESCAPED_QUOTE, QUOTE );
}
return s;
}
private const string QUOTE = "\"";
private const string ESCAPED_QUOTE = "\"\"";
private static char[] CHARACTERS_THAT_MUST_BE_QUOTED = { ',', '"', '\n' };
}
関連
-
[解決済み] MySQLのクエリ結果をCSV形式で出力するにはどうすればよいですか?
-
[解決済み] PostgreSQLからのPL/pgSQL出力をCSVファイルに保存する
-
[解決済み] pandasのDataFrameをCSVファイルに書き出す
-
[解決済み] NumPy の配列を csv ファイルにダンプする
-
[解決済み] HTML Input="file" Accept Attribute File Type (CSV)
-
[解決済み] PandasとPythonでCSVファイルを読み込むとUnicodeDecodeErrorが発生する。
-
[解決済み] CSVに使用するMIMEタイプは?
-
[解決済み] CSVファイル内のカンマの扱いについて
-
[解決済み】Pythonで作成したCSVファイルの行間に空白行がある。
-
[解決済み】CSVファイルをSQL Serverへインポートする。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン