2017-08-08 24 views
-3

誰かがdBaseの.DBF/.DBTファイルセットから直接データを読み取る方法を知っていますか?dbf/dbtファイルを直接読み取る方法は?

詳細:

私はDBF/DBTファイルのためのdBaseの仕様に応じてパーサを記述しようとしています。

DBFファイルは比較的簡単です。メモフィールドの値は、そのフィールドのデータがdbtファイルで開始されるシーケンシャルブロック番号です。

DBTファイルは仕様に深く定義されていません。 DBTファイルを解析すると(ブロックサイズが512バイトのシーケンシャルブロックで、ヘッダブロックである)、レコードデータの間に散在する余分なバイトデータが見えます(「ガベージ」バイナリデータ、db内の他のテーブル名のように見えます)。余分なデータの一部に文字/数字が含まれていると、不可能に近いブロックのレコードデータだけを読み込もうとします。私が見ることのできる仕様には、これらの奇妙なデータの明確な定義はありません。私はそれが何らかのヘッダーデータかもしれないと仮定しますが、固定バイト幅を持たないか、各ブロックの同じ位置に現れるように見えません。

また、DBFファイルのメモフィールドの連続ブロック番号は、実際のデータと常に一致するとは限りません。私。 dbfのレコード2は、ブロック2で始まりますが、dbtファイルではブロック6で始まります。

DBTファイルの構造に関する詳しい情報は誰にも分かりますか?多分、私は行方不明の何か?あなたは、たとえば、OLEDBを使用する必要が

' Holds information about data in the header .dbf file. 
Public Class HeaderFileClass 
    Public Property AccountNo As String  ' 6 bytes 
    Public Property BlockNumber As String '10 bytes 
    Public Property DateInfo As String  '8 bytes 
    Public Property EditBy As String  '3 bytes 
    Public Sub New() 
     AccountNo = String.Empty 
     BlockNumber = String.Empty 
     DateInfo = String.Empty 
     EditBy = String.Empty 
    End Sub 
    Public Sub New(newAcctNo As String, newBlockNo As String, newDateInf As String, newEditBy As String) 
     AccountNo = newAcctNo 
     BlockNumber = newBlockNo 
     DateInfo = newDateInf 
     EditBy = newEditBy 
    End Sub 
End Class 
' Strips a byte array of anything but alpha-numerics, space, or line feed. 
Private Function CleanBytes(ByRef bytes As Byte()) As Byte() 
    Dim newBytes As Byte() 
    Dim BLOCKSIZE As Integer = 512 
    Dim j As Integer = 0 
    Dim strOut As String = String.Empty 
    ReDim newBytes(BLOCKSIZE) 
    newBytes.Initialize() 
    For Each i As Byte In bytes 
     Dim intVal As Integer = Convert.ToInt32(i) 
     If (intVal >= 32 And intVal <= 126) Or intVal = 10 Then 
      newBytes(j) = i 
      j += 1 
     End If 
    Next 
    Return newBytes 
End Function 
Private Sub ParseFile() 
    Dim fileName As String = "C:\dbbackup\Schalls\Schalls_CleanLegacy\Schall_Clean_DATA\PATNOTES"  ' data location. 
    Dim BLOCKSIZE As Integer = 512     ' Default block size. 
    Dim bytes As Byte() = Nothing     ' bytes to be read from dbt file. 
    Dim buffer As Char()       ' buffer to use for reading dbf file. 
    Dim hList As New List(Of HeaderFileClass)  ' DBF header data storage. 
    Dim lstData As New List(Of Byte())    ' DBT block data storage. 
    ReDim buffer(28)        ' Set size of buffer array. 

    'header file load 
    Using inFile As New StreamReader(File.Open(fileName & ".DBF", FileMode.Open)) 
     ' read DBF header lines. 
     inFile.ReadLine() 
     inFile.ReadLine() 

     ' read DBF data. 
     While inFile.Read(buffer, 0, 28) > 0 
      Dim strBuf As New String(buffer) 
      Dim acctNo As String = strBuf.Substring(0, 7) 
      Dim blockNo As String = strBuf.Substring(7, 10).Trim 
      Dim dateInfo As String = strBuf.Substring(17, 8) 
      Dim editBy As String = strBuf.Substring(25, 3) 
      hList.Add(New HeaderFileClass(acctNo, blockNo, dateInfo, editBy)) 
     End While 
    End Using 


    'memo file load 
    Using inFile As New BinaryReader(File.Open(fileName & ".DBT", FileMode.Open)) 
     ' read data sequentially by blocksize. 
     Do 
      bytes = inFile.ReadBytes(BLOCKSIZE) 
      If bytes.Length > 0 Then 
       lstData.Add(bytes) 
      End If 
     Loop While bytes.Length > 0 
    End Using 

    If hList.Count > 2 Then 
     For i As Integer = 0 To hList.Count - 2 
      Dim h As HeaderFileClass = hList(i)    ' get data for the current record from the header file data. (contains block number to start) 
      Dim h2 As HeaderFileClass = hList(i + 1)  ' get the next data for the current record. (contains next starting block number) 
      Dim intFrom As Integer = CInt(h.BlockNumber) ' starting block number. 
      Dim intTo As Integer = CInt(h2.BlockNumber)  ' next record's starting block number. 
      Dim sbStr As New System.Text.StringBuilder  ' output string. 

      ' read the bytes, ensure they are text data, 
      For j As Integer = intFrom To intTo - 1 
       sbStr.Append(System.Text.Encoding.ASCII.GetString(CleanBytes(lstData(j)))) 
      Next 
      Debug.Print(sbStr.ToString) 
     Next 
    End If 
End Sub 
+1

あなたが任意のコードを書いていますか?問題のあるコードを投稿してください。 –

+0

私は約30分で私の仕事のコンピュータに着くとすぐにコードを掲載します。 –

+0

質問を投稿する前にこれを読んでください。http://www.dbase.com/Knowledgebase/INT/db7_file_fmt.htm – i486

答えて

0

コード例(VB.Net)

Imports System.Data.OleDb 
Public Class Form1 
    Private FileName As String = IO.Path.Combine(Application.StartupPath, "Customer.dbf") 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
     If IO.File.Exists(FileName) Then 
      Dim Builder As New OleDbConnectionStringBuilder With 
       { 
        .DataSource = IO.Path.GetDirectoryName(FileName), 
        .Provider = "Microsoft.Jet.OLEDB.4.0" 
       } 
      Builder.Add("Extended Properties", "dBase III") 
      Using cn As New OleDb.OleDbConnection With {.ConnectionString = Builder.ConnectionString} 
       Using cmd As New OleDbCommand With {.Connection = cn} 
        cmd.CommandText = "SELECT * FROM " & IO.Path.GetFileName(FileName) 
        cn.Open() 
        Dim dt As New DataTable 
        dt.Load(cmd.ExecuteReader) 
       End Using 
      End Using 
     End If 
    End Sub 
End Class 
関連する問題