2016-09-11 5 views
0

テスト用に数百万行の大きなCSVを読み込もうとしています。私はプロバイダを使用してCSVをデータベースとして扱うことができることを知っています。Microsoft.ACE.OLEDB.12.0Microsoft.ACE.OLEDB.12.0 OleDbConnectionを使用してCSVをカスタムオブジェクトに変換する

小さいデータセットを使用して、.GetValue(int)を使用して行の内容を位置的に読み取ることができます。私はデータを読むことがより良いということを見いだすのに苦労しています(1つでもあると仮定します)。手前のカラム名を知っていれば、これは簡単です。しかし、私がそれらを知らなかったら、ファイルの最初の行を読んで、そのデータを愚かに見えるようにしなければならないでしょう。

@" 
id,first_name,last_name,email,ip_address 
1,Edward,Richards,[email protected],201.133.112.30 
2,Jimmy,Scott,[email protected],103.231.149.144 
3,Marilyn,Williams,[email protected],52.180.157.43 
4,Frank,Morales,[email protected],218.175.165.205 
5,Chris,Watson,[email protected],75.251.1.149 
6,Albert,Ross,[email protected],89.56.133.54 
7,Diane,Daniels,[email protected],197.156.129.45 
8,Nancy,Carter,[email protected],75.162.65.142 
9,John,Kennedy,[email protected],85.35.177.235 
10,Bonnie,Bradley,[email protected],255.67.106.193 
"@ | Set-Content .\test.csv 

$conn = New-Object System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source='C:\Users\Matt';Extended Properties='Text;HDR=Yes;FMT=Delimited';") 
$cmd=$conn.CreateCommand() 
$cmd.CommandText="Select * from test.csv where first_name like '%n%'" 
$conn.open() 
$data = $cmd.ExecuteReader() 

$data | ForEach-Object{ 
    [pscustomobject]@{ 
     id=$_.GetValue(0) 
     first_name=$_.GetValue(1) 
     last_name=$_.GetValue(2) 
     ip_address=$_.GetValue(4) 
    } 
} 

$cmd.Dispose() 
$conn.Dispose() 

$cmd.ExecuteReader()の出力を処理するより良い方法はありますか? CSVインポートのための情報を得ることが難しい。 Webのほとんどは、SQLデータベースからこのプロバイダを使用してCSVにエクスポートすることを扱っています。ここでのロジックは大規模なCSVに適用されるので、大部分のデータを無視するだけで全体を読む必要はありません。

答えて

0

私はTechNet for the OleDbDataReader Classの近くを見るべきでした。 SQL文から返されるデータを理解するのに役立つメソッドとプロパティがいくつかあります。

  • FieldCount

    :現在行の列数を取得します。

    他に何もない場合は、行にいくつの列があるかわかります。

  • Item[Int32]:列序所与そのネイティブフォーマットで指定されたカラムの値を取得します。

    これを使用して、各行からデータを取り戻すことができます。これはGetValue()と同じように動作します。

  • GetName(Int32):指定された列の名前を取得します。

    したがって、列の名前がわからない場合は、指定したインデックスから取得するために使用できます。

は、多くの他の方法といくつかのプロパティがありますが、それらはあなたが(あなたが手動で手前に検証したくないと仮定して)CSV内に含まれるどのようなデータがわからない場合は光を当てるには十分です。だから、だろうと同じ情報を得るために、より動的な方法、ということを知って...これの

$data | ForEach-Object{ 

    # Save the current row as its own object so that it can be used in other scopes 
    $dataRow = $_ 
    # Blank hashtable that will be built into a "row" object 
    $properties = @{} 

    # For every field that exists we will add it name and value to the hashtable 
    0..($dataRow.FieldCount - 1) | ForEach-Object{ 
     $properties.($dataRow.GetName($_)) = $dataRow.Item($_) 
    } 

    # Send the newly created object down the pipeline. 
    [pscustomobject]$properties 
} 

$cmd.Dispose() 
$conn.Dispose() 

唯一の欠点は、カラムはおそらく元のCSVなどいないのと同じ順序で出力されるということです。これは、行名を別の変数に保存し、パイプの最後にSelectを使用することでアドレスにすることができます。この答えは、ほとんどが返された列名と値を理解しようとしていました。

関連する問題