level 2
自定义类型AA
Public Structure AA
Public A1 As Integer
Public A2() As Single
Public A3() As Single
Public A4 As String
Public Sub New(ByVal Size As UShort)
A2 = New Single(Size) {}
A3 = New Single(Size) {}
End Sub
End Structure
Public A As AA
现在想要使用A读写二进制文件,不知该怎样实现。请指教,谢谢!
2014年07月26日 12点07分
1
level 13
StructureToPtr写Byte(),用FileStream写文件
2014年07月27日 05点07分
2
写的话这样应该可以;但是读的话,A4 As String应该是不定长的,这个有办法解决吗?
2014年07月27日 07点07分
回复 jwjsb :在文件结构中保存这个String的位置和大小
2014年07月27日 10点07分
level 2
改变了下Structure,变相使用定长字符串,(程序见下)。
现在的问题是
调用完SaveFile保存后接着调用ReadFile读取,运行正常;但如果调用完SaveFile保存文件后关闭程序,然后重新运行程序再直接调用ReadFile读取文件就会报错【具体见程序内*+++++注释部分】。
请指教,谢谢!
Imports System
Imports System.Runtime.InteropServices
Module Module1
Public Structure AA
Public A1 As Integer
Public A2 As Long
<VBFixedString(10)> Public A3 As String
<VBFixedArray(12)> Public A4() As Single
End Structure
*读取文件
Public Sub ReadFile()
Dim B As New AA
ReDim B.A4(12)
Dim Size As Integer = Marshal.SizeOf(B)
Dim Buf() As Byte
ReDim Buf(Size)
*从文件指定位置读取数据
Dim fn As New IO.FileStream("e:\123.mp3", IO.FileMode.Open)
Dim fr As New IO.BinaryReader(fn)
fr.BaseStream.Position = 0 *从1000字节处开始读取文件
Buf = fr.ReadBytes(Size)
fr.Close()
fn.Close()
*分配结构体大小的内存空间
Dim ptrStruct As IntPtr = Marshal.AllocHGlobal(Size)
*将数组拷贝到内存
Marshal.Copy(Buf, 0, ptrStruct, Size)
*将内存转换为目标结构体
*++++++++++++++++++++++++++++++++++++++++++++++++++++++
*++++++++++SaveFile后接着ReadFile,运行正常++++++++++
*+但如果SaveFile后关闭程序,然后重新运行程序直接ReadFile,此处报错+
B = CType(Marshal.PtrToStructure(ptrStruct, GetType(AA)), AA)
*++++运行程序后,直接读取以前保存的文件,此处报错++++++
*++++++++++++++++++++++++++++++++++++++++++++++++++++++
*释放内存
Marshal.FreeHGlobal(ptrStruct)
MsgBox(B.A1)
MsgBox(B.A2)
End Sub
*保存文件
Public Sub SaveFile()
Dim A As New AA
Dim i As Short
ReDim A.A4(12)
A.A1 = 12
A.A2 = 20
A.A3 = "ABCDEFGHIJK"
For i = 0 To 12
A.A4(i) = i
Next
Dim Size As Integer
Dim Buff() As Byte
Size = Marshal.SizeOf(A)
ReDim Buff(Size)
Dim dat As IntPtr = Marshal.AllocHGlobal(Size)
Marshal.StructureToPtr(A, dat, False)
Marshal.Copy(dat, Buff, 0, Size)
Marshal.FreeHGlobal(dat)
*在文件指定位置写入数据
Dim fn As New IO.FileStream("e:\123.mp3", IO.FileMode.OpenOrCreate)
Dim fr As New IO.BinaryWriter(fn)
fr.BaseStream.Position = 0 *从1000字节处开始读取文件
fr.Write(Buff) *将data数组写入文件
fr.Close()
fn.Close()
End Sub
End Module *++++++++++SaveFile后接着ReadFile,运行正常++++++++++
*+但如果SaveFile后关闭程序,然后重新运行程序直接ReadFile,此处报错+
2014年07月27日 15点07分
3
level 13
不要使用String。用Char()代替。
--来自相机+平板电脑+手机融合成的的Lumia 1520
2014年07月27日 16点07分
4
level 13
用String会把字符串指针(与LPWStr类似的)保存进文件,当字符串从内存消失时指针无效。应当把Char()数据写进文件。
--来自相机+平板电脑+手机融合成的的Lumia 1520
2014年07月27日 17点07分
5
level 13
写带Char()的结构体还是老实用BinaryWriter比较方便。
--来自相机+平板电脑+手机融合成的的Lumia 1520
2014年07月27日 17点07分
6
level 13
读取用BinaryReader
--来自相机+平板电脑+手机融合成的的Lumia 1520
2014年07月27日 17点07分
7
level 13
但如果结构体里面的东西都是大小固定的而且是值类型的,就用StructureToPtr和PtrToStrure。
我估计楼主那段代码是从某博客学的。那段代码有缺陷,就是多占内存且多复制了。
--来自相机+平板电脑+手机融合成的的Lumia 1520
2014年07月27日 17点07分
8
level 13
序列化结构体为Byte()
先Dim 缓冲(上界) As Byte
然后用UnsafeAddrOfPinnedArrayElement获取数组的地址
下来用StructureToPtr,把结构写进Byte(),用File.WriteAllBytes保存。
代码短,执行快。
--来自相机+平板电脑+手机融合成的的Lumia 1520
2014年07月27日 17点07分
9
level 13
上界用SizeOf
--来自相机+平板电脑+手机融合成的的Lumia 1520
2014年07月27日 17点07分
10
-1 --来自相机+平板电脑+手机融合成的的Lumia 1520
2014年07月27日 17点07分