2016-06-29 6 views
2

Ich benutze CsvHelper. Um in eine .csv Datei zu schreiben, brauche ich einen Header, der auf einer Klasse basiert.Schreiben einer Kopfzeile mit CsvHelper? C#

Ich schreibe den Header manuell und es funktioniert, aber ich muss automatisch gemacht werden, wenn es gelesen wird.

Die gesamte Dokumentation, die ich finden kann, besagt, diesen Ausdruck zu verwenden, writer.WriteHeader<CSVDataFormat>();, aber das funktioniert nicht, weil es mehr Arbeit benötigt, um es zu erledigen. Hier

ist die Klasse, die Header basieren sollte sich aus:

public class CSVDataFormat 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public float Wage { get; set; } 
} 

Hier ist der Code für das Lesen und Schreiben:

private void ReadCSV(string ogCsvFile) 
{ 
     using (var streamReaederfileDir = new StreamReader(@ogCsvFile)) 
     { 
      using (var streamWriterFileDir = new StreamWriter(Path.Combine(Path.GetDirectoryName(ogCsvFile), "New" + Path.GetFileName(ogCsvFile)))) 
      { 
       var reader = new CsvReader(streamReaederfileDir); 
       var writer = new CsvWriter(streamWriterFileDir); 

       writer.WriteHeader<CSVDataFormat>(); 

       IEnumerable records = reader.GetRecords<CSVDataFormat>().ToList(); 

       foreach (CSVDataFormat record in records) 
       { 
        record.Wage = record.Wage + (record.Wage/10); 
        writer.WriteField(record.FirstName); 
        writer.WriteField(record.LastName); 
        writer.WriteField(record.Wage); 
        writer.NextRecord(); 
       } 
      } 
     } 
} 

aktualisieren

Dies ist Fehler, den ich erhalte, wenn ich meinen Code starte:

Eine nicht behandelte Ausnahme des Typs ‚CsvHelper.CsvMissingFieldException‘ aufgetreten in CsvHelper.dll

Zusätzliche Informationen: Felder ‚Vorname‘ existiert nicht in der CSV-Datei.

+1

definieren Was brauchen Sie in der Kopfzeile getan? Ich kann nicht sehen, wo Sie überhaupt eine schreiben – Plutonix

+1

@Plutonix Ich aktualisierte meinen Code, wo ich den Ausdruck verwenden. – Smithy

+1

@Plutonix Der 'writer.WriteHeader ();' soll die 'get & set' -Funktionen aus der CSVDataFormat-Klasse erhalten und deren Namen und Datentypen am Anfang der CSV-Datei hinzufügen. Dieser Header ist für CsvHelper erforderlich. – Smithy

Antwort

7

Sie können verwirrt sein, wie CSVHelper funktioniert. Dieser Code behandelt den Schreib Aspekt Ihrer Lese in-schreiben-Schleife:

List<Employee> empList = new List<Employee>(); 

empList.Add(new Employee { FirstName = "Ziggy", LastName = "Walters", Wage = 132.50F }); 
empList.Add(new Employee { FirstName = "Zoey", LastName = "Strand", Wage = 76.50F }); 

using (StreamWriter sw = new StreamWriter(@"C:\Temp\emp.csv")) 
using (CsvWriter cw = new CsvWriter(sw)) 
{ 
    cw.WriteHeader<Employee>(); 

    foreach (Employee emp in empList) 
    { 
     emp.Wage *= 1.1F; 
     cw.WriteRecord<Employee>(emp); 
    } 
} 
  • CSVWriter implementiert IDisposable, so dass ich es in einen als auch mit Block. ist
  • Die Lohnanpassung

Ergebnis leicht rationalisiert:

Vorname, Nachname, Lohn
Ziggy, Walters, 145,75
Zoey, Strand, 84,15

Schreibkopf schreibt nur die erste Zeile - die Namen der Spalten/Elemente. Beachten Sie, dass die aufgelisteten Löhne sich von denen unterscheiden, die ich für die Erstellung der einzelnen Löhne verwendet habe.

Für das, was Sie tun, würde ich anstelle der Iteration der empList ein typisiertes Objekt einlesen. Für den in der Bearbeitung aufgelisteten Fehler bedeutet dies, dass in der Eingabedatei keine Spalte mit diesem Namen gefunden wurde (wahrscheinlich, weil Sie die Überladung Typ nicht verwendet haben). Die Klasseneigenschaftsnamen sollten genau mit den Spaltennamen übereinstimmen (möglicherweise möchten Sie auch CSVHelper konfigurieren).


Der vollständige in-out Schleife nur etwas komplexer ist:

using (StreamReader sr = new StreamReader(@"C:\Temp\empIN.csv")) 
using (StreamWriter sw = new StreamWriter(@"C:\Temp\empOUT.csv")) 
using (CsvWriter cw = new CsvWriter(sw)) 
using (CsvReader cr = new CsvReader(sr)) 
{ 
    cw.WriteHeader<Employee>(); 
    var records = cr.GetRecords<Employee>(); 

    foreach (Employee emp in records) 
    { 
     emp.Wage *= 1.1F; 
     cw.WriteRecord<Employee>(emp); 
    } 

} 

Ergebnisse, die die Ausgabe von der ersten Schleife als Eingabe:

Vorname, Nachname, Wage
Ziggy, Walters, 160.325
Zoey, Strang, 92.565

Wenn in der eingehenden CSV kein Header-Datensatz vorhanden ist, weiß er nicht, wie Daten der Klasse zugeordnet werden. Sie brauchen eine Karte hinzuzufügen:

public class EmployeeMap : CsvHelper.Configuration.CsvClassMap<Employee> 
{ 
    public EmployeeMap() 
    { 
     Map(m => m.FirstName).Index(0); 
     Map(m => m.LastName).Index(1); 
     Map(m => m.Wage).Index(2); 
    } 
} 

-Mine befindet sich in der Employee Klasse verschachtelt. Dann geben CSVHelper diese Karte:

... before your try to read from the incoming CSV: 
cr.Configuration.RegisterClassMap<Employee.EmployeeMap>(); 

cw.WriteHeader<Employee>(); 
... 

Jetzt weiß es, wie Sie CSV-Spalten zu den Eigenschaften in Ihrer Klasse zuordnen.

+0

Wie kann ich empList den Inhalt meiner CSV-Datei gleich machen? – Smithy

+0

Sie haben das schon in 'Records'. Sie müssen sicherstellen, dass 'CSVDataFormat' Ihre eingehende CSV korrekt definiert. 'writer.WriteField (record);' – Plutonix

+0

Ich kann 'IEnumerable records = reader.GetRecords () nicht verwenden. ToList();' mit der von Ihnen bereitgestellten Lösung – Smithy

0

Ich glaube, diese Ausnahme stammt aus dem CsvReader und nicht der CsvWriter. Die Standard-CsvConfiguration erwartet einen Header und verwendet AutoMap zum Generieren einer PropertyName-to-Index-Zuordnung.

Aus der Dokumentation Sie eine Karte benötigen see mapping

Verwandte Themen