石岩Maple 2024-11-11 09:15 采纳率: 25%
浏览 18
已结题

VB6可以成功读取的文件,用C#读不了

VB6代码

Option Explicit
Public Type TypeResult
    KensaDate(1 To 2)           As Date
    RecipeNo                    As Integer
    RecipeName  As String
    GlassCF As String
    GLASSTFT As String
    
    VASNo As Byte
    VASX As Single
    VASY As Single
    VASC As Single
    
    Paneljieguo(1 To 50, 1 To 4, 1 To 2) As String    '50个单元,每个单元4个点位,1=X,2=Y
    YouxiaoMarkCnt As Integer
End Type
Public HistoryResult       As TypeResult   '20240104

Option Explicit

Private Sub Command1_Click()
    Dim fno     As Integer
    Dim ret&
    Dim fs

    Dim vFileName As String
    vFileName = "D:/HistoryData/Result/20241029/R0000000100"
    ret = 0
    Set fs = CreateObject("Scripting.FileSystemObject")
    If fs.FileExists(vFileName) = False Then
        ret = -1
    Else
        fno = FreeFile
        Open vFileName For Binary Access Read As fno
        Get fno, , HistoryResult
        Close fno
    End If
End Sub

这段VB6代码执行后,HistoryResult的值都是正确的,但是转成C#代码后却无法获取到正确的值,并且C#获取到的值是乱码,请问C#应该怎么写?

  • 写回答

28条回答 默认 最新

  • 专家-司宇[在线] 2024-11-11 09:16
    关注

    参考免费微信小程序:皆我百晓生 作答,经由专家-司宇整理回复,如问题解决,望采纳;如仍有疑问,请评论回复。

    理解了你的问题,从VB6迁移到C#时遇到了读取文件的问题。VB6使用了一种特定的方式读取二进制数据到自定义结构中,而在C#中,需要采取不同的方法来处理这种类型的序列化和反序列化。下面是将你的需求转换为C#代码的步骤及示例:

    1. 定义结构体

    首先,在C#中你需要创建一个与TypeResult等价的类或结构体,并且确保字段类型与VB6中的相匹配。

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct TypeResult
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
        public DateTime[] KensaDate;
        
        public int RecipeNo;
        
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
        public string RecipeName;
        
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
        public string GlassCF;
        
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
        public string GLASSTFT;
        
        public byte VASNo;
        
        public float VASX;
        
        public float VASY;
        
        public float VASC;
        
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50 * 4 * 2)]
        public string[,] Paneljieguo; // 注意这里数组的声明方式
        
        public int YouxiaoMarkCnt;
    }
    

    请注意:

    • 使用StructLayout属性指定布局顺序。
    • Pack=1用于控制对齐,这在处理跨语言数据交换时很重要。
    • 字符串长度设定为255(或者根据实际最大长度调整),并使用ByValTStr进行固定大小字符串的处理。
    • 二维数组Paneljieguo在C#中可能需要一些额外处理以正确映射到原始的三维数组形式。

    2. 读取二进制文件

    接下来是读取文件部分。你可以使用FileStream配合BinaryReader来进行二进制文件的读取,然后通过Marshal.PtrToStructure方法将字节流转换为结构体实例。

    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    
    class Program
    {
        static void Main()
        {
            string vFileName = "D:/B3MAFeedbackHistoryData/Result/20241029/R0000000100";
            
            if (!File.Exists(vFileName))
            {
                Console.WriteLine("文件不存在!");
                return;
            }
    
            using (var stream = new FileStream(vFileName, FileMode.Open, FileAccess.Read))
            {
                byte[] buffer = new byte[Marshal.SizeOf(typeof(TypeResult))];
                stream.Read(buffer, 0, buffer.Length);
    
                GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                try
                {
                    var result = (TypeResult)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(TypeResult));
                    
                    // 打印结果验证
                    Console.WriteLine($"RecipeNo: {result.RecipeNo}");
                    Console.WriteLine($"RecipeName: {result.RecipeName}");
                    // 其他字段同理打印...
                }
                finally
                {
                    handle.Free();
                }
            }
        }
    }
    

    这段代码展示了如何打开指定路径下的文件,读取其内容到缓冲区,并将该缓冲区的内容解析为之前定义好的TypeResult结构体。请根据实际情况调整字符编码和其他细节设置。如果遇到乱码问题,请检查源文件的实际编码格式是否与预期一致。希望这能帮助你解决问题!

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月12日
  • 修改了问题 11月11日
  • 创建了问题 11月11日