首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • SetFilePointer 回卷文件指针后,WriteFile 和 ReadFile 函数失败 [已结贴,结贴人:of123]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 13:48:57 楼主
    用 CreateFile 函数创建一个磁盘文件,写文件正常:
    hFile = CreateFile(strFileName, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, CREATE_NEW, 0, 0)

    现需要更新其文件头部分的一个 TLV 对象的 Value 域。从文件起始查找该对象成功(SetFilePointer 和 ReadFile)。

        ReadFile hFile, lngTmp, 4, ret, ByVal 0&
        If ret <> 4 Then Exit Function
       
        lngNumber = lngNumber + lngTmp    '这里正常
       
        ret = SetFilePointer(hFile, -4, 0, FILE_CURRENT)    ' ret 得到新的指针,本例 = 2
        ret = WriteFile(hFile, lngNumber, 4, n, ByVal 0&)    '这里出现问题

        '注:ret = 0(期望 1), n = 0(期望 4), GetLastError = 0

        '如果上面正常或跳过上面的写,执行下面的读
        ret = SetFilePointer(hFile, -4, 0, FILE_CURRENT)    ' ret 得到新的指针,本例 = 2
        ret = ReadFile(hFile, lngTmp, 4, n, ByVal 0&)    '这里出现问题

        '注:ret = 1(期望 1), n = 0(期望 4), GetLastError = 0
        '按照 MSDN 的说法,返回值 = 1 且 lpNumberofBytesRead = 0 表示指针超出可读区域。

    我现在的做法是绕过这一难题:

        ret = SetFilePointer(hFile, -4, 0, FILE_CURRENT)
        ret = SetFilePointer(hFile, ret, 0, FILE_BEGIN)
        ret = WriteFile(hFile, lngNumber, 4, n, ByVal 0&)
        '......
       
        ret = SetFilePointer(hFile, -4, 0, FILE_CURRENT)
        ret = SetFilePointer(hFile, ret, 0, FILE_BEGIN)
        ret = ReadFile(hFile, lngTmp, 4, n, ByVal 0&)

    这样可以正常读写。

    但是总觉得有点别扭,也奇怪为什么回卷指针后会出现这样的问题。
    300  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 15:50:291楼 得分:50
    高手的难题,不是一般的啊。

    我也没法理解为什么会有这个问题。

    Up...
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 16:15:532楼 得分:50
    你用了 CREATE_NEW 参数,但是上来就要读,好像不一致。
    要随机访问试试加上 FILE_FLAG_RANDOM_ACCESS 标志。

    还有VB本身就能操作二进制文件,为什么还要API?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 16:46:543楼 得分:0
    原来就是用的 Open, Get, Put 语句。但是用户要求文件大小可达 64 G。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 16:47:104楼 得分:40
    我通常都用Put , Get 的说。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 16:56:245楼 得分:0
    加了 FILE_FLAG_RANDOM_ACCESS ,问题依旧。

        hFile = CreateFile(strFileName, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0)
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 17:01:066楼 得分:40
    顶一个,,学习一下.............
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • myjian
    • 等级:
    发表于:2008-05-16 17:01:507楼 得分:0
    引用 3 楼 of123 的回复:
    原来就是用的 Open, Get, Put 语句。但是用户要求文件大小可达 64 G。


    真变态........单个文件就大于我的D分区了-_-
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 17:09:298楼 得分:40
    SetFilePointer怎么声明的?

    又:你所谓绕过的方式中第一个SetFilePointer是冗余的,它执行是否正确你根本没检查。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 17:18:519楼 得分:0
    Public Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long

    不完全是冗余的。因为我不能确定用户文件中该对象的位置,第一个 SetFilePointer 使我得到了当前指针位置,类似 Open 系统中的 Seek 函数,第二个 SetFilePointer 才可以从头偏移。

    目前发现,如果不将偏移量高位置为 Null 就行了。

        ' 找到该对象的 Value 域,读取
        ReadFile hFile, lngTmp, 4, ret, ByVal 0&
        If ret <> 4 Then Exit Function
       
        ' 计算新值
        lngNumber = lngNumber + lngTmp
       
        ret = SetFilePointer(hFile, -4, ByVal 0&, FILE_CURRENT)
        ret = WriteFile(hFile, lngNumber, 4, n, ByVal 0&)
        If n <> 4 Then Exit Function
       
        ret = SetFilePointer(hFile, -4, ByVal 0&, FILE_CURRENT)
        ret = ReadFile(hFile, lngTmp, 4, n, ByVal 0&)
        If n <> 4 Then Exit Function
       
        If lngTmp = lngNumber Then Update_Trace_File_Number_of_Traces_Ex = True

    大家可以继续讨论,晚一点结贴。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 17:28:1910楼 得分:40
    虽然不明白怎么用setfilepointer,不过我在老外的网站给找了有关资料,希望可以帮忙楼主。

    http://www.codeguru.com/vb/controls/vb_file/directory/article.php/c12917__3/
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 17:56:1811楼 得分:40
    引用 7 楼 myjian 的回复:
    引用 3 楼 of123 的回复:
    原来就是用的 Open, Get, Put 语句。但是用户要求文件大小可达 64 G。


    真变态........单个文件就大于我的D分区了-_-


    你的E分区呢? ^_^

    我的最大分区才60G。
    160G的硬盘(有点小 ^_^),分了6个分区。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 18:07:5512楼 得分:0
    明白了,MSDN 说:

    If lpDistanceToMoveHigh is not NULL, lpDistanceToMoveHigh and lDistanceToMove form a single 64-bit signed value that specifies the distance to move.

    If lpDistanceToMoveHigh is NULL, lDistanceToMove is a 32-bit signed value. A positive value for lDistanceToMove moves the file pointer forward in the file, and a negative value moves the file pointer back.

    实际上将 lpDistanceToMoveHigh 置为 ByVal 0& ,就是置为 Null。

    不过现在不这样做了:

        ' 找到该对象的 Value 域,读取
        n = SetFilePointer(hFile, 0, ByVal 0&, FILE_CURRENT) 
        ReadFile hFile, lngTmp, 4, ret, ByVal 0&
        If ret  <> 4 Then Exit Function
       
        ' 计算新值
        lngNumber = lngNumber + lngTmp
        Call SetFilePointer(hFile, n, 0, FILE_BEGIN)
        Call WriteFile(hFile, lngNumber, 4, ret, ByVal 0&)
        If ret  <> 4 Then Exit Function
       
        Call SetFilePointer(hFile, n, 0, FILE_BEGIN)
        Call ReadFile(hFile, lngTmp, 4, ret, ByVal 0&)
        If ret  <> 4 Then Exit Function
       
        If lngTmp = lngNumber Then Update_Trace_File_Number_of_Traces_Ex = True

    谢谢大家的提示。结贴。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-16 21:07:2613楼 得分:0
    你的执行语句与原来的也不一样了呀。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-19 08:50:0114楼 得分:0
    API中64位的值不多,到真是忘了它通过两个Long传递负数高位也要设置,所以应该是
    VBScript code
    ret = SetFilePointer(hFile, -4, -1, FILE_CURRENT)
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved