VB.NET中将结构体保存到文件的方法

VB.NET中将结构体保存到文件的方法,第1张

概述VB.NET中的结构体在使用的时候像是一个“小型的类”,其内部结构与VB6.0相比有许多不同。当需要把一个VB6.0中的结构体升级到对应的.NET版本时,在细节上会有很多区别。 前段时间,在将一个6.0的程序升级到.NET的过程中就遇到了很多麻烦。这个结构体中包含了定长字符串、数组以及其它一些结构,需要将该结构体作为头文件直接保存到一个二进制文件中,同时还要能从文件中读出该结构体。在6.0中,该结 VB.NET中的结构体在使用的时候像是一个“小型的类”,其内部结构与VB6.0相比有许多不同。当需要把一个VB6.0中的结构体升级到对应的.NET版本时,在细节上会有很多区别。

前段时间,在将一个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中将结构体保存到文件的方法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1276287.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-09
下一篇 2022-06-09

发表评论

登录后才能评论

评论列表(0条)

保存