問題: 匯出檔案.CSV時希望匯出逗號
已經搜尋過網路,說在要保留逗號,的字串前後加雙引號"string"
可是怎麼加雙引號都沒用不知道是哪裡錯了QQ
看不出來哪裡有問題還請各位幫忙><謝謝
還請各位幫忙看一下是哪裡的問題
原始資料是有幾行的資料內容有逗號
 while (!streamReader.EndOfStream)
    {
        string oneLine = streamReader.ReadLine();  // 一行
        string streamWriter = "";
        string address = "";
        string[] oneLineArr = Regex.Split(oneLine, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"); // 分割字串用逗號,但雙引號內的逗號不動
        streamWriter = $"姓名:{oneLineArr[3]}電話: {oneLineArr[5]}地址:";
        if (oneLine.Contains("\"")) // 如果有雙引號
        {
           Regex reg = new Regex("\"[^\"]*\"");                  // 取前後雙引號裡的字串
          address = reg.Match(oneLine).Value.Replace("\"", ""); // 將原本資料中前後帶雙引號的取代掉
            
            streamWriter += "\"" + address + "\"\r\n";         // 這個不行
            streamWriter += String.Format("{0}{1}\"{2}\"", oneLineArr[7], oneLineArr[8], address); // 這個也不行
            streamWriter += String.Format("{0}{1}{2}", oneLineArr[7], oneLineArr[8], address); // 這個也不行
            streamWriter += String.Format("{0}", "\"" + address + "\""); // 這個也不行
        }
        else
        {
            streamWriter += oneLineArr[7] + oneLineArr[8] + oneLineArr[9];
        }
        newFileStreamWrite.WriteLine(streamWriter);
圖中有雙引號的都被欄位分割了!!可是就不要分割啊!!要保留逗號啊!!
這是notepad++開的檔案
網路上多半解法都是加 雙引號 "string" 可是還是抓不到
https://stackoverflow.com/questions/5740359/how-to-use-comma-in-csv-columns
已經用好久了還是不行.....
謝謝大神們
從你po出來的圖片看。你只是用""包起來。
但你並沒使用正確的格式。
如你
台北市"aaa.708 ,JJJ..."
但正確的格式是
台北市,"aaa.708 ,JJJ..."
或
"台北市aaa.708 ,JJJ..."
(因為我不懂你那個台北市是要當一欄還是放在一起。)
雙引號要包的是一整欄的資料。
如果你用第一種方式包的話。
你會害excel不懂這是什麼東東。就只能依照你的,分開了。
其實如果你的欄位中沒有數值型態的話,大可以將所有的欄位都用雙引號包起來。
也不需要再用正則處理了。
這樣改看看
string Pattern = "\"[^\"]*,[^\"]*\"";
Regex commaSpl = new Regex(Pattern, RegexOptions.Compiled);
List<string> outputCSV = new List<string>();
string FileToRead = @"s:\pi\test.csv";
using (StreamReader ReaderObject = new StreamReader(FileToRead))
{
string Line;
string oline = "";
string[] splitLine;
while ((Line = ReaderObject.ReadLine()) != null)
{
    oline = "";
    if (commaSpl.IsMatch(Line))
    {
        splitLine = Line.Split(new string[] { "\n" }, StringSplitOptions.None);
    }
    else
    {
        splitLine = Line.Split(new string[] { "," }, StringSplitOptions.None);
    }
    foreach (var s in splitLine)
        oline += $"\"{s.Replace("\"", "")}\",";
    outputCSV.Add(oline);
}
File.WriteAllText(@"s:\pi\new.csv", string.Join("\n", outputCSV));
}
糟,剛剛發現我沒有考慮到 "xxxxx,yyyy","zzzz" 的狀況
直接教他判斷是否數值。數值就不要包""
如果有包到"字串的話。我記得要用兩個"才行。用"好像不行。
.net我不會處理。所以沒辦法寫給他看。
只能告訴他理念。
只是不明白為何要每個欄位都要包""
現在用的截取程式段 內含參考來源
private static string[] SplitComma(string subjectString)
{
List result = new List();
// ref url: https://stackoverflow.com/questions/3268622/regex-to-split-line-csv-file
Regex rgx = new Regex(@"
# Parse CVS line. Capture next value in named group: 'val'
\s*                      # Ignore leading whitespace.
(?:                      # Group of value alternatives.
""                     # Either a double quoted string,
(?                # Capture contents between quotes.
[^""](""""[^""])*  # Zero or more non-quotes, allowing
)                      # doubled "" quotes within string.
""\s*                  # Ignore whitespace following quote.
|  (?[^,]*)         # Or... zero or more non-commas.
)                        # End value alternatives group.
(?:,|$)                  # Match end is comma or EOS",
RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
MatchCollection matches = rgx.Matches(subjectString);
foreach (Match mtch in matches)
{
if (mtch.Success && mtch.Index < subjectString.Length)
{
string value = mtch.Value.TrimEnd(',');
if (value.Length >= 2 && value.First() == '"' && value.Last() == '"')
value = value.Trim('"').Replace("""", """);
result.Add(value);
}
}
return result.ToArray();
}
因為""其實對csv來說,就是宣告字串格式的欄位。
認真來說,跟用陣列的用法很像。
用雙引號包起來的會視為一個欄位內容。
直接用雙引號包全部的欄位,就可以省下判斷字元處理。
(雖然內容中的雙引號還是需要處理就是了)
算是很懶的招。
像 chang137 po的,就是針對csv全部格式轉換的方式。
我只是教最簡單的處理。
但 chang137 是更完美的處理方式。
我幫忙將程式碼整理一下
private static string[] SplitComma(string subjectString)
{
    List result = new List();
    // ref url: https://stackoverflow.com/questions/3268622/regex-to-split-line-csv-file
    Regex rgx = new Regex(@"
        # Parse CVS line. Capture next value in named group: 'val'
        \s* # Ignore leading whitespace.
        (?: # Group of value alternatives.
        "" # Either a double quoted string,
        (? # Capture contents between quotes.
        [^""](""""[^""])* # Zero or more non-quotes, allowing
        ) # doubled "" quotes within string.
        ""\s* # Ignore whitespace following quote.
        | (?[^,]*) # Or... zero or more non-commas.
    ) # End value alternatives group.
    (?:,|$) # Match end is comma or EOS",
    RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
    MatchCollection matches = rgx.Matches(subjectString);
    foreach (Match mtch in matches)
    {
        if (mtch.Success && mtch.Index < subjectString.Length)
        {
            string value = mtch.Value.TrimEnd(',');
            if (value.Length >= 2 && value.First() == '"' && value.Last() == '"')
            value = value.Trim('"').Replace("""", """);
            result.Add(value);
        }
    }
    return result.ToArray();
}
是不是要將從 CSV 取得的欄位合併成一個呢?
如果是的話,雙引號要串在整個字串的開頭和結尾,例如:
小明,09xxxxxxxx,"abc,123"
轉成
"小明 09xxxxxxxx abc,123"
var result = "";
using (var streamReader = new StreamReader("test.csv"))
{
    //切割欄位的正規式
    var regex = new Regex("(?<=^|,)(\"(?:[^\"]|\"\")*\"|[^,]*)", 
        RegexOptions.Multiline);
    //去除前後的雙引號
    IEnumerable<string> clear(MatchCollection matches)
    {
        foreach(Match match in matches)
        {
            //去除頭尾空白
            var value = match.Value.Trim();
            //如果開頭是雙引號,就去除頭尾的雙引號
            yield return value.StartsWith("\"") ?
                match.Value.Substring(1, match.Value.Length - 2) : value;
        }
    };
    while (!streamReader.EndOfStream)
    {
        var line = streamReader.ReadLine();
        //切割欄位
        var matches = regex.Matches(line);
        //清理資料
        var datas = clear(matches).ToList();
        //合併各欄位
        result += $"\"姓名: {datas[0]} 電話: {datas[1]} 地址: {datas[2]}\"\n";
    }
    File.WriteAllText(@"new.csv", result, Encoding.UTF8);
}
正規式部分參考 chang137 提供的連結:
https://stackoverflow.com/questions/3268622/regex-to-split-line-csv-file
小明,09xxxxxxxx,"abc,""123"
老王,09xxxxx123,台中市
"姓名: 小明 電話: 09xxxxxxxx 地址: abc,""123"
"姓名: 老王 電話: 09xxxxx123 地址: 台中市"

不過使用套件比較好啦,寫法也比較直覺。
Nuget 安裝 CsvHelper
public class Input
{
    public string Name { get; set; }
    public string Phone { get; set; }
    public string Address { get; set; }
}
public class Output
{
    public string Data { get; set; }
}
static void Main(string[] args)
{
    var input = null as List<Input>;
    //讀取資料
    using (var reader = new StreamReader("test.csv", Encoding.UTF8))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        csv.Configuration.HasHeaderRecord = false;
        input = csv.GetRecords<Input>().ToList();
    }
    //寫入資料
    using (var writer = new StreamWriter("new2.csv", false, Encoding.UTF8))
    using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
    {
        csv.Configuration.HasHeaderRecord = false;
        var output = input.Select(it => new Output
        {
            Data = $"姓名: {it.Name} 電話: {it.Phone} 地址: {it.Address}"
        });
        csv.WriteRecords(output);
    }
}
"姓名: 小明 電話: 09xxxxxxxx 地址: abc,""123"
姓名: 老王 電話: 09xxxxx123 地址: 台中市
