VB CreateFile不能写string类型数据

sandjuanjuan 2018-04-23 01:44:36
各位高手,用VB做数据保存和读取,定义的数据只要不是string类型的,使用CreateFile,write file ,read file都正常。如果要写入的数据包含strin类型的数据,读写就出现乱码。
...全文
877 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
舉杯邀明月 2018-05-02
  • 打赏
  • 举报
回复
引用 13 楼 sandjuanjuan 的回复:
[quote=引用 12 楼 chewinggum 的回复:] 貌似就是普通的读写文件嘛,VB有完整的一套文件操作指令,为啥要全API操作? 问度娘:“VB6 文件操作” 遍地都是结果 推荐看看 https://blog.csdn.net/ben1978/article/details/751498
谢谢,之前我采用的方法是OPEN INOUT或者write方法,但是发现在断电时会丢失数据。API这个函数支持无缓存直接写入,防止出现数据先被擦出还没来得及写入的情况。[/quote] 直接用VB6的文件操作语句,你写完后“Close”时,它也应该是会从缓冲区执行“写盘”的吧! 你说的“断电时会丢失数据”, 其一,估计是你没有及时“关闭文件”,造成缓存数据延后更新; 其二,如果是你正好在“写入磁盘”时断电,恐怕什么方法都无法保证“数据有效”的吧!
sandjuanjuan 2018-05-02
  • 打赏
  • 举报
回复
引用 12 楼 chewinggum 的回复:
貌似就是普通的读写文件嘛,VB有完整的一套文件操作指令,为啥要全API操作? 问度娘:“VB6 文件操作” 遍地都是结果 推荐看看 https://blog.csdn.net/ben1978/article/details/751498
谢谢,之前我采用的方法是OPEN INOUT或者write方法,但是发现在断电时会丢失数据。API这个函数支持无缓存直接写入,防止出现数据先被擦出还没来得及写入的情况。
sandjuanjuan 2018-05-02
  • 打赏
  • 举报
回复
[quote=引用 11 楼 Chen8013 的回复:] 给你段代码,参考一下。  非常感谢,学习了。
脆皮大雪糕 2018-05-02
  • 打赏
  • 举报
回复
其实你的这段代码太偷懒了,你应该定义数据格式,比如固定每条记录的长度,或者记录之间要有分割标志。否则只管写不管读,即使写正常了,读的时候也是一片混乱。
脆皮大雪糕 2018-05-02
  • 打赏
  • 举报
回复
引用 13 楼 sandjuanjuan 的回复:
[quote=引用 12 楼 chewinggum 的回复:] 貌似就是普通的读写文件嘛,VB有完整的一套文件操作指令,为啥要全API操作? 问度娘:“VB6 文件操作” 遍地都是结果 推荐看看 https://blog.csdn.net/ben1978/article/details/751498
谢谢,之前我采用的方法是OPEN INOUT或者write方法,但是发现在断电时会丢失数据。API这个函数支持无缓存直接写入,防止出现数据先被擦出还没来得及写入的情况。[/quote] 文件open写完及时close。 你调用API的这段代码,并不是因为它不缓存,而是你调用的WriteArray在函数的最后及时close handle了
脆皮大雪糕 2018-04-29
  • 打赏
  • 举报
回复
貌似就是普通的读写文件嘛,VB有完整的一套文件操作指令,为啥要全API操作? 问度娘:“VB6 文件操作” 遍地都是结果 推荐看看 https://blog.csdn.net/ben1978/article/details/751498
舉杯邀明月 2018-04-28
  • 打赏
  • 举报
回复
给你段代码,参考一下。 
' 窗体代码:
Option Explicit

Private strFileName  As String

Private Sub Form_Load()
    'strFileName = "E:\CESHI.TXT"
    strFileName = "E:\Temp\TestA.txt"
End Sub

Private Sub Command1_Click()
   Dim arrTest(1)   As MyType
    arrTest(0).banci = 12345
    arrTest(0).xingming = "张三李四"
    arrTest(1).banci = 789
    arrTest(1).xingming = "吕洞宾"
    WriteArray strFileName, arrTest
