在文件中有个文件是用VB写的,现在需要用C#读出这个文件的内容,供C#程序提供参数数据。
VB中定义的结构如下:
VB代码:
Public Type ChannelType
     name As String * 3  '通道名称
     Index As Long       '对应索引点
     Key As Long
     Edited As Boolean   '是否已经配置信息
End Type
'模块结构
Public Type SlotType
     Channel(7) As ChannelType
     name As String * 8   '子槽名称
     Slot_Num As Long     '槽号索引
     Key As Long
End Type
'设备结构
Public Type Board
     Address As String * 16   '设备地址(存IP地址或COM1、COM2....)
     Port_DIP  As Long        '设备分配号(如:5510 DIP地址)
     Slot(9) As SlotType
     name As String * 12      '母槽名称(如:ADAM5000TCP)
     Rtrn As Long             '整个槽采集命令返回长度(针对5000TCP、ADAM6017)
     Cmd As String * 5        '整个槽采集命令(针对5000TCP、ADAM6017)
     Key As Long              '
End Type
Public DeviceID() As Board然后再中间的一些地方对DeviceID 进行重定义,赋值下面是保存的部分语句
 
  Dim MainBoard  As Board
  Dim FileHandle,i As Long
  Dim LastRecord As Integer
  Dim strFilename, WriteStr As String
  Dim Fs
  Set Fs = CreateObject("Scripting.FileSystemObject")
    ''如果文件存在,则删除
    FileHandle = FreeFile
    strFilename = strFilePath + "Moudle.map" 'CDlg.FileName
    If Fs.fileexists(strFilename) Then Kill strFilename
    Open strFilename For Random As #FileHandle Len = Len(MainBoard)
    LastRecord = LOF(FileHandle) / Len(MainBoard)
    If DeviceTotal > 0 Then
        For i = 1 To DeviceTotal
            Put #FileHandle, LastRecord + i, DeviceID(i - 1)
        Next i
    End If
    Close #FileHandle
    Set Fs = Nothing
我现在用C#依上面的格式声明了结构体,然后用的读串行化文件的方法读这个文件,出现错误未处理 System.Runtime.Serialization.SerializationException
  Message="输入流是无效的二进制格式。开始内容(以字节为单位)是: 31-39-32-2E-31-36-38-2E-30-2E-32-30-31-20-20-20-F4..."
  Source="mscorlib"。应该是格式和C#的串行化文件的格式不一样,请问,还有其他的办法可以读出里面的数据吗?
  

