Wenn Sie eine CSV-Datei zu lesen ein Datareader und die OLEDB Jet-Datenanbieter verwenden, wie kann ich Spaltendatentypen steuern?

StackOverflow https://stackoverflow.com/questions/115658

  •  02-07-2019
  •  | 
  •  

Frage

In meiner C # Anwendung Ich bin mit dem Microsoft Jet OLEDB-Datenanbieter eine CSV-Datei zu lesen. Die Verbindungszeichenfolge sieht wie folgt aus:

Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\Data;Extended Properties="text;HDR=Yes;FMT=Delimited

Ich öffne eine ADO.NET-OleDbConnection Verwendung dieser Verbindungszeichenfolge und wählen Sie alle Zeilen aus der CSV mit dem Befehl Datei:

select * from Data.csv

Wenn ich eine OleDbDataReader öffnen und die Datentypen der Spalten untersucht sie zurückkommt, finde ich, dass etwas in dem Stapel hat versucht, an den Datentypen in der ersten Zeile von Daten in der Datei basieren, zu erraten. Angenommen, die CSV-Datei enthält:

House,Street,Town
123,Fake Street,Springfield
12a,Evergreen Terrace,Springfield

Der Aufruf der OleDbDataReader.GetDataTypeName Methode für das Haus Spalte wird zeigen, dass die Spalte den Datentyp „DBTYPE_I4“ gegeben wurde, so dass alle von ihm gelesenen Werte werden als ganze Zahlen interpretiert. Mein Problem ist, dass Haus ein String sein sollte -. Wenn ich das Haus Wert aus der zweiten Reihe zu lesen, die OleDbDataReader null zurück

Wie kann ich entweder die Jet-Datenbank-Anbieter oder die OleDbDataReader erzählen eine Spalte als Strings anstelle von Zahlen zu interpretieren?

War es hilfreich?

Lösung

Es gibt eine Schema-Datei, die Sie, dass ADO.NET erstellen würde sagen, wie die CSV zu interpretieren -. In der Tat eine Struktur zu geben

Versuchen Sie folgendes: http://www.aspdotnetcodes.com/Importing_CSV_Database_Schema.ini.aspx

Andere Tipps

auf Marcs Antwort zu erweitern, muß ich eine Textdatei erstellen namens Schema.ini und es im selben Verzeichnis wie die CSV-Datei setzen. Neben Spaltentypen kann diese Datei mit dem Dateiformat, das Datum Zeitformat, regionale Einstellungen angeben, und die Spaltennamen, wenn sie nicht in der Datei enthält.

Um das Beispiel mache ich in der Frage der Arbeit gab, sollte die Schema-Datei wie folgt aussehen:

[Data.csv]
ColNameHeader=True
Col1=House Text
Col2=Street Text
Col3=Town Text

Ich könnte auch versuchen, diese den Datenanbieter zu machen, untersucht alle Zeilen in der Datei, bevor es die Datentypen zu erraten versucht:

[Data.csv]
ColNameHeader=true
MaxScanRows=0

Im wirklichen Leben, meine Anwendung importiert Daten aus Dateien mit dynamischen Namen, so habe ich eine Datei Schema.ini on the fly erstellen und sie in das gleichen Verzeichnis wie die CSV-Datei schreiben, bevor ich meine Verbindung zu öffnen.

Weitere Informationen finden Sie hier - http: // msdn.microsoft.com/en-us/library/ms709353(VS.85).aspx - oder von der MSDN Library für "Datei Schema.ini" gesucht

.

Bitte überprüfen

http://kbcsv.codeplex.com/

using (var reader = new CsvReader("data.csv"))
{
    reader.ReadHeaderRecord();
    foreach (var record in reader.DataRecords)
    {
        var name = record["Name"];
        var age = record["Age"];
    }
}

Sie müssen die Fahrer sagen, alle Zeilen zu scannen, das Schema zu bestimmen. Andernfalls, wenn die ersten paar Zeilen sind numerisch und der Rest sind alphanumerische Zeichen, die alphanumerischen Zellen wird leer sein.

Wie Rory , fand ich, dass ich brauchte eine schema.ini Datei dynamisch zu erstellen, da es keine Möglichkeit gibt programatically sagen Sie dem Fahrer alle Zeilen zu scannen. (Dies ist nicht der Fall für Excel-Dateien)

Sie müssen MaxScanRows=0 in Ihrem schema.ini haben

Hier ist ein Codebeispiel:

    public static DataTable GetDataFromCsvFile(string filePath, bool isFirstRowHeader = true)
    {
        if (!File.Exists(filePath))
        {
            throw new FileNotFoundException("The path: " + filePath + " doesn't exist!");
        }

        if (!(Path.GetExtension(filePath) ?? string.Empty).ToUpper().Equals(".CSV"))
        {
            throw new ArgumentException("Only CSV files are supported");
        }
        var pathOnly = Path.GetDirectoryName(filePath);
        var filename = Path.GetFileName(filePath);
        var schemaIni =
            $"[{filename}]{Environment.NewLine}" +
            $"Format=CSVDelimited{Environment.NewLine}" +
            $"ColNameHeader={(isFirstRowHeader ? "True" : "False")}{Environment.NewLine}" +
            $"MaxScanRows=0{Environment.NewLine}" +
            $" ; scan all rows for data type{Environment.NewLine}" +
            $" ; This file was automatically generated";
        var schemaFile = pathOnly != null ? Path.Combine(pathOnly, "schema.ini") : "schema.ini";
        File.WriteAllText(schemaFile, schemaIni);

        try
        {
            var sqlCommand = $@"SELECT * FROM [{filename}]";

            var oleDbConnString =
                $"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={pathOnly};Extended Properties=\"Text;HDR={(isFirstRowHeader ? "Yes" : "No")}\"";

            using (var oleDbConnection = new OleDbConnection(oleDbConnString))
            using (var adapter = new OleDbDataAdapter(sqlCommand, oleDbConnection))
            using (var dataTable = new DataTable())
            {
                adapter.FillSchema(dataTable, SchemaType.Source);
                adapter.Fill(dataTable);
                return dataTable;
            }
        }
        finally
        {
            if (File.Exists(schemaFile))
            {
                File.Delete(schemaFile);
            }
        }
    }

Sie müssen einige Änderungen tun, wenn Sie diese in mehreren Threads auf das gleiche Verzeichnis laufen zur gleichen Zeit.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top