End Sub

Private Sub Command2_Click()
   Dim arrTemp(1)   As MyType
   Dim i As Long
   
   Call ReadArray(strFileName, arrTemp())
   Me.Cls
   For i = 0& To 1&
      ' 加个“<”符号,让你可以看到读出来的文本没有“多余的东西”
      Me.Print arrTemp(i).banci, arrTemp(i).xingming & "<"
   Next
   'Text1.Text = S(0).xingming
End Sub
' 标准模块代码:
Option Explicit

Private Declare Sub CopyMemory Lib "Kernel32" Alias "RtlMoveMemory" ( _
                  ByRef Destination As Any, _
                  ByRef Source As Any, _
                  ByVal Length As Long)

Private Declare Function ReadFile Lib "Kernel32" ( _
                  ByVal hFile As Long, _
                  ByRef lpBuffer As Any, _
                  ByVal nNumberOfBytesToRead As Long, _
                  ByRef lpNumberOfBytesRead As Long, _
                  ByVal lpOverlapped As Long) As Long

Private Declare Function CloseHandle Lib "Kernel32" ( _
                  ByVal hObject As Long) As Long
 
Private Declare Function WriteFile Lib "Kernel32" ( _
                  ByVal hFile As Long, _
                  ByRef lpBuffer As Any, _
                  ByVal nNumberOfBytesToWrite As Long, _
                  ByRef lpNumberOfBytesWritten As Long, _
                  ByVal lpOverlapped As Long) As Long
 
Private Declare Function CreateFile Lib "Kernel32" _
            Alias "CreateFileA" (ByVal lpFileName As String, _
                  ByVal dwDesiredAccess As Long, _
                  ByVal dwShareMode As Long, _
                  ByVal lpSecurityAttributes As Long, _
                  ByVal dwCreationDisposition As Long, _
                  ByVal dwFlagsAndAttributes As Long, _
                  ByVal hTemplateFile As Long) As Long

Private Declare Function FlushFileBuffers Lib "Kernel32" (ByVal hFile As Long) As Long

Public Type MyType
   banci As Integer
   xingming As String
End Type

Private Type MyType_IO
   banci As Integer
   data(9)  As Byte
End Type


Private Const GENERIC_WRITE   As Long = &H40000000
Private Const GENERIC_READ As Long = &H80000000
Private Const FILE_ATTRIBUTE_NORMAL As Long = &H80
Private Const CREATE_ALWAYS As Long = 2
Private Const OPEN_ALWAYS As Long = 4
Private Const INVALID_HANDLE_VALUE As Long = -1

Public Sub ReadArray(ByVal Fname As String, anArray() As MyType)
   Dim arrBuff()  As MyType_IO
   Dim strTemp As String
   Dim fHandle As Long
   Dim fSuccess As Long
   Dim lBytesRead As Long
   Dim BytesToRead As Long
   Dim i%, m As Integer

   m = UBound(anArray)
   ReDim arrBuff(m)
   BytesToRead = (m + 1) * LenB(arrBuff(0))
   fHandle = CreateFile(Fname, GENERIC_WRITE Or GENERIC_READ, _
                           0&, 0&, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0&)
   If (INVALID_HANDLE_VALUE = fHandle) Then Exit Sub
   fSuccess = ReadFile(fHandle, arrBuff(0), BytesToRead, lBytesRead, 0&)
   Call CloseHandle(fHandle)
   If (fSuccess) Then
      For i = 0 To m
         anArray(i).banci = arrBuff(i).banci
         strTemp = StrConv(arrBuff(i).data(), vbUnicode)
         m = InStr(1&, strTemp, vbNullChar)
         If (m) Then strTemp = Left$(strTemp, m - 1&)
         anArray(i).xingming = strTemp
      Next
   End If
End Sub

