2

サードパーティによって生成されたいくつかの DBF ファイルがあり、それらをクエリできるようにする必要があります。すべての列タイプが文字として定義されているため、問題が発生していますが、これらのフィールドの一部のデータには実際にはバイナリ データが含まれています。OleDbDataReader を文字列または文字配列以外として使用してこれらのフィールドを読み取ろうとすると、InvalidCastException がスローされますが、それらをバイナリ値として読み取るか、読み取った後に少なくともキャスト/変換できる必要があります。 . 実際にテキストを含む列は、期待どおりに返されています。

たとえば、最初の列は長さ 2 バイトの文字フィールドとして定義されていますが、このフィールドには 16 ビット整数が含まれています。

最初の列を読み取って適切なデータ型に変換する次のテスト コードを作成しましたが、値が正しく出力されません。

データベースの最初の行の最初の列の値は 17365 (0x43D5) です。次のコードを実行すると、最終的に 17215 (0x433F) になります。データリーダーによって返された文字列からバイトを取得するためにASCIIエンコーディングを使用する必要があると確信していますが、必要な形式に値を取得する別の方法はわかりません。独自の DBF リーダーを作成し、絶対に必要でない限り、ADO.NET を完全にバイパスします。どんな助けでも大歓迎です。

        byte[] c0;
        int i0; 

        string con = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\ASTM;Extended Properties=dBASE III;User ID=Admin;Password=;";

        using (OleDbConnection c = new OleDbConnection(con))
        {
            c.Open();
            OleDbCommand cmd = c.CreateCommand();
            cmd.CommandText = "SELECT * FROM astm2007";
            OleDbDataReader dr = cmd.ExecuteReader();
            while (dr.Read())
            {
                c0 = Encoding.ASCII.GetBytes(dr.GetValue(0).ToString());

                i0 = BitConverter.ToInt16(c0, 0);
            }
            dr.Dispose();
        }
4

2 に答える 2

0

あなたが遭遇している可能性があるのは、実際にはメモベースのフィールドです...これらは、実際には生のテキストが別のファイル (通常は .DBT (dBASE) または .FPT (FoxPro)) にある列です。テキスト内のポインター オフセットです。長さが自由でブロック単位で記述されたコンテンツ ファイルですが、ポインターは 4 バイトで格納されます。

.dbf ビューアにアクセスできて、ある程度ネイティブに表示できる場合は、おそらく多少は役立つでしょう。

于 2010-05-18T17:17:02.643 に答える
0

ASCII 文字変換については、あなたが正しいと確信しています。Jet エンジンでサポートされているスカラー関数を少し探しましたが、見つけることができませんでした...というか、スカラー関数がリストされていても構文が見つかりませんでした。機能はおそらくあなたCONVERTが望むものです。何かのようなもの:

SELECT CONVERT(twobytefield, SQL_BINARY) from astm2007

dr.GetBytes()次に、生データを読み取るために呼び出すことができます。しかし、Jet エンジンが好むその関数を使用してステートメントを作成することはできませんでした。

変換がうまくいかない場合は、Advantage .NET Data Providerを使用することもできます。または、OLE DB プロバイダー (ただし、C# を使用しているため、.NET データ プロバイダーの方が適している場合があります)。そのプロバイダーは DBF ファイルを読み取り、CONVERT スカラー関数をサポートします。無料のローカルエンジンがあります。

あなたがそれを試してみると言いましたので、嘘をついていないことを確認するためにテストしたので、私が使用したコードスニペットは次のとおりです。

AdsConnection conn = new AdsConnection( 
   @"data source=c:\path;chartype=ansi;ServerType=local;TableType=cdx;" );
conn.Open();
AdsCommand cmd = conn.CreateCommand();
cmd.CommandText = "select cast(somefield as sql_binary) from sometable";
cmd.CommandType = CommandType.Text;
AdsExtendedReader rdr = cmd.ExecuteExtendedReader();
rdr.Read();
byte[] c0 = rdr.GetBytes( 0 );
int i0 = BitConverter.ToInt16( c0, 0 );
Console.WriteLine( "val = {0}", i0 );
于 2010-05-18T18:02:22.943 に答える