DataReader 및 OLEDB Jet 데이터 공급자를 사용하여 CSV 파일을 읽을 때 열 데이터 유형을 어떻게 제어할 수 있습니까?

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

  •  02-07-2019
  •  | 
  •  

문제

내 C# 응용 프로그램에서는 Microsoft Jet OLEDB 데이터 공급자를 사용하여 CSV 파일을 읽습니다.연결 문자열은 다음과 같습니다.

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

해당 연결 문자열을 사용하여 ADO.NET OleDbConnection을 열고 다음 명령을 사용하여 CSV 파일의 모든 행을 선택합니다.

select * from Data.csv

OleDbDataReader를 열고 반환되는 열의 데이터 유형을 검사할 때 스택의 어떤 항목이 파일의 첫 번째 데이터 행을 기반으로 데이터 유형을 추측하려고 시도한 것을 발견했습니다.예를 들어 CSV 파일에 다음이 포함되어 있다고 가정합니다.

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

House 열에 대해 OleDbDataReader.GetDataTypeName 메서드를 호출하면 해당 열에 "DBTYPE_I4" 데이터 유형이 지정되어 해당 열에서 읽은 모든 값이 정수로 해석된다는 사실이 드러납니다.내 문제는 House가 문자열이어야 한다는 것입니다. 두 번째 행에서 House 값을 읽으려고 하면 OleDbDataReader가 null을 반환합니다.

Jet 데이터베이스 공급자나 OleDbDataReader에게 열을 숫자 대신 문자열로 해석하도록 지시하려면 어떻게 해야 합니까?

도움이 되었습니까?

해결책

ADO.NET에 CSV를 해석하는 방법을 알려주는 스키마 파일을 만들 수 있습니다. 즉, 실제로 구조를 제공하는 것입니다.

이 시도: http://www.aspdotnetcodes.com/Importing_CSV_Database_Schema.ini.aspx

다른 팁

Marc의 답변을 확장하려면 Schema.ini라는 텍스트 파일을 만들어 CSV 파일과 동일한 디렉터리에 넣어야 합니다.열 유형뿐만 아니라 이 파일은 파일 형식, 날짜 시간 형식, 지역 설정 및 열 이름(파일에 포함되지 않은 경우)을 지정할 수 있습니다.

질문에 제시한 예제가 작동하려면 스키마 파일이 다음과 같아야 합니다.

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

또한 데이터 공급자가 데이터 유형을 추측하기 전에 파일의 모든 행을 검사하도록 하기 위해 다음과 같이 시도할 수도 있습니다.

[Data.csv]
ColNameHeader=true
MaxScanRows=0

실제로 내 응용 프로그램은 동적 이름을 가진 파일에서 데이터를 가져오기 때문에 Schema.ini 파일을 즉시 생성하고 연결을 열기 전에 CSV 파일과 동일한 디렉터리에 작성해야 합니다.

자세한 내용은 여기에서 확인하실 수 있습니다 - http://msdn.microsoft.com/en-us/library/ms709353(VS.85).aspx - 또는 MSDN 라이브러리에서 "Schema.ini 파일"을 검색합니다.

확인해주십시오

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

스키마를 결정하려면 모든 행을 스캔하도록 드라이버에 지시해야 합니다.그렇지 않고 처음 몇 행이 숫자이고 나머지 행이 영숫자인 경우 영숫자 셀은 비어 있게 됩니다.

좋다 로리, 모든 행을 스캔하도록 드라이버에 프로그래밍 방식으로 지시할 방법이 없기 때문에 Schema.ini 파일을 동적으로 생성해야 한다는 것을 알았습니다.(엑셀 파일은 그렇지 않습니다.)

당신은 가지고 있어야합니다 MaxScanRows=0 귀하의 Schema.ini에서

다음은 코드 예시입니다.

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

여러 스레드의 동일한 디렉터리에서 동시에 실행하는 경우 몇 가지 수정이 필요합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top