解决方案 »

  1.   

    BitConvert.ToInt32等的系列方法可以将字节数组转为基本类型。
    或是参考
    c# 二进制序列化和反序列化方法
      

  2.   


    BitConvert.ToInt32等的系列方法可以将字节数组转为基本类型。这里讲的是什么方法,可以详细点说明不?系列化和反系列化好像只适用于C#自己生成的文件,我试过的,就是报格式错误。
      

  3.   

    考虑用BinaryReader 来地个成员地读,但是string类型不知道怎么解决,VB中用的是指定长度的String .name As String * 3 而C#中不能指定长度。
      

  4.   

    序列化就不太熟习。给你个可行的不太优雅的办法。是我说的第一种方法。
    假设vb6写文件为:Private Sub Command1_Click()
        Dim demoType As ChannelType
        demoType.Edited = True
        demoType.Index = 123
        demoType.Key = 18
        demoType.name = "abc"
        Dim FileHandle As Integer
        FileHandle = FreeFile
        strFilename = App.Path + "\Moudle.map" 'CDlg.FileName
        Open strFilename For Random As #FileHandle Len = Len(demoType)
        Put #FileHandle, 1, demoType
        Close #FileHandle
    End SubC#这样读取//需要添加命名空间的引用:
    //using System.IO;
    static void Main(string[] args)
    {
        byte[] data = File.ReadAllBytes("Moudle.map");
        ChannelType ct = ChannelType.Parse(data);
        Console.ReadKey();
    }public class ChannelType
    {
        public StringBuilder name = new StringBuilder(3);//通道名称
        public int Index = 0; //对应索引点
        public int Key = 0;
        public bool Edited = false;//是否已经配置信息
        public static ChannelType Parse(byte[] data)
        {
            ChannelType c = new ChannelType();
            c.name.Append((char)data[0]);
            c.name.Append((char)data[1]);
            c.name.Append((char)data[2]);
            c.Index = BitConverter.ToInt32(data, 3);
            c.Key = BitConverter.ToInt32(data, 7);
            c.Edited = BitConverter.ToBoolean(data, 8);
            return c;
        }
    }
      

  5.   

    VB包装成一个ActiveX DLL,C#直接用。
      

  6.   

    四楼的按照你的思路我读出来了这个数据,另外我用BinaryReader也读出来了。
      

  7.   


        public class ChannelType
        {
            public StringBuilder name = new StringBuilder(3);
            public int index = -1;
            public int channelkey = -1;
            public bool edited =false;        public static ChannelType Parse(byte[] data)
            {
                ChannelType c = new ChannelType();
                c.name.Append((char)data[0]);
                c.name.Append((char)data[1]);
                c.name.Append((char)data[2]);
                c.index = BitConverter.ToInt32(data, 3);
                c.channelkey = BitConverter.ToInt32(data, 7);
                c.edited = BitConverter.ToInt16(data, 11)==0?false:true;  //VB中的BOOL型占2个字节
                return c;
            }        public static ChannelType ReadMapChannel(BinaryReader br)
            {
                ChannelType c = new ChannelType();
                c.name.Append((char)br.ReadByte());
                c.name.Append((char)br.ReadByte());
                c.name.Append((char)br.ReadByte());
                c.index = br.ReadInt32();
                c.channelkey = br.ReadInt32();
                c.edited = br.ReadInt16() == 0 ? false : true;
                return c;
            }
        }    public class ModuleType
        {
            public ChannelType[]  channel = new ChannelType[8];
            public StringBuilder name = new StringBuilder(8);
            public int slotNum = -1;
            public int key=-1;        public static ModuleType Parse(byte[] data)
            {
                const int channelTypeLen = 13;
                ModuleType m = new ModuleType();            byte[] channelData = new byte[channelTypeLen];
                for (int i = 0; i < 8; i++)
                {
                    for (int j = i * channelTypeLen,k=0; j < (i+1)*channelTypeLen; j++,k++)
                    {
                       channelData[k] = data[j];
                    }                               
                    m.channel[i] = ChannelType.Parse(channelData);
                }
                for (int i = 0; i < 8; i++)
                {                m.name.Append((char)data[8 * channelTypeLen + i]);
                }
                m.slotNum = BitConverter.ToInt32(data, 8 * channelTypeLen + 8);
                m.key = BitConverter.ToInt32(data, 8 * channelTypeLen + 12);
                return m;
            }        public static ModuleType ReadMapModule(BinaryReader br)
            {
                ModuleType m = new ModuleType();
                for (int i = 0; i < 8; i++)
                {
                    m.channel[i] = ChannelType.ReadMapChannel(br);
                }            for (int i = 0; i < 8; i++)
                {
                    m.name.Append((char)br.ReadByte());
                }
                
                m.slotNum = br.ReadInt32();
                m.key = br.ReadInt32();
                return m;
            }
        }    public class DeviceType
        {        public StringBuilder address = new StringBuilder(16);        public int portDIP =-1;
            public ModuleType[] module = new ModuleType[10];
            public StringBuilder name = new StringBuilder(12);
            public int rtrn =-1;
            public StringBuilder cmd =new StringBuilder(5);
            public int deviceKey =-1;        public static DeviceType Parse(byte[] data)
            {
                const int moduleTypeLen = 120;
                DeviceType d = new DeviceType();
                for (int i = 0; i < 16; i++)
                {
                    d.address.Append((char)data[i]);
                }
                d.portDIP = BitConverter.ToInt32(data,16);            byte[] moduleData = new byte[moduleTypeLen];
                for(int i = 0 ; i <10;i++)
                {
                    for (int j = 20 + i * moduleTypeLen,k=0; j < 20 + (i+1) * moduleTypeLen; j++,k++)
                    {
                        moduleData[k] = data[j];
                    }       
                    d.module[i] = ModuleType.Parse(moduleData);
                }
                for (int i = 0; i < 12; i++)
                {
                    d.name.Append((char)data[i + 20 + 8 * moduleTypeLen]);
                }
                d.rtrn = BitConverter.ToInt32(data, 32 + 8 * moduleTypeLen);            for (int i = 0; i < 5; i++)
                {
                    d.cmd.Append((char)data[i + 36 + 8 * moduleTypeLen]);
                }
                d.deviceKey = BitConverter.ToInt32(data, 41 + 8 * moduleTypeLen);            return d;
            }        public static List<DeviceType> ReadMapDevice(BinaryReader br)
            {
                List<DeviceType> Devices = new List<DeviceType>();
                try
                {
                    while (true)
                    {
                        DeviceType d = new DeviceType();
                        for (int i = 0; i < 16; i++)
                        {
                            d.address.Append((char)br.ReadByte());
                        }
                        d.portDIP = br.ReadInt32();
                        for (int i = 0; i < 10; i++)
                        {
                            d.module[i] = ModuleType.ReadMapModule(br);
                        }                    for (int i = 0; i < 12; i++)
                        {
                            d.name.Append((char)br.ReadByte());
                        }
                        d.rtrn = br.ReadInt32();
                        for (int i = 0; i < 5; i++)
                        {
                            d.cmd.Append((char)br.ReadByte());
                        }
                        d.deviceKey = br.ReadInt32();                    Devices.Add(d);
                    }
                }
                catch (EndOfStreamException)
                {
                    return Devices;
                }
                           
              
            }
        }这里是3个对象的实现代码,Frase方法为支持 File类的读写,ReadMap方法为支持BinaryReader类的读写。这里有几个地方对应的VB与C#变量定义不一样需要转换
    VB的Boolean型是2个字节,我要转成C#的一个字节用 br.ReadInt16()==0?false:ture;这样转化。
    另外,对于StringBuilder的字符串,本来是用的br.ReadChars()读入的,后来在调试中发现有时候
    br.ReadChars(count) 读入的字符数和count不一致(还没有发现是什么原因),改成了用 ReadBytes()方法
      

  8.   


     private void btnOpen_Click(object sender, EventArgs e)
            {
                List<DeviceType> Devices = new List<DeviceType>();
                
                Dlg1.Title = "打开配置文件";
                if (Dlg1.ShowDialog() ==DialogResult.OK)
                {
                    FileStream loadFile = new FileStream(Dlg1.FileName, FileMode.Open, FileAccess.Read);
                    BinaryReader br = new BinaryReader(loadFile);
                    Devices = DeviceType.ReadMapDevice(br);
                    br.Close();
                    loadFile.Close();
                    foreach (DeviceType d in Devices)
                    {
                        AddDeviceTotree(d, treeView2);
                    }
                   /*      另一种读取map文件到对象的方法
                    byte[] data = File.ReadAllBytes(Dlg1.FileName);
                    DeviceType ct = DeviceType.Parse(data);               
                    AddDeviceTotree(ct, treeView3);
                    */
                }
                   
            }调用的方法比较简单,考虑到.map文件经常是保存的多个对象的数据,所以我把对象方法的返回值设置为List<t> 形式