当文件的定位区域小于2g时用下面的方式就可以正确定位
SetFilePointer hdlSRCFile, NowsSart, ByVal 0&, FILE_BEGIN
当定位区域超过2g时也就是nowstart的数值大于2g时,就会溢出,看了一下网上的说明,SetFilePointer可以用高低位的方式为定位超2g的文件支持64bit
但小弟不知这个高低位应该是怎么算出来呢?
在SetFilePointer hdlSRCFile, NowsSart, ByVal 0&, FILE_BEGIN
中应该怎么写呢?例如nowstart现在的值需要为2146959360也就是说超过2g时,直接将nowstart设为该值,肯定要益出,那么设成高低位该怎么写呢
还望高人们写个简单的例子就成了。。小弟感激不尽啊。

解决方案 »

  1.   

    阿门,谁说超过2G会溢出Long型的正数最大可以表示到 2147483647超过这个的部分放到后面的那个高位参数去
      

  2.   

    嗯???该怎么用呢??
    SetFilePointer hdlSRCFile, NowsSart,2146959360, FILE_BEGIN
    这样???那前面该填什么呢?
    小弟对于变量之类的东东还有数学基础很差,还望高人指点。
      

  3.   

    比如开始位应该是2146959360
    是否应该这样呢?
    SetFilePointer hdlSRCFile, 2147483647,2146959360-2147483647, FILE_BEGIN 
    我这样写好向没有益出,但结果好向不对。。
      

  4.   

    这篇文章可以很好地回答你的问题http://www.codeguru.com/cpp/w-p/files/fileinformation/article.php/c12917__1/
      

  5.   

    lDistanceToMove和lpDistanceToMoveHigh组合起来就是一个64位的值,是不是就是所谓的INT_64?
      

  6.   

    55~~~~我开始在baidu上也搜索到了这个贴子并且还下载了例子代码,其中有几段
    看起来就是Size2Long Position, PosL, PosH这里是关键,可我怎么看它们之间也没办法联系起来呀,都是sub没有返回参数。posl,posh是从哪里来的呢????55~~~~~~高人要是能提醒一下就好了。Size2Long关键应该就是在这里,可我看里面的ByRef LongLow As Long, ByRef LongHigh As Long并没有输出啊。真的是搞不明白了,,,,Public Sub API_ReadFile(ByVal FileNumber As Long, ByVal Position As Currency, ByRef BlockSize As Long, ByRef Data() As Byte)
    Dim PosL As Long
    Dim PosH As Long
    Dim SizeRead As Long
    Dim Ret As Long
    Size2Long Position, PosL, PosH
    Ret = SetFilePointer(FileNumber, PosL, PosH, FILE_BEGIN)
    Ret = ReadFile(FileNumber, Data(0), BlockSize, SizeRead, 0&)
    BlockSize = SizeRead
    End SubPrivate Sub Size2Long(ByVal FileSize As Currency, ByRef LongLow As Long, ByRef LongHigh As Long)
    '&HFFFFFFFF unsigned = 4294967295
    Dim Cutoff As Currency
    Cutoff = 2147483647
    Cutoff = Cutoff + 2147483647
    Cutoff = Cutoff + 1 ' now we hold the value of 4294967295 and not -1
    LongHigh = 0
    Do Until FileSize < Cutoff
        LongHigh = LongHigh + 1
        FileSize = FileSize - Cutoff
    Loop
    If FileSize > 2147483647 Then
        LongLow = -CLng(Cutoff - (FileSize - 1))
    Else
        LongLow = CLng(FileSize)
    End If
    End SubPrivate Sub Long2Size(ByVal LongLow As Long, ByVal LongHigh As Long, ByRef FileSize As Currency)
    Dim Cutoff As Currency
    Cutoff = 2147483647
    Cutoff = Cutoff + 2147483647
    Cutoff = Cutoff + 1
    FileSize = Cutoff * LongHigh
    If LongLow < 0 Then
        FileSize = FileSize + (Cutoff + (LongLow + 1))
    Else
        FileSize = FileSize + LongLow
    End If
    End Sub
      

  7.   

    这几天为2g以上文件的,下载,获取进度,获取总大小,本地总大小,等等问题是调了又调试了又试,现在暂时就只差这一个问题了。SetFilePointer定位超过2g以后的内容到底是该如何操作呢。。唉,人感觉很疲惫,脑袋都不好使了。还望高人,有个简单的程序写法方面的提示,真心的说声谢谢。
      

  8.   

    我试了一下这样。
    FileKB是Currency变量
    并且filekb=大于2g的数
    用此种方法Size2Long filekb, LongLow, LongHigh
    SetFilePointer hdlSRCFile, LongLow, LongHigh, FILE_BEGIN
    Private Sub Size2Long(ByVal FileSize As Currency, ByRef LongLow As Long, ByRef LongHigh As Long)
    '&HFFFFFFFF unsigned = 4294967295
    Dim Cutoff As Currency
    Cutoff = 2147483647
    Cutoff = Cutoff + 2147483647
    Cutoff = Cutoff + 1 ' now we hold the value of 4294967295 and not -1
    LongHigh = 0
    Do Until FileSize < Cutoff
        LongHigh = LongHigh + 1
        FileSize = FileSize - Cutoff
    Loop
    If FileSize > 2147483647 Then
        LongLow = -CLng(Cutoff - (FileSize - 1))
    Else
        LongLow = CLng(FileSize)
    End If
    End Sub
    结果是 LongLow = -CLng(Cutoff - (FileSize - 1))益出。。
    唉。上帝。 
      

  9.   

    Sub Main()
        Dim hdlSRCFile As Long
        Dim NowsStart As Currency
        Dim lMoveLo As Long, lMoveHi As Long
        ...
        NowsStart = 3146959360@ '假定这是你要定位的位置
        Size2Long NowsStart, lMoveLo, lMoveHi '用你7楼的函数转换
        
        SetFilePointer hdlSRCFile, lMoveLo, lMoveHi, FILE_BEGIN
    End Sub
      

  10.   

    1. 64位大整数
    顾名思义,就是64位、8字节长的数据类型
    在某些高级语言中有专门相对应的类型
    在系统API中,有专门的LARGEINTEGER等结构来存放这种数
    但不幸的是,VB中没有所谓的int64类型2. Currency类型
    在VB中,与64位大整数的性质最相似的数据类型就是Currency了
    Currency是一个可以用来存储64位大整数的,比较理想的基本数据类型。
    Currency的取值范围是-922,337,203,685,477.5808 到 922,337,203,685,477.5807,
    在内存中的表示形式为从 &H8000000000000000 到 &H7FFFFFFFFFFFFFFF
    但是要注意的是,该类型数值的最后四位在VB中表现为小数部分,因此,你虽然在使用该类型进行计算时可以不去理会小数点,但在表现时却要将其乘上10000,变为整数3. 大文件处理
    首先,文件大小、指针位置等需要用到64位大整数的地方都改用 Currency。其次,在实际使用时,或采取公式
    函数中的移动距离 = 移动距离/10000,以配合Currency类型的特质以下为代码:首先是Currency类型和LARGEINTEGER结构之间的转换。这个东西比较简单,因为两个东西的内存布局是完全一样的,所以拿出CopyMemory即可。'货币类型转换为大整数结构
    Public Function Currency2LargeInteger(ByVal curDistance As Currency) As LARGE_INTEGER
        CopyMemory Currency2LargeInteger, curDistance, 8
    End Function
    '大整数结构转换为货币类型
    Public Function LargeInteger2Currency(li As LARGE_INTEGER) As Currency
        CopyMemory LargeInteger2Currency, li, 8
    End Function接下去是对SetFilePointer的小小封装,参照了MSDN中的建议:Public Function MySeek(ByVal hFile As Long, ByVal curDistance As Currency, ByVal lMoveMethod As Long) As Currency
        Dim li As LARGE_INTEGER
        li = Currency2LargeInteger(curDistance)
        li.lowpart = SetFilePointer(hFile, li.lowpart, li.highpart, lMoveMethod)
        
        If li.lowpart = -1 Or Err.LastDllError <> 0 Then
            li = Currency2LargeInteger(-1@)
        End If
        
        MySeek = LargeInteger2Currency(li)
        
        Debug.Print "Seek to "; Hex(li.highpart); Hex(li.lowpart)
    End Function
      

  11.   

    这里是完整实现代码及测试代码模块中的代码Option Explicit
    Public Const MOVEFILE_REPLACE_EXISTING = &H1
    Public Const FILE_ATTRIBUTE_TEMPORARY = &H100
    Public Const FILE_BEGIN = 0
    Public Const FILE_SHARE_READ = &H1
    Public Const FILE_SHARE_WRITE = &H2
    Public Const CREATE_NEW = 1
    Public Const OPEN_EXISTING = 3
    Public Const GENERIC_READ = &H80000000
    Public Const GENERIC_WRITE = &H40000000Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length 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 Any) As Long
    Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) 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 Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
    Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Public Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
    Public Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long
    Public Declare Function SetEndOfFile Lib "kernel32" (ByVal hFile As Long) As Long
    ' 32 bit
    'signed int
    '1000 0000 0000 0000 0000 0000 0000 0000
    '   =
    '8000 0000 -> -2147483648
    '
    '0111 1111 1111 1111 1111 1111 1111 1111
    '   =
    '7FFF FFFF -> 0 ~ 2^31-1 2147483647
    '
    'unsigned int
    '1111 1111 1111 1111 1111 1111 1111 1111
    '   =
    'FFFF FFFF -> 0 ~ 2^32-1 4294967295
    '
    ' 64 bit
    'signed int
    '1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
    '   =
    '8000 0000 0000 0000 -> -9223372036854775808
    '
    '0111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
    '   =
    '7FFF FFFF FFFF FFFF -> 0 ~ 2^63-1 9223372036854775807
    '                      VB Currency 922337203685477.5807
    '
    'unsigned int
    '1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
    '   =
    'FFFF FFFF FFFF FFFF -> 0 ~ 2^64-1 18446744073709551615
    Public Type LARGE_INTEGER
        lowpart As Long
        highpart As Long
    End TypePublic Function Currency2LargeInteger(ByVal curDistance As Currency) As LARGE_INTEGER
        CopyMemory Currency2LargeInteger, curDistance, 8
    End FunctionPublic Function LargeInteger2Currency(li As LARGE_INTEGER) As Currency
        CopyMemory LargeInteger2Currency, li, 8
    End FunctionPublic Function MyOpen(ByVal sFileName As String) As Long
        MyOpen = CreateFile(sFileName, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, 0, 0)
    End FunctionPublic Function MySeek(ByVal hFile As Long, ByVal curDistance As Currency, ByVal lMoveMethod As Long) As Currency
        Dim li As LARGE_INTEGER
        li = Currency2LargeInteger(curDistance)
        li.lowpart = SetFilePointer(hFile, li.lowpart, li.highpart, lMoveMethod)
        
        If li.lowpart = -1 Or Err.LastDllError <> 0 Then
            li = Currency2LargeInteger(-1@)
        End If
        
        MySeek = LargeInteger2Currency(li)
        
        Debug.Print "Seek to "; Hex(li.highpart); Hex(li.lowpart)
    End Function这里是窗体测试代码,我测试读取了一个2.38G的页面文件,偏移量2451374078处1个字节的内容Option Explicit
    Private Sub Command1_Click()
        Dim hFile As Long
        hFile = MyOpen("c:\pagefile2.sys")
        If hFile Then
            Dim curPos As Currency
            curPos = 2451374078@
            Debug.Print MySeek(hFile, curPos / 10000@, FILE_BEGIN)
            
            Dim b As Byte, lBytesRead As Long
            ReadFile hFile, b, 1, lBytesRead, ByVal 0
            Debug.Print b
            CloseHandle hFile
        End If
    End Sub
      

  12.   

    谢谢大家对我的帮助,今天中午时在gogole发现了一段代码,是国外一个论坛的,试了一下好用。
    特意转了进来,以后再有朋友有类似困扰就方便了,,,,,希望对大家有用。
    '超过2g时利用指针定位SetFilePointer
    Private Function SeekPosDouble(ByVal FHandle As Long, ByVal NewPos As Double) As Boolean
    Dim SizeLow As Long, SizeHigh As Long
    SizeLow = DoubleToLongs(NewPos, SizeHigh)
    SeekPosDouble = SeekPos(FHandle, SizeLow, SizeHigh)
    End FunctionPrivate Function SeekPos(ByVal FHandle As Long, ByVal NewPos As Long, Optional ByVal PosHigh As Long = 0) As Boolean
    Dim Ret As Long, dwError As Long
    Ret = SetFilePointer(FHandle, NewPos, PosHigh, FILE_BEGIN)If Ret = -1 Then
    dwError = GetLastError
    If dwError = NO_ERROR Then SeekPos = True
    Else
    SeekPos = True
    End IfEnd FunctionPrivate Function DoubleToLongs(ByVal Dbl As Double, ByRef SizeHigh As Long) As Long
    Dim SizeLowDbl As Double
    SizeHigh = Fix(Dbl / 4294967296#)
    SizeLowDbl = Dbl - SizeHigh * 4294967296#
    If SizeLowDbl > 2147483647 Then
    DoubleToLongs = CLng(SizeLowDbl - 2147483648#) Xor &H80000000
    Else
    DoubleToLongs = SizeLowDbl
    End If
    '---------------------------------------
    End Function
      

  13.   

    补一句,使用方法是SeekPosDouble 句柄,起点
    然后后面的模块会将SetFilePointer 移到起点位置YES!!!!头疼的问题终于解决了,另外今天14点时,跟朋友反复调试,居然发现我下载时的数据超2g时crc校验不正确居然是因为控件版本没有正确换成最新的当时图方便用迅雷下载的控件,结果。。该死的。迅雷,害人啊此问题及FTP下载超2g问题搞了我正正2天。终于。YES了!
      

  14.   

    DWORD SetFilePointer(
      HANDLE hFile,                // handle to file
      LONG lDistanceToMove,        // bytes to move pointer
      PLONG lpDistanceToMoveHigh,  // bytes to move pointer
      DWORD dwMoveMethod           // starting point
    );
    最後一個參數 可以有三值值
    FILE_BEGIN  從開頭
    FILE_CURRENT 從當前位 置  
    FILE_END    從文件尾,如果大於 4G,可以先用 SetFilePointer 把位置定到 4 G, 再用 SetFilePointer + FILE_CURRENT 再加一個新的位置上去
    更簡單的方法是用
    BOOL SetFilePointerEx(
      HANDLE hFile,                    // handle to file
      LARGE_INTEGER liDistanceToMove,  // bytes to move pointer
      PLARGE_INTEGER lpNewFilePointer, // new file pointer
      DWORD dwMoveMethod               // starting point
    );
      

  15.   

    用内存映射文件吧,不要折磨这些API了
      

  16.   

    啊。。15楼的朋友早说就好了啊。原来还可以这样的啊。。晕死。那我过2g时不就可以先移动到2g,再从当前位置移动到任意位置就使现了超2g?晕
    16楼的朋友,内存影射对这些大文件也能高效么?????现在小弟还处于初学阶段,对这些还不甚了解