Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将复杂字符串转义为CSV格式_C#_Flat File_Csv - Fatal编程技术网

C# 将复杂字符串转义为CSV格式

C# 将复杂字符串转义为CSV格式,c#,flat-file,csv,C#,Flat File,Csv,我必须从webservice输出创建一个CSV文件,CSV文件使用带逗号分隔符的带引号的字符串我无法更改格式 所以如果我有一个字符串,它就变成了“字符串”。。。 如果该值已经有引号,则会用双引号替换。 例如,str“ing变为“str”ing 但是,最近我的导入失败,原因如下 原始输入字符串是:”,“word1,word2,…” 每一个单引号都被双引号替换,结果是:“,”word1,word2,…“ 然后在写入CVS文件之前,将其前缀和后缀加上引号:“”“”,“word1,word2,…”

我必须从webservice输出创建一个CSV文件,CSV文件使用带逗号分隔符的带引号的字符串我无法更改格式

所以如果我有一个
字符串
,它就变成了
“字符串”
。。。 如果该值已经有引号,则会用双引号替换。 例如,
str“ing
变为
“str”ing

但是,最近我的导入失败,原因如下

  • 原始输入字符串是:
    ”,“word1,word2,…”
  • 每一个单引号都被双引号替换,结果是:
    “,”word1,word2,…“
  • 然后在写入CVS文件之前,将其前缀和后缀加上引号:
    “”“”,“word1,word2,…”
如您所见,最终结果如下:

""""",""word1,word2,..."""
这破坏了我的导入(将其视为另一个字段)。。。 我认为问题在于原始输入字符串中出现了“
”、“

此场景是否有CVS转义序列

更新
上述中断的原因是由于BCP映射文件(BCP实用程序用于将CSV文件加载到SQL db中)的终止符定义为“
”,“
”。因此,它看到的不是1个字段,而是2个字段…但我无法更改映射文件…

解析此文件的第一步是删除字符串周围额外添加的“'s”。一旦你这样做了,你应该能够处理嵌入的“以及,”。

我使用这段代码,它一直有效:

