2010-12-13 13 views
0

ich eine binäre Datei mit folgendem Inhalt haben:Lesen variabler Größe String aus Binärdatei (VB6 vs. C#)

alt text

Der folgende Code verwendet wird, diese Inhalte in alten VB6-Programm zu lesen:

Private Type tpClient 
    Firstname As String 
    LastName As String 
    Birth As String 
    Adres As String 
    Geslacht As String 
    IDNummer As Long 
    SSNummer As String 
    DatabaseID As Long 
    Telefoon1 As String 
    Telefoon2 As String 
End Type 

Open strFilePath For Random Access Read As #intFileNumber 
Get #intFileNumber, 1, ClientData ' ClientData is of type tpClient 

Jetzt versuche ich dies mit meinem neuen C# Programm zu lesen:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public struct PatientStruct 
{ 
    [MarshalAs(UnmanagedType.BStr)] 
    public string FirstName; 

    [MarshalAs(UnmanagedType.BStr)] 
    public string LastName; 

    [MarshalAs(UnmanagedType.BStr)] 
    public string BirthDate; 

    [MarshalAs(UnmanagedType.BStr)] 
    public string Address; 

    [MarshalAs(UnmanagedType.BStr)] 
    public string Gender; 

    [MarshalAs(UnmanagedType.BStr)] 
    public string IdNumber; 

    [MarshalAs(UnmanagedType.BStr)] 
    public string SsNumber; 

    [MarshalAs(UnmanagedType.BStr)] 
    public string DatabaseId; 

    [MarshalAs(UnmanagedType.BStr)] 
    public string Telephone1; 

    [MarshalAs(UnmanagedType.BStr)] 
    public string Telephone2; 
} 

byte[] buffer = new byte[stream.Length]; 
stream.Read(buffer, 0, (int)stream.Length); 
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); 
T stuff = (PatientStruct)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); 
handle.Free(); 

Ich erhalte jedoch eine AccessViolationException beim Aufruf von Marshal.PtrToStructure.

Irgendwelche Vorschläge?

Antwort

2

Zunächst einmal sollte Ihre Struktur keine Struktur sein, sondern eine Klasse. Strukturen sind für kleine, unveränderliche Typen gedacht, die einen einzelnen Wert darstellen.

Einen Datentyp marshal genau so zu machen, wie Sie wollen, ist wirklich schwierig, und da Sie nicht interop machen, brauchen Sie gar kein Marshalling. Es ist einfacher, einfach eine BinaryReader zu verwenden, um die Daten aus der Datei zu lesen.

Die einfachen Datentypen können direkt abgelesen werden, und die Saiten können wie folgt gelesen werden:

string value = reader.ReadChars(reader.ReadShort()); 

eine entsprechende Single-Byte-Codierung angeben, wenn die Leser zu öffnen, zum Beispiel Fenster-1252.

5

Marshal.PtrToStructure erwartet die buffer voller Zeiger auf Zeichenfolgen. Ich glaube nicht, Marshal kann verwendet werden, um zu tun, was Sie wollen.

Stattdessen müssen Sie das binäre Dateiformat bestimmen und den Code dafür manuell schreiben. Werfen Sie einen Blick auf die Klasse BinaryReader.

Bearbeiten: Wenn Sie stecken bleiben, können Sie einen Verweis auf Microsoft.VisualBasic.dll hinzufügen und die FileSystem.FileGetObject Methode verwenden. Dies verhält sich genauso wie das Schlüsselwort Get in VB6.

+1

+1 für 'FileSystem.FileGetObject' Dies ist wahrscheinlich der einfachste Weg. Aus der Hilfe "Wenn die einzulesende Variable eine Zeichenfolge ist, liest FileGetObject standardmäßig einen Zwei-Byte-Deskriptor, der die Zeichenfolge enthält, und liest dann die Daten in die Variable" Die Hex-Ansicht in Ihrer Frage bestätigt, dass die Zeichenfolgen geschrieben wurden so: Länge der Zeichenkette in Bytes, dann die Zeichenkette. Die Zeichenfolgencodierung ist Ihre Windows ANSI-Codierung, wahrscheinlich Windows 1252, wenn Sie in Westeuropa ansässig sind (?) – MarkJ