Generieren von CSV-Zeichenfolgen für verschiedene Dienstprogramme von Drittanbietern

1931
Greg Buehler

Ich generiere CSV-Zeichenfolgen für verschiedene Dienstprogramme von Drittanbietern, und dieser Codeabschnitt wird in vielen Klassen wiederholt. Gibt es eine bessere Möglichkeit, diese Zeichenfolge zu generieren?

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
    ));
}
Antworten
21
Ich würde einen StringBuilder verwenden, wenn dies für Java wäre. Möglicherweise gibt es ein C # -Äquivalent? Jeremy Heiler vor 9 Jahren 0
@Jeremy Heiler, es gibt :) genau die gleiche Struktur wie ich glaube RobertPitt vor 9 Jahren 0

5 Antworten auf die Frage

19
Alex Humphrey

Ich bezweifle, dass Sie eine Möglichkeit finden, alle diese Eigenschaften nicht ohne Reflektion aufzulisten, aber das folgende hilft, die riesige Formatzeichenfolge zu beseitigen, die wahrscheinlich zur Fehlerquelle wird.

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);

Ein paar Dinge zu beachten:

Dies ist kaum ein effizienter Weg, bietet jedoch ziemlich wartbaren Code. Wenn Sie eine zusätzliche Eigenschaft haben, fügen Sie sie einfach dem Array hinzu.

Dies funktioniert nur in .NET 4.0. In früheren Versionen müssen Sie ToArray()nach diesem Aufruf anrufen Select.

Dies ist eine viel sauberere Methode und adressiert die fehleranfällige Formatzeichenfolge. Das hat mir das Leben leichter gemacht. Greg Buehler vor 9 Jahren 0
Wenn Sie "\ u0022" + String.Join zurückgeben ("\ u0022, \ u0022", Eigenschaften) + "\ u0022" `, können Sie die Select-Projektion ganz vermeiden. ICR vor 9 Jahren 2
10
BenV

Verwenden Sie ein 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();
Ich frage mich, ob `String.Format` unter der Haube verwendet wird. Jeremy Heiler vor 9 Jahren 1
Eigentlich string.Format verwendet StringBuilder (so sagt Reflector), so dass in diesem speziellen Fall kein Speicher- / Leistungsvorteil entsteht (einmalige Formatierung der Zeichenfolge). Jaime vor 9 Jahren 1
6
Sean Lynch

Vielleicht so etwas:

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

Bearbeiten:

Wenn man darüber nachdenkt, könnte es besser sein, einen String-Builder so aufzubauen:

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

Dadurch müssten lange Zeichenfolgen im gesamten Code wiederholt werden. Bearbeiten: Die Funktion hat das ursprüngliche Ergebnis zurückgegeben.

Sie müssten sich an `" \ u0022, \ u0022 "` beteiligen und dann am Anfang und Ende auch "\ u0022" hinzufügen, um das gleiche Ergebnis wie das Original zu erhalten. sepp2k vor 9 Jahren 1
@ sepp2k Dein Recht, ich ändere den Code entsprechend Sean Lynch vor 9 Jahren 0
2
Hosam Aly

Als Variante der Lösung von Alex Humphrey können Sie dies zur Verbesserung der Leistung versuchen:

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
};

var builder = new StringBuilder(properties.Length * 6);
foreach (var property in properties)
{
    builder.Append('"').Append(property).Append('"').Append(',');
}
builder.Remove(builder.Length - 1, 1); // remove the last comma

return builder.ToString();

Beachten Sie jedoch, dass dieser Code anfällig für Fehler ist, wenn eine der Eigenschaften ein doppeltes Anführungszeichen enthält. Sie sollten sicherstellen, dass sie entkommen sind.

2
Malachi

In den neuen Versionen von C # können Sie die String-Interpolation verwenden, um das Codieren ein wenig zu erleichtern und zu wissen, wo die Variablen in den String eingefügt werden. Alles, was Sie tun, ist ein $ vor dem ersten Anführungszeichen.

Dann wird die Rückkehr stattdessen dies

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";