Public Sub WriteArray(Fname As String, anArray() As MyType)
   Dim arrBuff()  As MyType_IO
   Dim arrTemp()  As Byte
   Dim fHandle As Long
   Dim fSuccess As Long
   Dim lBytesWritten As Long
   Dim BytesToWrite As Long
   Dim i%, m As Integer

   m = UBound(anArray)
   ReDim arrBuff(m)
   For i = 0 To m
      arrBuff(i).banci = anArray(i).banci
      arrTemp() = StrConv(anArray(i).xingming, vbFromUnicode)
      m = 1& + UBound(arrTemp())
      If (10 < m) Then m = 10 ' 文本限制最多10字节
      If (m) Then Call CopyMemory(arrBuff(i).data(0), arrTemp(0), m)
   Next
   BytesToWrite = i * LenB(arrBuff(0))
   fHandle = CreateFile(Fname, GENERIC_WRITE Or GENERIC_READ, _
                           0&, 0&, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0&)
   If (INVALID_HANDLE_VALUE = fHandle) Then Exit Sub
   fSuccess = WriteFile(fHandle, arrBuff(0), BytesToWrite, lBytesWritten, 0&)
   If (fSuccess) Then Call FlushFileBuffers(fHandle)
   Call CloseHandle(fHandle)
End Sub
舉杯邀明月 2018-04-28
  • 打赏
  • 举报
回复
我觉得,你这种“结构体”(自定义数据类型),恐怕只有用“定长记录格式”进行磁盘I/O操作,才能保证数据的正确性。 否则,你那其中的一个“字符串数据”长度是不确定的,你怎么知道“某条数据”究竟是占用了多少字节呢!
sandjuanjuan 2018-04-28
  • 打赏
  • 举报