/// <summary>
/// Turn a string into a CSV cell output
/// </summary>
/// <param name="str">String to output</param>
/// <returns>The CSV cell formatted string</returns>
public static string StringToCSVCell(string str)
{
    bool mustQuote = (str.Contains(",") || str.Contains("\"") || str.Contains("\r") || str.Contains("\n"));
    if (mustQuote)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("\"");
        foreach (char nextChar in str)
        {
            sb.Append(nextChar);
            if (nextChar == '"')
                sb.Append("\"");
        }
        sb.Append("\"");
        return sb.ToString();
    }

    return str;
}
//
///将字符串转换为CSV单元格输出
/// 
///要输出的字符串
///CSV单元格格式的字符串
公共静态字符串StringToCSVCell(字符串str)
{
bool mustQuote=(str.Contains(“,”)| | str.Contains(“\”)| | str.Contains(“\r”)| | str.Contains(“\n”);
如果(必须引用)
{
StringBuilder sb=新的StringBuilder();
某人加上“\”;
foreach(str中的字符nextChar)
{
某人追加(下一次);
如果(nextChar==“”)
某人加上“\”;
}
某人加上“\”;
使某人返回字符串();
}
返回str;
}
我的佩妮想:

String[] lines = new String[] { "\"\",\"word\",word,word2,1,34,5,2,\"details\"" };
for (int j = 0; j < lines.Length; j++)
{
    String[] fields=lines[j].Split(',');
    for (int i =0; i<fields.Length; i++)
    {
        if (fields[i].StartsWith("\"") && fields[i].EndsWith("\""))
        {
            char[] tmp = new char[fields[i].Length-2];
            fields[i].CopyTo(1,tmp,0,fields[i].Length-2);
            fields[i] =tmp.ToString();
            fields[i] = "\""+fields[i].Replace("\"","\"\"")+"\"";
        }
        else
            fields[i] = fields[i].Replace("\"","\"\"");

    }
    lines[j]=String.Join(",",fields);
String[]line=新字符串[]{“\”,“word\”,word,word2,1,34,5,2,\“details\”;
对于(int j=0;j对于(int i=0;i,经过深思熟虑后,决定需要修复导入实用程序格式。字符串转义是正确的(如用户所示),但导入实用程序使用的格式文件不正确,导致其中断导入

感谢所有人,特别感谢@dbt(向上投票)

基于“Ed Bayiates”的贡献这里有一个有用的类来构建csv文档:

/// <summary>
/// helpful class to build csv document
/// </summary>
public class CsvBuilder
{
    /// <summary>
    /// create the csv builder
    /// </summary>
    public CsvBuilder(char csvSeparator)
    {
        m_csvSeparator = csvSeparator;
    }

    /// <summary>
    /// append a cell
    /// </summary>
    public void appendCell(string strCellValue)
    {
        if (m_nCurrentColumnIndex > 0) m_strBuilder.Append(m_csvSeparator);

        bool mustQuote = (strCellValue.Contains(m_csvSeparator)
                        || strCellValue.Contains('\"') 
                        || strCellValue.Contains('\r') 
                        || strCellValue.Contains('\n'));

        if (mustQuote)
        {
            m_strBuilder.Append('\"');
            foreach (char nextChar in strCellValue)
            {
                m_strBuilder.Append(nextChar);
                if (nextChar == '"') m_strBuilder.Append('\"');
            }
            m_strBuilder.Append('\"');
        }
        else
        {
            m_strBuilder.Append(strCellValue);
        }
        m_nCurrentColumnIndex++;
    }

    /// <summary>
    /// end of line, new line
    /// </summary>
    public void appendNewLine()
    {
        m_strBuilder.Append(Environment.NewLine);
        m_nCurrentColumnIndex = 0;
    }

    /// <summary>
    /// Create the CSV file
    /// </summary>
    /// <param name="path"></param>
    public void save(string path )
    {
        File.WriteAllText(path, ToString());
    }

    public override string ToString()
    {
        return m_strBuilder.ToString();
    }

    private StringBuilder m_strBuilder = new StringBuilder();
    private char m_csvSeparator;
    private int m_nCurrentColumnIndex = 0;

}

根据Ed Bayiates的回答:

/// <summary>
/// Turn a string into a CSV cell output
/// </summary>
/// <param name="value">String to output</param>
/// <returns>The CSV cell formatted string</returns>
private string ConvertToCsvCell(string value)
{
    var mustQuote = value.Any(x => x == ',' || x == '\"' || x == '\r' || x == '\n');

    if (!mustQuote)
    {
        return value;
    }

    value = value.Replace("\"", "\"\"");

    return string.Format("\"{0}\"", value);
}
//
///将字符串转换为CSV单元格输出
/// 
///要输出的字符串
///CSV单元格格式的字符串
私有字符串ConvertToCsvCell(字符串值)
{
变量mustQuote=value.Any(x=>x=','||x='\'“\'”|x=='\r'|x='\n');
如果(!mustQuote)
{
返回值;
}
值=值。替换(“\”,“\”);
返回string.Format(“\”{0}\”,value);
}

不同的应用程序往往具有不同的CSV规范。您要导入哪个应用程序?可能值得检查它为您的特定用例输出的内容。如果
,“word1,word2,…”
是值,则
,“word1,word2,…”
是转义的CSV字段。具体是什么中断?@dtb导入文件的过程使用BCP实用程序将其导入SQL datbase…终止符声明为“,”,它将上述解释为2个字段,而不是1,因此实用程序中断。太棒了!…不是。解决方法:全部替换
使用其他内容,导入,执行SQL查询以将其他内容替换回
。我不确定BCP是否能与CSV输入一起工作。如果它声称能正确读取CSV,则它没有正确读取。我已将上述代码中的CSV读取到Excel中,没有问题。如果我的代码与您的代码获得相同的输出,则可能会有一个特定的CSV读取器损坏。我从我的代码中获得相同的输出:“”、word1、word2,…”,并将其作为“”读取到Excel中,“word1,word2,…”如预期。如果您的代码生成该输出,则您的代码已经正确。我相信我的问题是导入实用程序终止符(如问题更新中所述),所以我想知道是否有方法添加额外的转义序列以使其工作!我在寻找完全相同的东西。@kavun是的,这是显而易见的,而且是故意的。空检查在多次调用的函数中通常是不合适的。如果您采用此代码,则如何处理坏数据取决于您。原始字符串s将按原样出现在db中-我希望我可以删除其中的空引号…简单替换最简单的解决方案。但是计算上要昂贵得多!Ed的代码使用StringBuilder是有充分理由的。对于大型CSV文件,性能将差几个数量级!简单是相对的。如果你喜欢花几个小时跟踪执行如果代码中存在瓶颈,请复制此代码段。如果没有,请使用Ed的代码。对于
mustQuote
表达式,请使用
Regex.IsMatch(值“[,\”\\r\\n]”;
。更快。
/// <summary>
/// Turn a string into a CSV cell output
/// </summary>
/// <param name="value">String to output</param>
/// <returns>The CSV cell formatted string</returns>
private string ConvertToCsvCell(string value)
{
    var mustQuote = value.Any(x => x == ',' || x == '\"' || x == '\r' || x == '\n');

    if (!mustQuote)
    {
        return value;
    }

    value = value.Replace("\"", "\"\"");

    return string.Format("\"{0}\"", value);
}