【问题标题】:How to remove CRLF between text qualifiers in C#如何在 C# 中删除文本限定符之间的 CRLF
【发布时间】:2021-01-05 14:32:52
【问题描述】:

我有一个 csv 文件,它有一个标题行和 2 个数据行,但有时我们会从源中将数据行拆分为多行,在下面的情况下使其成为 3 行。

因此,我的 SSIS 包在通过 C# 代码处理此 csv 文件时失败,因为它将“ETF”行视为新行。我目前正在使用以下代码将所有数据添加到数组列表中。

            string sLine;
            ArrayList arrText = new ArrayList();
            StreamReader objReader = new StreamReader(filepath);

            do
            {
                sLine = objReader.ReadLine();
                if (sLine != null)
                    arrText.Add(sLine);
            }
            while (sLine != null);

我是 C# 新手,所以任何人都可以建议我们如何处理这种情况,以便我的代码可以处理这个文件 2 只有 2 行而不是 3 行并将其加载到数据库中。

【问题讨论】:

  • 您尝试过简单的文本替换吗?
  • 您似乎想替换双引号字符 " 内的任何 CRLF。这很容易(正则表达式可能是要走的路),但是如果 " 出现在字段中会发生什么,以及如何逃脱?这可能会打乱你的逻辑。
  • SSIS 如果您使用内置导入,则可以选择跳过的行数。或者将您的文件标记为文本限定(不确定 C# 如何做到这一点),但文本限定文件应该忽略限定符之间的任何内容,至少在 SSIS 数据流任务中,但如果它忽略换行符则不是 100%。
  • @canton7 我会说一个正确格式的正则表达式来解析 CSV 是相当复杂的,特别是如果您考虑多行文本(文本分成至少 3 行)和转义双引号 ("")。我会用正确完成的 csv 库解析文本,用空格替换换行符,然后重写 csv
  • @canton7 - 是的,我需要替换双引号字符内的任何 CRLF.. 但即使我使用替换来执行此操作,下一个任务也是让“ETF”在第三行成为第二行的一部分,以便 C# 知道只有 2 行并将其导入 DB 并且不会失败

标签: c# ssis


【解决方案1】:

使用 Microsoft.VisualBasic.FileIO.TextFieldParser 读取 csv 文件或参考 thisthis

【讨论】:

    【解决方案2】:

    现在...我觉得这不是一个好主意。一个好主意是使用 .net 的 CSV 库之一,加载文件,用空格替换换行符,将文件重写为 csv。

    这不是一个好主意。这是一个正则表达式的想法。

    string csv = File.ReadAllText("sample.csv");
    
    string separator = "#";
    string escapedDoubleQuotes = "\"\"";
    var rx = new Regex($@"(?<=^ *|{Regex.Escape(separator)} *)""({Regex.Escape(escapedDoubleQuotes)}|[^""])*""", RegexOptions.Multiline);
    var replacer = new Regex(" *[\r\n]+ *");
    
    string csv2 = rx.Replace(csv, x => replacer.Replace(x.Value, " "));
    
    File.WriteAllText("output.csv", csv2);
    

    它将用一个空格替换\r 和/或\n(加上周围的可选空格)的序列。正则表达式将尝试在 csv 中查找双引号字符串,“提取”它们,然后用一个空格进行一些替换(使用第二个正则表达式,称为 replacer)。甚至支持转义双引号。默认情况下,在值中插入双引号 ",您必须将 "" 加倍。

    【讨论】:

    • 感谢您的代码。我在 C# 2015 中尝试了您的代码,并在其上放置了一个调试器来检查值,但 SSIS 不允许我调试值,而只是完成脚本任务。这可能是一个字符串插值问题,即在上面的正则表达式中使用 $,如果是,你能更新你的脚本吗
    【解决方案3】:

    假设每一行都以日期开头并且没有其他字段是日期,您可以简单地将所有文本作为一个字符串读取并删除每个 \r\n 后面没有紧跟日期的:

    string csv = File.ReadAllText(filename);
    csv = Regex.Replace(csv, "\r\n(?!(\"[0-9]+/))", "$1");
    arrtext.AddRange(csv.Split("\r\n"));
    

    这不是给定日期格式的完整模式,但适用于示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      • 1970-01-01
      • 1970-01-01
      • 2023-01-18
      • 1970-01-01
      • 1970-01-01
      • 2022-11-25
      相关资源
      最近更新 更多