正気を保つために、ここに書かれているさまざまなメモをすべてまとめました。このコードは少しきれいで、いくつかの検証が含まれています。
これを試して:
string dir = @"\\198.0.0.4\e$\Globus\LIVE\bnk.run\URA.BP\WEBOUT\";
foreach (string fileName2 in Directory.GetFiles(dir)) {
StreamReader st = new StreamReader(fileName2);
while (!sr.EndOfStream) {
string line = sr.ReadLine();
if (!String.IsNullOrEmpty(line)) {
string[] columns = line.Split(',');
if (columns.Length == 8) {
string prnout = columns[0];
string tinout = columns[1];
string amtout = columns[2];
string valdate = columns[3];
string paydate = columns[4];
string status = columns[5];
string branch = columns[6];
string reference = columns[7];
}
}
}
}
編集: 他のユーザーがコメントしたように、CSV 形式はテキスト修飾子も受け入れます。これは通常、二重引用符記号 (") を意味します。たとえば、テキスト修飾行は次のようになります。
user,"Hello!",123.23,"$123,123.12",and so on,
このように完全にフォーマットされたファイルがある場合、CSV 解析コードの記述は少し複雑になります。何年にもわたって、不適切な形式の CSV ファイルを解析してきました。事実上すべての単体テストに合格する標準コード スクリプトを作成しましたが、説明するのは面倒です。
/// <summary>
/// Read in a line of text, and use the Add() function to add these items to the current CSV structure
/// </summary>
/// <param name="s"></param>
public static bool TryParseLine(string s, char delimiter, char text_qualifier, out string[] array)
{
bool success = true;
List<string> list = new List<string>();
StringBuilder work = new StringBuilder();
for (int i = 0; i < s.Length; i++) {
char c = s[i];
// If we are starting a new field, is this field text qualified?
if ((c == text_qualifier) && (work.Length == 0)) {
int p2;
while (true) {
p2 = s.IndexOf(text_qualifier, i + 1);
// for some reason, this text qualifier is broken
if (p2 < 0) {
work.Append(s.Substring(i + 1));
i = s.Length;
success = false;
break;
}
// Append this qualified string
work.Append(s.Substring(i + 1, p2 - i - 1));
i = p2;
// If this is a double quote, keep going!
if (((p2 + 1) < s.Length) && (s[p2 + 1] == text_qualifier)) {
work.Append(text_qualifier);
i++;
// otherwise, this is a single qualifier, we're done
} else {
break;
}
}
// Does this start a new field?
} else if (c == delimiter) {
list.Add(work.ToString());
work.Length = 0;
// Test for special case: when the user has written a casual comma, space, and text qualifier, skip the space
// Checks if the second parameter of the if statement will pass through successfully
// e.g. "bob", "mary", "bill"
if (i + 2 <= s.Length - 1) {
if (s[i + 1].Equals(' ') && s[i + 2].Equals(text_qualifier)) {
i++;
}
}
} else {
work.Append(c);
}
}
list.Add(work.ToString());
// If we have nothing in the list, and it's possible that this might be a tab delimited list, try that before giving up
if (list.Count == 1 && delimiter != DEFAULT_TAB_DELIMITER) {
string[] tab_delimited_array = ParseLine(s, DEFAULT_TAB_DELIMITER, DEFAULT_QUALIFIER);
if (tab_delimited_array.Length > list.Count) {
array = tab_delimited_array;
return success;
}
}
// Return the array we parsed
array = list.ToArray();
return success;
}
このアルゴリズムがどれほど複雑であっても、テキスト修飾値内に改行が埋め込まれている CSV ファイルを解析できないことに注意してください。たとえば、次のようになります。
123,"Hi, I am a CSV File!
I am saying hello to you!
But I also have embedded newlines in my text.",2012-07-23
これらを解決するために、Try() 機能を使用してテキスト行を追加し、メイン関数が正しく機能することを確認する複数行パーサーを用意しました。
/// <summary>
/// Parse a line whose values may include newline symbols or CR/LF
/// </summary>
/// <param name="sr"></param>
/// <returns></returns>
public static string[] ParseMultiLine(StreamReader sr, char delimiter, char text_qualifier)
{
StringBuilder sb = new StringBuilder();
string[] array = null;
while (!sr.EndOfStream) {
// Read in a line
sb.Append(sr.ReadLine());
// Does it parse?
string s = sb.ToString();
if (TryParseLine(s, delimiter, text_qualifier, out array)) {
return array;
}
}
// Fails to parse - return the best array we were able to get
return array;
}