在文件中有个文件是用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#的串行化文件的格式不一样,请问,还有其他的办法可以读出里面的数据吗?
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#的串行化文件的格式不一样,请问,还有其他的办法可以读出里面的数据吗?
或是参考
c# 二进制序列化和反序列化方法
BitConvert.ToInt32等的系列方法可以将字节数组转为基本类型。这里讲的是什么方法,可以详细点说明不?系列化和反系列化好像只适用于C#自己生成的文件,我试过的,就是报格式错误。
假设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;
}
}
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()方法
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> 形式