我正在为各种第三方工具生成CSV字符串,并且在许多类中都重复了这一部分代码。有更好的方法来生成此字符串吗?

public override string CsvString()
{
    return (
        string.Format("\u0022{0}\u0022,\u0022{1}\u0022,\u0022{2}\u0022,\u0022{3}\u0022,\u0022{4}\u0022,\u0022{5}\u0022,\u0022{6}\u0022,\u0022{7}\u0022,\u0022{8}\u0022,\u0022{9}\u0022,\u0022{10}\u0022,\u0022{11}\u0022,\u0022{12}\u0022,\u0022{13}\u0022",

        this.BlockType,         //  1, A_NAME
        this.Tag,               //  2, A_TAG
        this.Description,       //  3, A_DESC
        this.InitialScan,       //  4, A_ISCAN
        this.AutoManual,        //  5, A_SCAN
        this.ScanTime,          //  6, A_SCANT
        this.IoDevice,          //  7, A_IODV
        this.IoAddress,         //  8, A_IOAD
        this.InitialAmStatus,   //  9, A_IAM
        this.AlarmPriority,     // 10, A_PRI
        this.AlarmEnable,       // 11, A_ENAB
        this.EnableOutput,      // 12, A_EOUT
        this.HistDescription,   // 13, A_HIST_DESC
        this.SecurityArea1      // 14, A_SECURITYAREA1
    ));
}


评论

如果这是用于Java,我将使用StringBuilder。可能有等效的C#?

@Jeremy Heiler,有:)我也相信完全相同的结构

#1 楼

我怀疑您会找到一种在不使用反射的情况下不列出所有这些属性的方法,但是以下内容有助于消除可能成为错误源的巨大格式字符串。

var properties = new Object[]
{
    this.BlockType,         //  1, A_NAME
    this.Tag,               //  2, A_TAG
    this.Description,       //  3, A_DESC
    this.InitialScan,       //  4, A_ISCAN
    this.AutoManual,        //  5, A_SCAN
    this.ScanTime,          //  6, A_SCANT
    this.IoDevice,          //  7, A_IODV
    this.IoAddress,         //  8, A_IOAD
    this.InitialAmStatus,   //  9, A_IAM
    this.AlarmPriority,     // 10, A_PRI
    this.AlarmEnable,       // 11, A_ENAB
    this.EnableOutput,      // 12, A_EOUT
    this.HistDescription,   // 13, A_HIST_DESC
    this.SecurityArea1      // 14, A_SECURITYAREA1
}.Select(x => String.Format("\u0022{0}\u0022", x));

return String.Join(",", properties);


需要注意的几件事:

这不是一种有效的方法,但是提供了可维护的代码。如果您有其他属性,只需将其添加到数组即可。

仅在.NET 4.0中有效。在早期版本中,必须先调用ToArray(),然后再调用Select

评论


\ $ \ begingroup \ $
这是一种更简洁的方法,可解决容易出错的格式字符串。这使我的生活更加轻松。
\ $ \ endgroup \ $
– Greg Buehler
2011年1月20日15:15

\ $ \ begingroup \ $
如果确实返回“ \ u0022” + String.Join(“ \ u0022,\ u0022”,properties)+“ \ u0022”,则可以完全避免使用Select投影。
\ $ \ endgroup \ $
– ICR
11年1月27日在21:30

#2 楼

使用StringBuilder

sbuilder.AppendFormat("\u0022{0}\u0022,\u0022{1}\u0022,\u0022{2}\u0022,\u0022{3}\u0022,\u0022{4}\u0022,\u0022{5}\u0022,\u0022{6}\u0022,\u0022{7}\u0022,\u0022{8}\u0022,\u0022{9}\u0022,\u0022{10}\u0022,\u0022{11}\u0022,\u0022{12}\u0022,\u0022{13}\u0022",
    this.BlockType,         //  1, A_NAME
    this.Tag,               //  2, A_TAG
    this.Description,       //  3, A_DESC
    this.InitialScan,       //  4, A_ISCAN
    this.AutoManual,        //  5, A_SCAN
    this.ScanTime,          //  6, A_SCANT
    this.IoDevice,          //  7, A_IODV
    this.IoAddress,         //  8, A_IOAD
    this.InitialAmStatus,   //  9, A_IAM
    this.AlarmPriority,     // 10, A_PRI
    this.AlarmEnable,       // 11, A_ENAB
    this.EnableOutput,      // 12, A_EOUT
    this.HistDescription,   // 13, A_HIST_DESC
    this.SecurityArea1      // 14, A_SECURITYAREA1
 ).AppendLine();


评论


\ $ \ begingroup \ $
我想知道这是不是String.Format在幕后使用了什么?
\ $ \ endgroup \ $
–杰里米·海勒(Jeremy Heiler)
2011年1月19日23:40

\ $ \ begingroup \ $
实际上string.Format在其中使用了StringBuilder(或者Reflector说),因此在这种特定情况下(字符串的一次格式化)不会在内存/性能方面带来好处。
\ $ \ endgroup \ $
– Jaime
2011年1月20日,下午1:36

#3 楼

也许是这样的:

public static string MakeCsvLine(params string[] items)
{
  return String.Format("\u0022{0}\u0022",String.Join("\u0022,\u0022",items));
}


编辑:

考虑到使用它构建字符串生成器可能会更好,所以:

public static void AddCsvLine(StringBuilder sb, params string[] items)
{
  sb.AppendFormat("\u0022{0}\u0022",String.Join("\u0022,\u0022",items))
        .AppendLine();
}


这将避免在整个代码中重复长字符串。
编辑:使函数返回原始结果。

评论


\ $ \ begingroup \ $
您必须加入“ \ u0022,\ u0022”,然后在开头和结尾添加“ \ u0022”,以得到与原始结果相同的结果。
\ $ \ endgroup \ $
–sepp2k
2011年1月20日下午4:40

\ $ \ begingroup \ $
@ sepp2k您的权利,我更改了代码以反映这一点
\ $ \ endgroup \ $
– Sean Lynch
2011年1月20日上午11:59

#4 楼

作为Alex Humphrey解决方案的一种变体,您可以尝试使用以下方法来提高性能:引用。您应该确保它们已被逃脱。

#5 楼

在新版本的C#中,您可以使用字符串插值使编码更容易一点,并知道将变量插入字符串的位置。您要做的就是将$放在引号前。

然后Return变成这个

return $"\u0022{this.BlockType}\u0022,\u0022{this.Tag}\u0022,\u0022{this.Description}\u0022,\u0022{This.InitialScan}\u0022,\u0022{this.AutoManual}\u0022,\u0022{this.ScanTime}\u0022,\u0022{this.IoDevice}\u0022,\u0022{this.IoAddress}\u0022,\u0022{this.InitialAmStatus}\u0022,\u0022{this.AlarmPriority}\u0022,\u0022{this.AlarmEnable}\u0022,\u0022{this.EnableOutput}\u0022,\u0022{this.HistDescription}\u0022,\u0022{this.SecurityArea}\u0022";