Binär Dateien einlesen

Hallo Wissende,
das ist schon ewig=immer einer meiner größten Schwachpunkte.

Textdateien sind kein Problem, die lese ich mit Line Input oder Input aus und beschreibe sie mit Print.

Aber, was ich noch nie ohne Hilfe hinbrachte ist, wie lese ich eine Datei ein die Bytes von 0-255 in sich hat.

rtfm triffts in dem Fall nicht. Ich habe dazu alles gelesen was mir unter die Finger kam, habe aber keinen Plan.

Deshalb meine Bitte, kann mir hier jmd. Code posten , VB, VBA, der eine Datei einliest in eine Variable, a) auf einen Rutsch b) wenn die Datei zu groß ist in mehreren Schüben.

Also sowas
(???= Binary,Random,sonstwas)

Open „C:\Test\meineDatei.bmp“ for ??? As #1 Len=filelen(„C:\Test\meineDatei.bmp“)
Get #1,Satz
close
msgbox Satz

Open „C:\Test\meineDatei.bmp“ for ??? As #1 Len=50000
while not eof(1)
Get #1,Satz
S=S & Satz
wend
msgbox S

Und, auch mit dem Put habe ich Probleme. Ich schaffte es schon eine Datei einzulesen, dann mit Put usw. in eine andere Datei zu schreiben, leider war die vielfach größer:frowning:
Dann las ich irgendwo dass Put immer 2 Bytes mehr schreibt…

Wie ersichtlich habe ich Null Plan was da zu tun ist.

Freue mich über jede Hilfe.

Danke ^ Gruß
Reinhard

Hallo Reinhard,

ist es das was du suchst?

Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" Alias \_
 "RtlMoveMemory" (lpTo As Any, lpFrom As Any, \_
 ByVal lLen As Long)

Dim B() As Byte


