使用逗号和引号

时间:2016-09-26 08:55:21

标签: c# csv parsing

以前曾问过,但没有解决办法对我有效。

我有一个类似的csv文件:

data1,data2,data3,"<tag field1=""test"" field2=""test,2,3""></tag>",data4

当我用逗号分割时,由于标记中的数据,它不适合,所以我想在每次看到“”时使用正则表达式或其他东西。

我正在使用winforms,我想从csv中只提取data1,data2等。

请问任何想法?

谢谢

编辑:我会更精确:它不应该是一项艰巨的任务,因为我知道我想忽略“标签”中的任何内容,所以正则表达式可以做到这一点吗? 在上面的例子中,我想使用正则表达式并操纵该行给出以下结果:

data1,data2,data3,data4
现在很清楚了吗?谢谢大家

3 个答案:

答案 0 :(得分:1)

有几种开源CSV解析器可用作NuGet包,它们将为您处理所有这些。你最好的选择就是使用其中之一,因为没有必要在流行的平台上编写常见文件格式的解析器,因为可能已经有至少一个可以做你想要的了。

如果你真的想自己解析这个问题,除非你真的对解析感兴趣或者你需要一些非常奇特的要求,否则我不会推荐你解决这个问题,你需要一些比简单更有能力的东西。正则表达式。正则表达式不擅长处理引用的字段,您还必须记住,引用的字段可以根据RFC在其中添加换行符。

答案 1 :(得分:0)

如果您在评论时不想使用库,则可以对单行数据(伪代码)执行类似的操作:

read a line

bool bInsideQuotes = false

loop over chars
  if character == '"'
    bInsideQuotes = !bInsideQuotes
  if character == ',' and !bInsideQuotes
    found a field separator

或者不是逐行阅读,而是可以阅读整个文件并自行处理换行符(仅当!bInsideQuotes允许多行行时)。

答案 2 :(得分:0)

出于好奇,我花了大部分时间尝试编写自己的CSV解析器,该解析器可以处理在CSV字段值中输入的逗号和引号的任何变体。这就是我想出的(需要输入字符串$ myfilename和boolean $ use_headers作为输入)

<?php
$rows = file($myfilename)
for($i = 0; $i < count($rows); $i++)
{
    # Remove non-printable characters
    $rows[$i] = preg_replace('/[[:^print:]]/', '', $rows[$i]);

    # Reduce csv line to only commas and quotes
    $cleanup_1 = preg_replace('/[^,"]/', '', $rows[$i]);

    # Count the number of quote characters between commas.
    # When the cumulative number of quotes is an even number,
    # you have a distinct field from your CSV line data.
    # Record the key valus for delimiter commas.
    $delimiters = array();
    $count = 0;
    foreach(explode(',', $cleanup_1) as $key => $value)
    {
        $count += strlen($value);
        if($count % 2 == 0)
        {
            $delimiters[] = $key;
            $count = 0;
        }
    }

    # Split your original line data by commas and combine
    # text values between delimiters.
    $strings = array();
    $new_array = array();
    foreach(explode(',', $rows[$i]) as $key => $value)
    {
        $strings[] = $value;
        if(in_array($key, $delimiters))
        {
            $text = implode(',', $strings);
            # If the field value contains escaped commas or quotes, 
            # remove the beginning and end quotation marks. 
            if(substr($text, 0, 1) == '"' && substr($text, strlen($text)-1, 1) == '"')
            {
                $text = substr($text, 1, strlen($text)-2);
                $text = str_replace('""', '"', $text);
            }
            $new_array[] = $text;
            $strings = array();
        }
    }

    # Optional setting to include headers. $user_headers
    # will be a boolean input. Result is a set of 
    # associative arrays with matching, aligned keys.
    if($i == 0 && $use_headers)
    {
        $headers = array();
        foreach($new_array as $key => $header)
            {$headers[$key] = $header;}
    } else {
        $tmp = array();
        foreach($new_array as $key => $value)
        {
            if($use_headers)
                {$tmp[$headers[$key]] = $value;} 
            else
                {$tmp[] = $value;}
        }
        $data_array[] = $tmp;
    }
}
?>