简体   繁体   English

从二进制文件读取可变大小的字符串(VB6与C#)

[英]Read variable sized string from binary file (VB6 vs. C#)

I have a binary file with the following contents: 我有一个包含以下内容的二进制文件:

替代文字

The following code is used to read this contents in old VB6 program: 以下代码用于在旧的VB6程序中读取此内容:

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

Now I'm trying to read this with my new C# program: 现在,我尝试使用新的C#程序阅读此内容:

[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();

However, I get an AccessViolationException on the call to Marshal.PtrToStructure. 但是,我在调用Marshal.PtrToStructure时收到AccessViolationException。

Any suggestions? 有什么建议么?

Marshal.PtrToStructure is expecting the buffer to be full of pointers to strings. Marshal.PtrToStructure期望buffer充满指向字符串的指针。 I don't think Marshal can be used to do what you want. 我认为Marshal不能用来做你想做的事。

Instead, you'll need to determine the binary file format and write the code for this by hand. 相反,您需要确定二进制文件格式,并为此手工编写代码。 Take a look at the BinaryReader class. 看一下BinaryReader类。

Edit: If you're stuck, you could add a reference to Microsoft.VisualBasic.dll and use the FileSystem.FileGetObject method. 编辑:如果遇到问题,可以添加对Microsoft.VisualBasic.dll的引用,并使用FileSystem.FileGetObject方法。 This behaves the same as the Get keyword in VB6. 此行为与VB6中的Get关键字相同。

First of all, your struct should not be a struct at all, but a class. 首先,您的结构根本不应该是结构,而应该是一个类。 Structs are intended for small, immutable types that represent a single value. 结构旨在用于表示单个值的小型不变类型。

Making a data type marshal exactly as you want is really tricky, and as you are not doing interop you really don't need marshalling at all. 完全按照您的需要编组数据类型确实很棘手,而且由于您没有进行互操作,所以您实际上根本不需要编组数据。 It's easier to just use a BinaryReader to read the data from the file. 仅使用BinaryReader从文件读取数据会更容易。

The simple data types can be read straight off, and the strings can be read like this: 可以直接读取简单的数据类型,并可以像这样读取字符串:

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

Specify an appropriate single byte encoding when opening the reader, for example windows-1252. 打开阅读器时,请指定适当的单字节编码,例如Windows-1252。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM