Benutzer mit den meisten Antworten
Wie kann man eine Datei byteweise (nicht zeichenweise) lesen und schreiben?

Frage
-
Windows 7 - VisualBasic 2010 Express - Anfänger/Umsteiger von VB6, Autodidakt
Die beträchtlichen Änderungen von VB6 auf VB2010 haben den Aufruf und das Öffnen von Dateien sehr vereinfacht. Ich finde aber keine Anweisungen mehr zum byteweisen Lesen und Schreiben einer Datei.
Was habe ich:
- Eine ganze Datei (Textdatei in Codierung Cp 1252 oder Unicode mit Kennung) lese ich auf einmal (hier in die TextBox1) mit
Dim lese1 As New System.IO.StreamReader(OpenFileDialog1.FileName, System.Text.Encoding.Default)
TextBox1.Text = lese1.ReadToEnd
- Eine ganze Datei (Textdatei in Codierung Cp 1252 oder Unicode mit Kennung) lese ich zeilenweise (hier in die TextBox1) mit
Dim lese2 As New System.IO.StreamReader(OpenFileDialog1.FileName, System.Text.Encoding.Default)
Dim z As String
Do Until lese2.Peek() = -1
z = lese2.ReadLine()
TextBox1.Text = TextBox1.Text & z & vbCrLf
Loop
- Eine ganze Datei (Textdatei in Codierung Cp 1252 oder Unicode mit Kennung) lese ich zeichenweise (hier in die TextBox1) mit
Dim lese3 As New System.IO.StreamReader(OpenFileDialog1.FileName, System.Text.Encoding.Default)
Dim y As Integer
Do Until lese3.Peek() = -1
y = lese3.Read
TextBox1.Text = TextBox1.Text & ChrW(y) & vbCrLf
Loop
Was möchte ich:
Eine ganze Datei (ohne Rücksicht auf ihre Codierung, also eine 'Binärdatei') byteweise (nicht zeichenweise!) lesen (und später schreiben). Natürlich soll sie nicht wie in den obigen Beispielen in eine TextBox gelesen, sondern sofort bearbeitet werden. Unter VB6 konnte ich das mit GET und PUT machen. In VB10 finde ich keine passende Anweisungen.
Ich bitte um Nachsicht für die langatmige Darstellung und danke für jede Anregung.
Werner314
Antworten
-
Hallo Werner,
Kern für Datenzugriffe ist ein Stream, womit die grundlegenden Operationen definiert werden,
die dort immer auf Byte-Ebene üblicherweise über ein Byte-Array erfolgen.Für Dateien ist die stellt die FileStream Klasse die Implementiert für einen Stream bereit.
Alle Streams können über einen BinaryReader bzw. BinaryWriter binär verarbeitet werden.
Die Klassen stellen dabei den Zugriff für die primitiven Datentypen (wie Integer, Double usw.) bereit.StreamReader und StreamWriter wiederum sind Klassen für textbasierten Zugriff,
basierend auf den abstrakten TextReader- und TextWriter-Klassen,
d. h. sie interpretieren die Bytes in einem Stream anhand des Encodings -
.NET arbeitet im Standard mit UTF8-Kodierung.Bei der Verarbeitung sollte man grundsätzlich beachten, die Datei nach dem Zugriff zu schliessen.
Damit das auch im Falle eines Fehlers passiert, empfiehlt sich der Einsatz der using Anweisung.
Exemplarisch für Dein erstes Beispiel:Using lese1 As New System.IO.StreamReader(OpenFileDialog1.FileName, System.Text.Encoding.Default) TextBox1.Text = lese1.ReadToEnd() End Using
Für mehr schau Dir mal an: Grundlegende Datei-E/A.
Gruß Elmar
P. S.: Allgemeine Fragen zu Visual Basic sind im Visual Basic .NET Forum besser aufgehoben.
- Als Antwort vorgeschlagen Stefan FalzModerator Dienstag, 26. Juli 2011 15:40
- Als Antwort markiert Robert BreitenhoferModerator Mittwoch, 3. August 2011 06:16
-
Hallo Werner,
sobald Du einen StreamReader verwendest, wird die Datei als Textdatei behandelt -
StreamReader ist von TextReader abgeleitet, was den Zusammenhang deutlich machen sollte.Und Text sind keine Bytes mehr, zumindest bei den komplexeren Zeichensätzen wie UTF-8
wo ein Zeichen ein bis vier Bytes beanspruchen kann.
Die vom StreamReader in Unicode (UCS-2) umgewandelt werden, womit .NET intern arbeitet.Würde man da einfach ein Byte zwischen weglesen, gibt es Zeichensalat -
und so ist aus gutem Grund ReadByte nicht mehr (direkt) erreichbar.Nackte Bytes kannst Du bereits mit dem FileStream selbst lesen.
Der BinaryReader/-Writer erweitert den Stream, und ermöglicht die primitiven Datentypen sauber zu verarbeiten -
denn auch da kann es durch die Byte-Reihenfolge (Endianess) ansonsten Probleme geben.Ein sehr einfaches Beispiel:
Option Explicit On Option Infer On Option Strict On Imports System.Diagnostics Imports System.IO Class BinaryFile ' Dateiname für das Beispiel, entsprechend anpassen Const DateiName As String = "C:\TEMP\Datei.dat" ' ABCDEabcde Private Shared ReadOnly TestDaten As Byte() = {&H41, &H42, &H43, &H44, &H45, &H61, &H62, &H63, &H64, &H65} Friend Shared Sub BinärSchreibenUndLesen() Using writer As New BinaryWriter(New FileStream(DateiName, FileMode.Create, FileAccess.Write, FileShare.None)) ' Länge schreiben writer.Write(TestDaten.Length) ' Byte für Byte schreiben For index = 0 To TestDaten.Length - 1 writer.Write(TestDaten(index)) Next ' Effizienter wäre 'writer.Write(TestDaten) End Using ' Lesen der geschriebenen Daten Dim daten As Byte() Using reader As New BinaryReader(New FileStream(DateiName, FileMode.Open, FileAccess.Read, FileShare.Read)) ' Länge lesen Dim length = reader.ReadInt32() ' Dimensionieren daten = New Byte(length - 1) {} ' Byteweise Lesen For index = 0 To length - 1 daten(index) = reader.ReadByte() Next ' Effizienter wäre ' Dim daten = reader.ReadBytes(length) End Using ' Gelesene Daten vergleichen Debug.Assert(TestDaten.Length = daten.Length, "Länge abweichend") For index = 0 To TestDaten.Length - 1 Debug.Assert(TestDaten(index) = daten(index), "Byte abweichend an " & index.ToString()) Next End Sub End Class
was Du als eine neue Klasse einfügen kannst und in einem Windows Forms Projekt
über einen Button starten kannst mit:Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click BinaryFile.BinärSchreibenUndLesen() End Sub
Zu den MSDN Beispielen:
Die Beispiele sind zwar häufig als Konsolenprojekte konzipiert - die man mit Visual Basic ebenso erstellen kann.
Wenn Du sie aber lieber in einem Windows Form Projekt haben möchtest, so reicht es im allgemeinen
den Abschnitt aus Sub Main() in eine Shared Sub mit anderem Namen zu übertragen und zugehörige Klassen ebenso.
Die Main Prozedur ist reserviert als Einstiegspunkt und sollte nur einmalig im Projekt vorkommen.Gruß Elmar
- Als Antwort vorgeschlagen Stefan FalzModerator Sonntag, 31. Juli 2011 16:24
- Als Antwort markiert Robert BreitenhoferModerator Mittwoch, 3. August 2011 06:16
Alle Antworten
-
-
Hallo Werner,
Kern für Datenzugriffe ist ein Stream, womit die grundlegenden Operationen definiert werden,
die dort immer auf Byte-Ebene üblicherweise über ein Byte-Array erfolgen.Für Dateien ist die stellt die FileStream Klasse die Implementiert für einen Stream bereit.
Alle Streams können über einen BinaryReader bzw. BinaryWriter binär verarbeitet werden.
Die Klassen stellen dabei den Zugriff für die primitiven Datentypen (wie Integer, Double usw.) bereit.StreamReader und StreamWriter wiederum sind Klassen für textbasierten Zugriff,
basierend auf den abstrakten TextReader- und TextWriter-Klassen,
d. h. sie interpretieren die Bytes in einem Stream anhand des Encodings -
.NET arbeitet im Standard mit UTF8-Kodierung.Bei der Verarbeitung sollte man grundsätzlich beachten, die Datei nach dem Zugriff zu schliessen.
Damit das auch im Falle eines Fehlers passiert, empfiehlt sich der Einsatz der using Anweisung.
Exemplarisch für Dein erstes Beispiel:Using lese1 As New System.IO.StreamReader(OpenFileDialog1.FileName, System.Text.Encoding.Default) TextBox1.Text = lese1.ReadToEnd() End Using
Für mehr schau Dir mal an: Grundlegende Datei-E/A.
Gruß Elmar
P. S.: Allgemeine Fragen zu Visual Basic sind im Visual Basic .NET Forum besser aufgehoben.
- Als Antwort vorgeschlagen Stefan FalzModerator Dienstag, 26. Juli 2011 15:40
- Als Antwort markiert Robert BreitenhoferModerator Mittwoch, 3. August 2011 06:16
-
Vielen Dank für die freundlichen Antworten. Unmittelbar gehelfen haben sie mir leider nicht. Aber das liegt an mir. Ich muss offensichtlich noch viel lernen, was die Strukturen von VB10 betrifft.
Immerhin hatte ich verstanden und einrichten können, dass das Lesen einer Datei möglich ist mithilfe von
System.IO.StreamReader(OpenFileDialog1.FileName)
Dabei wird sie mit
.ReadToEnd
am Stück (als UTF-8-codiert) gelesen, mit
.ReadLine
zeilenweise (als UTF-8-codiert) gelesen und mit
.Read
zeichenweise (als UTF-8-codiert) gelesen.
Was liegt näher, als das byteweise Lesen zu versuchen mit
.ReadByte
Aber: '"ReadByte" ist kein Member von "System.IO.StringReader".'
Anstelle von 'StreamReader' 'BinaryReader' zu verwenden scheint mir nicht logisch, denn ich will ja den 'Datenstrom' einer Datei lesen, wenn auch byteweise. Trotzdem probiert, aber unter Verwendung von
System.IO.BinaryReader(OpenFileDialog1.FileName)
bekomme ich dann die Meldung: 'Der Wert vom Typ "String" kann nicht in "System.IO.Stream" konvertiert werden.' Das ist für mich unverständlich.
Die Beispiele in MSDN helfen mir oft deshalb nicht weiter, weil sie für Console eingerichtet sind und och damit (noch) nicht arbeiten kann.
Dank und freundliche Grüße
Werner314
-
Hallo Werner,
sobald Du einen StreamReader verwendest, wird die Datei als Textdatei behandelt -
StreamReader ist von TextReader abgeleitet, was den Zusammenhang deutlich machen sollte.Und Text sind keine Bytes mehr, zumindest bei den komplexeren Zeichensätzen wie UTF-8
wo ein Zeichen ein bis vier Bytes beanspruchen kann.
Die vom StreamReader in Unicode (UCS-2) umgewandelt werden, womit .NET intern arbeitet.Würde man da einfach ein Byte zwischen weglesen, gibt es Zeichensalat -
und so ist aus gutem Grund ReadByte nicht mehr (direkt) erreichbar.Nackte Bytes kannst Du bereits mit dem FileStream selbst lesen.
Der BinaryReader/-Writer erweitert den Stream, und ermöglicht die primitiven Datentypen sauber zu verarbeiten -
denn auch da kann es durch die Byte-Reihenfolge (Endianess) ansonsten Probleme geben.Ein sehr einfaches Beispiel:
Option Explicit On Option Infer On Option Strict On Imports System.Diagnostics Imports System.IO Class BinaryFile ' Dateiname für das Beispiel, entsprechend anpassen Const DateiName As String = "C:\TEMP\Datei.dat" ' ABCDEabcde Private Shared ReadOnly TestDaten As Byte() = {&H41, &H42, &H43, &H44, &H45, &H61, &H62, &H63, &H64, &H65} Friend Shared Sub BinärSchreibenUndLesen() Using writer As New BinaryWriter(New FileStream(DateiName, FileMode.Create, FileAccess.Write, FileShare.None)) ' Länge schreiben writer.Write(TestDaten.Length) ' Byte für Byte schreiben For index = 0 To TestDaten.Length - 1 writer.Write(TestDaten(index)) Next ' Effizienter wäre 'writer.Write(TestDaten) End Using ' Lesen der geschriebenen Daten Dim daten As Byte() Using reader As New BinaryReader(New FileStream(DateiName, FileMode.Open, FileAccess.Read, FileShare.Read)) ' Länge lesen Dim length = reader.ReadInt32() ' Dimensionieren daten = New Byte(length - 1) {} ' Byteweise Lesen For index = 0 To length - 1 daten(index) = reader.ReadByte() Next ' Effizienter wäre ' Dim daten = reader.ReadBytes(length) End Using ' Gelesene Daten vergleichen Debug.Assert(TestDaten.Length = daten.Length, "Länge abweichend") For index = 0 To TestDaten.Length - 1 Debug.Assert(TestDaten(index) = daten(index), "Byte abweichend an " & index.ToString()) Next End Sub End Class
was Du als eine neue Klasse einfügen kannst und in einem Windows Forms Projekt
über einen Button starten kannst mit:Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click BinaryFile.BinärSchreibenUndLesen() End Sub
Zu den MSDN Beispielen:
Die Beispiele sind zwar häufig als Konsolenprojekte konzipiert - die man mit Visual Basic ebenso erstellen kann.
Wenn Du sie aber lieber in einem Windows Form Projekt haben möchtest, so reicht es im allgemeinen
den Abschnitt aus Sub Main() in eine Shared Sub mit anderem Namen zu übertragen und zugehörige Klassen ebenso.
Die Main Prozedur ist reserviert als Einstiegspunkt und sollte nur einmalig im Projekt vorkommen.Gruß Elmar
- Als Antwort vorgeschlagen Stefan FalzModerator Sonntag, 31. Juli 2011 16:24
- Als Antwort markiert Robert BreitenhoferModerator Mittwoch, 3. August 2011 06:16