前段时间,在将一个6.0的程序升级到.NET的过程中就遇到了很多麻烦。这个结构体中包含了定长字符串、数组以及其它一些结构,需要将该结构体作为头文件直接保存到一个二进制文件中,同时还要能从文件中读出该结构体。在6.0中,该结构体如下:
view plain TypeOptionType IDAsstring*11 SamplingModeAsInteger StartModeAsByte FreqAsInteger TimeAsSingle PreTimeAsLong SamplesAsLong TestnameAsstring*24 Chan(1ToADCOCHANS)AsChanType TimeUnitAsInteger VectorUSpanAsSingle VectorISpanAsSingle RelatAsstring*20 AddrAsstring*20 TestDateAsDate TestMemoAsstring*320 EndType
其中,ChanType是另一个结构体,如下:
TypeChanType ChanNoAsstring*10 ChannameAsstring*10 UnitAsstring*6 OffonAsInteger RatioAsSingle FactorAsSingle DcacAsInteger LowerAsSingle UpperAsSingle ZerovalAsSingle colorAsLong ShiftAsInteger EndType
如果只是简单的将其改写到.NET版本并不难,但若想在.NET中读出以前6.0下保存的二进制文件时,就需要好好的设计一番了。具体涉及到以下几个问题:
1、.NET中已不再直接支持6.0中的定长字符串。不定长的字符串在存储时,需要同时存储一个长度值。
2、.NET中的数据类型有了很大变化,比如Integer是从16位变为32位,DateTime以整数形式保存而不再是以前的Double型
。。。
在此不一一列举,有兴趣的可以参看微软出的相关文档。下面是改写后的结构体:
<StructLayoutAttribute(LayoutKind.Sequential,CharSet:=CharSet.Ansi,Pack:=1)>_ PublicStructureStructoption <MarshalAs(UnmanagedType.ByValTStr,SizeConst:=11)>_ PublicIDAsString PublicSamplingModeShort PublicStartModeByte PublicFreqPublicTimeSingle PublicPreTimeInteger PublicSamplesInteger <MarshalAs(UnmanagedType.ByValTStr,SizeConst:=24)>_ PublicTestnameString <MarshalAs(UnmanagedType.ByValArray,SizeConst:=44)>_ PublicChan()AsStructChan PublicTimeUnitPublicVectorUSpanPublicVectorISpanSingle <MarshalAs(UnmanagedType.ByValTStr,SizeConst:=20)>_ PublicRelatString PublicAddrPublicTestDateDate <MarshalAs(UnmanagedType.ByValTStr,SizeConst:=320)>_ PublicTestMemoString SharedFunctionCreateInstance()AsStructoption DimretNewStructoption DimnewChanNewStructChan ReDimret.Chan(ADCOCHANS-1) ForiInteger=0ToADCOCHANS-1 ret.Chan(i)=newChan Next Returnret EndFunction Structure
StructureStructChan <MarshalAs(UnmanagedType.ByValTStr,SizeConst:=10)>_ PublicChanNoString <MarshalAs(UnmanagedType.ByValTStr,153); background-color:inherit">PublicChannameUnitPublicOffonPublicRatioPublicfactorPublicDcacShort PublicLowerPublicUpperPublicZerovalPubliccolorInteger PublicShiftStructure
或许你已经注意到了,在改写的结构体中使用了一些属性,必须使用这些属性,才能构造出与VB6一模一样的结构体(至少说保存到文件中时时一样的结构)。
.NET中将结构体保存至文件的方法有两种:
一种是为结构体添加<Serializable()>属性,然后使用System.Runtime.Serialization.Formatters.Binary.BinaryFormatter中的Serialize方法将其串行化为文件流,并可用Deserialize方法将其还原为结构体;
另一种方法便是本文要讨论的,即结构体与字节数组之间的转化,因为在VB6中保存结构体时是按字节存储的,要做到同样效果需要将结构体其转化为字节数组。
再回到改写后的结构体中,为了定义属性,首先需要导入命名空间
imports System.Runtime.InteropServices
接下来的结构体属性必不可少:
<StructLayoutAttribute(LayoutKind.Sequential,CharSet:=CharSet.Ansi,Pack:=1)>
对于定长字符串,需要添加如下属性:
<MarshalAs(UnmanagedType.ByValTStr,SizeConst:=11)>
注意,这里,字符串只能保存10个字符
对于定长数组,同样需要添加属性:
<MarshalAs(UnmanagedType.ByValArray,SizeConst:=44)>
另外,在使用前,需要对定长数组的长度进行ReDim,且长度必须与SizeConst相等。事实上,如果你定义了更长的长度,它会只截取SizeConst长度进行保存
接下来便是结构体与字节数组之间的转化,以及从文件读取结构体的源代码(注:部分源码根据网络上的C#版本改写)
PrivateSubStructToBytes(ByValobJstructObject,ByRefbytes()Byte) '得到结构体长度 DimsizeInteger=Marshal.SizeOf(obJstruct) '重新定义数组大小 ReDimbytes(size) '分配结构体大小的内存空间 DimptrStructAsIntPtr=Marshal.AllocHGlobal(size) '将结构体放入内存空间 Marshal.StructuretoPtr(obJstruct,ptrStruct,False) '将内存拷贝到字节数组 Marshal.copy(ptrStruct,bytes,size) '释放内存空间 Marshal.FreeHGlobal(ptrStruct) Sub '''<summary> '''字节数组bytes()转化为结构体 FunctionBytesToStruct(Byte,153); background-color:inherit">ByValmytypeAsType)Object '获取结构体大小 Integer=Marshal.SizeOf(mytype) 'bytes数组长度小于结构体大小 If(size>bytes.Length)Then '返回空 Returnnothing If '将数组拷贝到内存 Marshal.copy(bytes,0); background-color:inherit">'将内存转换为目标结构体 DimobjObject=Marshal.PtrToStructure(ptrStruct,mytype) '释放内存 Marshal.FreeHGlobal(ptrStruct) Returnobj Function '''从文件中读取结构体 '''</summary> '''<returns>结构体</returns> '''<remarks></remarks> FunctionfileToStruct(ByValstrPathString,0); background-color:inherit">'获得结构体大小 '打开文件流 DimfsNewfileStream(strPath,fileMode.Open) '读取size个字节 Dimbytes(size)Byte fs.Read(bytes,0); background-color:inherit">'将读取的字节转化为结构体 Object=BytesToStruct(bytes,248); margin:0px!important; padding:0px 3px 0px 10px!important"> fs.Close() Function 总结
以上是内存溢出为你收集整理的VB.NET中将结构体保存到文件的方法全部内容,希望文章能够帮你解决VB.NET中将结构体保存到文件的方法所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)