Private Sub Command1\_Click()
Dim aa$, l&
Open "DeinFile" For Binary As #1
aa = Input(LOF(1), #1)
Close #1
 l = Len(aa) - 1
 ReDim B(0 To l)
 Call CopyMemory(B(0), ByVal aa, l + 1)
End Sub

Was verstehst du denn nicht an der PUT Anweisung?

MfG Alex

Hallo Alex,

Option Explicit

Private Declare Sub CopyMemory Lib „kernel32“ Alias _
„RtlMoveMemory“ (lpTo As Any, lpFrom As Any, _
ByVal lLen As Long)

Dim B() As Byte

Private Sub Command1_Click()
Dim aa$, l&
Open „DeinFile“ For Binary As #1
aa = Input(LOF(1), #1)
Close #1
l = Len(aa) - 1
ReDim B(0 To l)
Call CopyMemory(B(0), ByVal aa, l + 1)
End Sub

ich kannte Input nur in Verbindung zum Auslesen von reinen Textdateien.
Scheinbar kann es mehr.

Deine Variante speichere ich mir ab, mit dem API-Aufruf.

Aber wie geht es ohne API, nur mit Open und Get eine beeliebige Datei einzulesen, mal komplett auf einen Streich, wenn es da Größenbegrenzungen von 64KB o.ä. gibt, halt in mehreren Schüben und drittens Byteweise?

Was verstehst du denn nicht an der PUT Anweisung?

Nach einigen Versuchen gelang es mir dann doch mittels Open und Get eine Datei Byteweise (Len=1) einzulesen.
Warum „hinten“ eine 0 angehängt ist, so wie bei dir, ist mir schleierhaft, aber nicht so wichtig, kann man ja korrigieren mit z.B.
l = Len(aa) - 1

Tja, dann versuchte ich die in einer Variablen gespeicherten Bytes wieder in eine neue Datei mittels Put zu schreiben, wiederum Byteweise, nur hat dann dieses Put immer mehr Bytes geschrieben.
Irgednwo habe ich gelesen, Put schreibt immer 2 Bytes mehr als das was es schreiben soll.
Je nachdem wie ich das Put einsetzte hatte ich dann in der neuen Datei 2-5mal soviel Bytes wie in der ausgelesenen Datei.

Mein Weihnachtswunsch heuer wären 6 Codeschnipsel (ohne API).
Jeweils 3 für Lesen und Schreiben in/aus einer) Datei, die Varianten:

  • Byteweise
  • bestimmte Anzahl von Bytes(Problem: ich lese/schreibe in z.B. 64KB-Blöcken, wie ist es dann mit den RestBytes?)
  • Alles auf Einmal.

Danke ^ Gruß
Reinhard

Hallo Reinhard,

ich kannte Input nur in Verbindung zum Auslesen von reinen
Textdateien.
Scheinbar kann es mehr.

Jups kann es auch *zwinker* Aber wie sagt man immer ? Man lernt nie aus :smile:

Aber wie geht es ohne API, nur mit Open und Get eine
beeliebige Datei einzulesen, mal komplett auf einen Streich,
wenn es da Größenbegrenzungen von 64KB o.ä. gibt, halt in
mehreren Schüben und drittens Byteweise?

Eine Grössenbegrenzung gibt es soweit ich weiss nicht direkt. Wie du siehst werden die Daten ja erst in einen String gespeichert. Soweit ich weiss kann VB Strings verwalten bis zu 2 GB! Bin mir da aber net sicher. Sprich da waere ja dann eine Begrenzung von 2 GB :smile:
Aber mal ehrlich 2 GB mit einem Rutsch einlesen? Oje, das macht man nicht :wink:
Ich selbst nehme lieber die Variante mit dem API Aufruf. Natuerlich geht das auch ohne API’s :smile: Wie das zeige ich dir weiter unten :smile:

Nach einigen Versuchen gelang es mir dann doch mittels Open
und Get eine Datei Byteweise (Len=1) einzulesen.
Warum „hinten“ eine 0 angehängt ist, so wie bei dir, ist mir
schleierhaft, aber nicht so wichtig, kann man ja korrigieren
mit z.B.
l = Len(aa) - 1

Du meinst bei dem API Aufruf?
Das hat folgende bewandnis. das niedrigste Array unter VB beginnt bei 0! Es seidenn man verwendet Option Base 1. Aber das fuehrt nur irre.
Lof(FileNr) oder len(xyz) gibt dir die Laenge zurueck. Hast du zum bsp. 18 Zeichen geschrieben, so sind das 18 Byte und die laenge ergo auch 18! Da das Array aber nun bei 0 beginnt, brauchen wir die Dimensionen 0 bis 17! Deswegen das -1 :smile:
Wenn dann die API aufgerufen wird, siehst du ja das wir dort wieder 1 aufaddieren :smile:

Tja, dann versuchte ich die in einer Variablen gespeicherten
Bytes wieder in eine neue Datei mittels Put zu schreiben,
wiederum Byteweise, nur hat dann dieses Put immer mehr Bytes
geschrieben.

Hmm, wenn man den Quelltext sehen würde koennte ich dir sicherlich sagen, woran es liegt. Bei dem was ich dir mal getippselt habe, stimmt alles. Also die groesse vom Ursprungsfile und dem Endfile :smile:
Egal wie du die Daten ausliesst!

Irgednwo habe ich gelesen, Put schreibt immer 2 Bytes mehr als
das was es schreiben soll.

Hmm, das waere mir neu :s
Ich selbst habe das Phaenomaen noch nicht erlebt :s
Bei welchen Daten handelt es sich denn? Zeichen, Zahlen etc ?

Du darfst auch nicht verwechseln. PUT und GET kannst du einmal zum binaeren einlesen / schreiben nutzen und auch zum lesen und schreiben von Typen! Ich habe mich aber mal nur auf das Binary bezogen!

Je nachdem wie ich das Put einsetzte hatte ich dann in der
neuen Datei 2-5mal soviel Bytes wie in der ausgelesenen Datei.

Hmm, das Phaenomaen kann ich net nachvollziehen :s
Kannst du mal ein Demo posten?

Mein Weihnachtswunsch heuer wären 6 Codeschnipsel (ohne API).
Jeweils 3 für Lesen und Schreiben in/aus einer) Datei, die
Varianten:

  • Byteweise
  • bestimmte Anzahl von Bytes(Problem: ich lese/schreibe in
    z.B. 64KB-Blöcken, wie ist es dann mit den RestBytes?)
  • Alles auf Einmal.

