You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#读取VB.NET FilePut写入的二进制文件?

解决VB.NET FilePut写入的二进制文件在C#中读取的问题

问题根源

VB.NET的FilePut和FileGet依赖固定长度字符串的ANSI编码(默认对应Windows-1252,适配德语变音字符),且严格按结构体的内存布局写入字节。之前C#读取出错的核心原因:

  • 用class而非值类型struct匹配VB的结构体
  • 字符集、结构体布局设置不匹配导致编码错误
  • 手动读取时未严格按结构体字节长度分割,导致记录数不准

正确的C#结构体定义

必须和VB.NET的结构体完全匹配,重点设置字符集、固定长度字符串和内存布局:

' VB.NET 原结构体
Public Structure MyTestStruct
    <VBFixedString(20)> Public Name As String
    Public Age As Integer
End Structure

对应C#结构体:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct MyTestStruct
{
    // 对应VB的<VBFixedString(20)>,CharSet.Ansi适配德语变音
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
    public string Name;
    public int Age;
}

实现类似VB.NET FileGet的C#方法

方法1:一次性读取所有记录(适合小文件)

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;

public static List<T> ReadAllStructs<T>(string filePath) where T : struct
{
    int structSize = Marshal.SizeOf(typeof(T));
    byte[] fileBytes = File.ReadAllBytes(filePath);

    if (fileBytes.Length % structSize != 0)
        throw new InvalidDataException("文件大小不是结构体字节数的整数倍,记录不完整");

    var result = new List<T>();
    GCHandle bufferHandle = GCHandle.Alloc(fileBytes, GCHandleType.Pinned);
    try
    {
        IntPtr basePtr = bufferHandle.AddrOfPinnedObject();
        for (int i = 0; i < fileBytes.Length / structSize; i++)
        {
            IntPtr currentPtr = IntPtr.Add(basePtr, i * structSize);
            T structObj = Marshal.PtrToStructure<T>(currentPtr);
            result.Add(structObj);
        }
    }
    finally
    {
        bufferHandle.Free();
    }
    return result;
}

方法2:流式读取(适合大文件,避免内存过载)

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;

public static IEnumerable<T> ReadStructsStream<T>(string filePath) where T : struct
{
    int structSize = Marshal.SizeOf(typeof(T));
    byte[] buffer = new byte[structSize];

    using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
    {
        int bytesRead;
        while ((bytesRead = fs.Read(buffer, 0, structSize)) > 0)
        {
            if (bytesRead != structSize)
                throw new InvalidDataException("文件结尾存在不完整记录");

            GCHandle bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            try
            {
                T structObj = Marshal.PtrToStructure<T>(bufferHandle.AddrOfPinnedObject());
                yield return structObj;
            }
            finally
            {
                bufferHandle.Free();
            }
        }
    }
}

关键注意事项

  • 必须用struct而非class:VB的结构体是值类型,C#用值类型才能匹配FilePut写入的二进制格式
  • 字符集必须设为CharSet.Ansi:确保德语变音字符(ä/ö/ü等)按Windows-1252编码解析,避免乱码
  • 严格按结构体字节长度分割文件:通过Marshal.SizeOf获取准确的结构体字节数,保证记录数计算正确

内容的提问来源于stack exchange,提问作者Cloudcuckoohome

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 09:33:12