回复
引用 8 楼 Chen8013 的回复:
[quote=引用 6 楼 sandjuanjuan 的回复:] [quote=引用 1 楼 Chen8013 的回复:] 你的API声明 or 使用不恰当。 把你的代码贴出来………… 一般来说,你要处理“String数据”的话,那个“缓冲区”你得用字节数组中转一下。
非常感谢! 我根据老弟给的建议重新写的程序,计算了写的字节数,运行程序发现,有一半的机率可以读出字符,另一半读出来是E盘符,不知道为啥? 模块程序: Public FILE_NAME As String Public Const GENERIC_WRITE = &H40000000 Const GENERIC_READ = &H80000000 Const FILE_ATTRIBUTE_NORMAL = &H80 Const CREATE_ALWAYS = 2 Const OPEN_ALWAYS = 4 Const INVALID_HANDLE_VALUE = -1 Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, _ lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, _ lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long Public Declare Function CloseHandle Lib "kernel32" ( _ ByVal hObject As Long) As Long Public Declare Function WriteFile Lib "kernel32" ( _ ByVal hFile As Long, lpBuffer As Any, _ ByVal nNumberOfBytesToWrite As Long, _ lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long Public Declare Function CreateFile Lib "kernel32" _ Alias "CreateFileA" (ByVal lpFileName As String, _ ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, _ ByVal lpSecurityAttributes As Long, _ ByVal dwCreationDisposition As Long, _ ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) _ As Long Public Declare Function FlushFileBuffers Lib "kernel32" ( _ ByVal hFile As Long) As Long Declare Function GetLastError Lib "kernel32" () As Long Type MyType banci As Integer xingming As String End Type Public T(0) As MyType Public S(0) As MyType Public Sub readArray(Fname As String, anArray() As MyType) Dim fHandle As Long Dim fSuccess As Long Dim lBytesRead As Long Dim BytesToRead As Long ' 'Get size of data to write Dim i As Integer i = UBound(anArray) BytesToRead = (UBound(anArray) + 1) * (LenB(Str((anArray(i).banci))) + LenB(anArray(i).xingming)) ' 'Get a handle to a file Fname. fHandle = CreateFile(Fname, GENERIC_WRITE Or GENERIC_READ, _ 0, 0, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0) 'Here you should test to see if you get a file handle or not. 'CreateFile returns INVALID_HANDLE_VALUE if it fails. If fHandle <> INVALID_HANDLE_VALUE Then Dim j As Integer j = 0 fSuccess = ReadFile(fHandle, anArray(j), _ BytesToRead, lBytesRead, 0) 'ReadFile returns a non-zero value if it is successful. 'Now you just close the file. fSuccess = CloseHandle(fHandle) End If End Sub Public Sub writearray(Fname As String, anArray() As MyType) Dim fHandle As Long Dim fSuccess As Long Dim lBytesWritten As Long Dim BytesToWrite As Long 'Get the length of data to write Dim i As Integer i = UBound(anArray) BytesToWrite = (UBound(anArray) + 1) * (LenB(Str((anArray(i).banci))) + LenB(anArray(i).xingming)) 'Get a handle to a file Fname. fHandle = CreateFile(Fname, GENERIC_WRITE Or GENERIC_READ, _ 0, 0, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0) 'Here you should test to see if you get a file handle or not. 'CreateFile returns INVALID_HANDLE_VALUE if it fails. If fHandle <> INVALID_HANDLE_VALUE Then Dim j As Integer j = 0 fSuccess = WriteFile(fHandle, anArray(j), _ BytesToWrite, lBytesWritten, 0) 'Check to see if you were successful writing the data If fSuccess <> INVALID_HANDLE_VALUE Then ' 'Flush the file buffers to force writing of the data. fSuccess = FlushFileBuffers(fHandle) 'Close the file. fSuccess = CloseHandle(fHandle) End If End If End Sub FORM1: Private Sub Form_Load() FILE_NAME = "E:\CESHI.TXT" End Sub Private Sub Command1_Click() '写按钮 T(0).banci = 12345 T(0).xingming = "张三李四" writearray FILE_NAME, T 'Write the entire array to disk End Sub Private Sub Command2_Click() 'Define another large array ' S(0).xingming = "" readArray FILE_NAME, S 'Read into a different array Text1.Text = S(0).xingming End Sub
舉杯邀明月 2018-04-28
  • 打赏
  • 举报
回复
引用 6 楼 sandjuanjuan 的回复:
[quote=引用 1 楼 Chen8013 的回复:] 你的API声明 or 使用不恰当。 把你的代码贴出来………… 一般来说,你要处理“String数据”的话,那个“缓冲区”你得用字节数组中转一下。
如果你有简单的实例,能不能发个看一下。我并不是专业程序员,我是做工控的,有客户有这个需求了,我才接触了VB语言。都是百度出来了………………[/quote] 刚才看一下,你的“代码”根本不能运行吧! 在 Command1_Click() 中,调用:  writearray FILE_NAME, T  按 Sub writearray( )的定义,这儿的第2个参数,要求是“字符串数组”;  而你的变量 T ,类型是 MyType 。 根本就是“类型不匹配”的。 在 Command2_Click() 中,调用 readArray FILE_NAME, S 也是同样的错误! 另外再说一点: 即使把 writearray( ) 、readArray( ) 的第2个参数类型改为“MyType”,也不能保证正常的数据 读/写, 因为“直接”以你这种方式传递 MyType类型的数据给API,无法保证 读/写的长度(字节数)。
sandjuanjuan 2018-04-28
  • 打赏
  • 举报
回复
引用 3 楼 zhao4zhong1 的回复:
strconv
请问是不是这样赋值:T(0).xingming=StrConv("张三", vbFromUnicode)?
sandjuanjuan 2018-04-28
  • 打赏
  • 举报
回复
谢谢各位的回复,我把代码贴出来,请参阅。 模块里的代码如下: Public FILE_NAME As String Public Const GENERIC_WRITE = &H40000000 Const GENERIC_READ = &H80000000 Const FILE_ATTRIBUTE_NORMAL = &H80 Const CREATE_ALWAYS = 2 Const OPEN_ALWAYS = 4 Const INVALID_HANDLE_VALUE = -1 Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, _ lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, _ lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long Private Declare Function CloseHandle Lib "kernel32" ( _ ByVal hObject As Long) As Long Private Declare Function WriteFile Lib "kernel32" ( _ ByVal hFile As Long, lpBuffer As Any, _ ByVal nNumberOfBytesToWrite As Long, _ lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long Private Declare Function CreateFile Lib "kernel32" _ Alias "CreateFileA" (ByVal lpFileName As String, _ ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, _ ByVal lpSecurityAttributes As Long, _ ByVal dwCreationDisposition As Long, _ ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) _ As Long Private Declare Function FlushFileBuffers Lib "kernel32" ( _ ByVal hFile As Long) As Long Type MyType banci As Integer xingming As String End Type Public T(0) As MyType Public S(0) As MyType Public Sub readArray(Fname As String, anArray() As String) Dim fHandle As Long Dim fSuccess As Long Dim lBytesRead As Long Dim BytesToRead As Long ' 'Get size of data to write BytesToRead = (UBound(anArray) + 1) * LenB(anArray(0)) ' 'Get a handle to a file Fname. fHandle = CreateFile(Fname, GENERIC_WRITE Or GENERIC_READ, _ 0, 0, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0) 'Here you should test to see if you get a file handle or not. 'CreateFile returns INVALID_HANDLE_VALUE if it fails. If fHandle <> INVALID_HANDLE_VALUE Then fSuccess = ReadFile(fHandle, anArray(0), _ BytesToRead, lBytesRead, 0) 'ReadFile returns a non-zero value if it is successful. 'Now you just close the file. fSuccess = CloseHandle(fHandle) End If End Sub Public Sub writearray(Fname As String, anArray() As String) Dim fHandle As Long Dim fSuccess As Long Dim lBytesWritten As Long Dim BytesToWrite As Long 'Get the length of data to write BytesToWrite = LenB(anArray(iii)) + BytesToWrite 'Get a handle to a file Fname. fHandle = CreateFile(Fname, GENERIC_WRITE Or GENERIC_READ, _ 0, 0, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0) 'Here you should test to see if you get a file handle or not. 'CreateFile returns INVALID_HANDLE_VALUE if it fails. If fHandle <> INVALID_HANDLE_VALUE Then fSuccess = WriteFile(fHandle, anArray(0), _ BytesToWrite, lBytesWritten, 0) 'Check to see if you were successful writing the data If fSuccess <> INVALID_HANDLE_VALUE Then ' 'Flush the file buffers to force writing of the data. fSuccess = FlushFileBuffers(fHandle) 'Close the file. fSuccess = CloseHandle(fHandle) End If End If End Sub 窗口FORM1里的代码如下: Private Sub Form_Load() FILE_NAME = "E:\CESHI.TXT" End Sub Private Sub Command1_Click() '写按钮 T(0).banci = 1 T(0).xingming = "张三" writearray FILE_NAME, T 'Write the entire array to disk End Sub Private Sub Command2_Click() 'Define another large array readArray FILE_NAME, S 'Read into a different array Text1.Text = S(0).xingming End Sub FORM1里有三个控件:一个写按钮,一个读按钮,一个显示。
sandjuanjuan 2018-04-28
  • 打赏
  • 举报
回复
引用 1 楼 Chen8013 的回复:
你的API声明 or 使用不恰当。 把你的代码贴出来………… 一般来说,你要处理“String数据”的话,那个“缓冲区”你得用字节数组中转一下。
如果你有简单的实例,能不能发个看一下。我并不是专业程序员,我是做工控的,有客户有这个需求了,我才接触了VB语言。都是百度出来了………………
xzjxucxx 2018-04-25
  • 打赏
  • 举报
回复
代码贴出来。。。。。。。。。。
vansoft 2018-04-24
  • 打赏
  • 举报
回复
文件编码格式。
赵4老师 2018-04-24
  • 打赏
  • 举报
回复
strconv
舉杯邀明月 2018-04-23
  • 打赏
  • 举报
回复
你的API声明 or 使用不恰当。 把你的代码贴出来………… 一般来说,你要处理“String数据”的话,那个“缓冲区”你得用字节数组中转一下。

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