Dürfen es auch mehr sein :smiley:
Ich hab dir mal fix nen paar Subs getippselt. Teste sie mal aus.
Wenn du dann noch fragen hast, dann einfach her damit!
File Handling ist sehr umfangreich und alles dazu habe ich sicherlich net bedacht!

Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpTo As Any, lpFrom As Any, ByVal lLen As Long)

Dim b() As Byte
Dim Data As String 'Daten die gelesen wurden!

Const readFile As String = "f:\Alex.txt" 'File was gelesen wird
Const WriteFile As String = "f:\Alex1.txt" 'File was geschrieben wird

Private Sub StringToByte(vData As String)
Dim L As Long
 L = Len(vData) - 1 'Weil das Array B bei 0 beginnt!
 ReDim b(0 To L) 'Array erstellen o bis Laenge -1!
 Call CopyMemory(b(0), ByVal vData, L + 1) 'L+1 weil wir vorhins von der Länge 1 abgezogen haben!
End Sub

Private Sub ReadFileComplete() 'Liest ein File Komplett ein
 Data = ""
 Open readFile For Binary As #1
 Data = Space$(LOF(1))
 Get #1, , Data
 Close #1
End Sub

Private Sub ReadFileBlock(Blocksize As Long, Pos As Long) 'Liest einen bestimmten Block ein
 'Blocksize = grösse der daten die gelesen werden sollen
 'Pos = Ab welcher Position sollen die Daten gelesen werden
 Open readFile For Binary As #1
 'Ein paar Überprüfungen
 If Blocksize \> LOF(1) Then Blocksize = LOF(1)
 If Pos = 0 Then Pos = 1
 If Pos + Blocksize \> LOF(1) Then Blocksize = LOF(1) - Pos + 1
 Data = Space$(Blocksize)
 Get #1, Pos, Data
 Close #1
End Sub

Private Sub ReadFileByte(Pos As Long)
 'Pos = Ab welcher Position soll das Byte gelesen werden
 Open readFile For Binary As #1
 'Ein paar Überprüfungen
 If Pos = 0 Then Pos = 1
 If Pos \> LOF(1) Then Pos = LOF(1)
 Data = Space$(1)
 Get #1, Pos, Data
 Close #1
 StringToByte Data
End Sub

Private Sub WriteFileComplete() 'Schreibt das File Komplett
 If Dir(WriteFile) "" Then Kill WriteFile
 Open WriteFile For Binary As #2
 Put #2, , Data
 Close #2
End Sub

Private Sub WriteFileExistBlock(Pos As Long) 'Schreibt einen Block in die Datei
Dim p As Long
'Schreibst du nicht ans Dateiende, so werden vorhandene Daten ueberschrieben!
 Open WriteFile For Binary As #2
 Select Case Pos
 Case -1
 'Ans Ende schreiben
 p = LOF(2) + 1
 Case -2
 'Am Anfang schreiben
 p = 1
 Case Else
 'an die gegebene Position
 p = Pos
 If p \> LOF(2) Then p = LOF(2) + 1
 End Select
 Put #2, p, Data
 Close #2
End Sub

Private Sub WriteFileBlock() 'Schreibt einen Block in eine Datei
 If Dir(WriteFile) "" Then Kill WriteFile
 Open WriteFile For Binary As #2
 Put #2, LOF(2) + 1, Data
 Close #2
End Sub

Public Sub WriteFileByte(b As Byte) 'Schreibt ein Byte in die Datei
 If Dir(WriteFile) "" Then Kill WriteFile
 Open WriteFile For Binary As #2
 Put #2, , b
 Close #2
 'Dateigrösse = 1 Byte!
End Sub

Public Sub WriteFileManyByte() 'Schreibt einige Bytes in die Datei
 'Wir nehmen das komplette Array b zum schreiben, welches wir vorher über redim preserve kuerzen :wink:
 'Übergibst du hier die kompletten Bytes als Array, was in B steht, so werden alle Bytes mit einmal geschrieben!
 If Dir(WriteFile) "" Then Kill WriteFile
 Open WriteFile For Binary As #2
 Put #2, , b
 Close #2
 'Ubound(b)=13 -\> 14 Bytes vorhanden
 'Geschrieben im File 14 Bytes
 'Dateigrösse 14 Bytes!
End Sub

Private Sub WriteFileBlockComplete(NeuesFile As Boolean) 'Schreibt das File Blockweise Komplett
Dim p As Long
'NeuesFile=true -\> Es wird eine neue Datei angelegt, ansonsten werden die Blöcke hinten dran gehangen
 If NeuesFile Then If Dir(WriteFile) "" Then Kill WriteFile
 Open WriteFile For Binary As #2
 p = LOF(2) + 1
 Put #2, p, Data
 Close #2
End Sub

Private Sub ReadFileASByteComplete() 'File wird komplet als Byt eingelesen, ohne API Aufruf :smile:
Dim c() As Byte
Open readFile For Binary As #1
If LOF(1) = 0 Then Exit Sub
ReDim c(LOF(1))
Get #1, 1, c
Close #1
End Sub

Private Sub Command1\_Click()
 ReadFileASByteComplete
End Sub

Danke ^ Gruß

Nichts zu danken :smile:

Reinhard

Alex

Hallo Reinhard,

anbei noch fix ne Routine ( leider mit API *zwinker*) die ein File DOS oder halt WIN Kombatibel macht! Du weisst ja, das man da die Zeichensaetze beachten sollte :smile:

Option explicit

Private Declare Function OemToCharA Lib "user32" ( \_
 ByVal lpszSrc As String, ByVal lpszDst As String) As Long
Private Declare Function CharToOemA Lib "user32" ( \_
 ByVal lpszSrc As String, ByVal lpszDst As String) As Long

Sub ConvertFile( \_
 ByRef Path As String, \_
 Optional ByVal AsWin As Boolean = True \_
 )
 Dim hFile As Long
 Dim sOrg As String
 Dim sConv As String
 Dim nPos As Long

 'Blockweise konvertieren:
 sOrg = Space$(4096)
 sConv = sOrg
 hFile = FreeFile
 Open Path For Binary As #hFile
 For nPos = 1 To LOF(hFile) Step Len(sOrg)
 If nPos \> LOF(hFile) - Len(sOrg) Then
 'Restblock-Größe bestimmen:
 sOrg = Space$(LOF(hFile) - nPos + 1)
 sConv = sOrg
 End If
 Get #hFile, , sOrg
 If AsWin Then
 'DOS -\> Windows:
 OemToCharA sOrg, sConv
 Else
 'Windows -\> DOS:
 CharToOemA sOrg, sConv
 End If
 If sOrg sConv Then Put #hFile, nPos, sConv
 Next nPos
 Close #hFile
End Sub

MfG Alex

OT Zwischenrückmeldung
Hallo Alex,

ich bin noch am rumtesten mit Input, Get, Put usw. und da fliesst die Zeit weg weg wenn ich das teste mit verschiedenen Dateiöffnungsmodi usw.
Deshalb habe ich mich noch nicht mit deinen Codes beschäftigt.
Aber das kommt.
Danke erstmal für deine Mühen:smile:
Gruß
Reinhard

Hallo Alex,

Hallo Reinhard,

das macht ja nichts :smile: Ich bin gerade dabei umzusteigen auf VB .NET und da habsch genug zu tun, somal da sehr sehr viel anders ist, aber auch erheblich einfacher :wink:
Zur Zeit binsch dabei nen paar Handbuecher auszudrucken ( ist besser als die PDF Documente. Nur sind das was ich derzeit drucke knapp 1050 Seiten :s. Du kennst nicht eine Adresse, wo man sich Ebook, speziell dem Datenbank Handling laden kann?

MfG Alex

Zur Zeit binsch dabei nen paar Handbuecher auszudrucken ( ist
besser als die PDF Documente. Nur sind das was ich derzeit
drucke knapp 1050 Seiten :s. Du kennst nicht eine Adresse, wo
man sich Ebook, speziell dem Datenbank Handling laden kann?

Hallo Alex,
Ebooks,rss-feed, alles neumodischer Kram, keine Ahnung davon.
Gruß
Reinhard