VB读取大文件的问题

苦寒 2010-12-13 12:35:04
我通过循环执行Get #1, , Byt_sBuffer语句来实现对文件的读操作,其中Byt_sBuffer()是一个字节型数组。当文件比较小的时候,这个语句没有任何问题,可以正常执行。但现在的问题是:一旦文件大小超过2G,随着文件记录号的增加,记录号最终会超过2147483647,即Long型数据的表示范围,这时就程序就会报错。因为在Get语句中,文件记录号默认就是Long型,所以我也无法另外使用双精度型数据类型来代替。这个问题该如何解决呢??
...全文
393 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
sorry……贴错代码了。

Option Explicit
Const GENERIC_READ = &H80000000
Const FILE_SHARE_READ = &H1
Const OPEN_EXISTING = 3
Const FILE_TYPE_CHAR = &H2
Const FILE_TYPE_DISK = &H1
Const FILE_TYPE_PIPE = &H3
Const FILE_TYPE_UNKNOWN = &H0
Private Declare Function GetFileType Lib "kernel32" (ByVal hFile As Long) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function GetFileSizeEx Lib "kernel32" (ByVal hFile As Long, lpFileSize As Currency) As Boolean
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Sub Form_load()
Debug.Print GetBigSize("i:\c_pan.gho")
End Sub

Public Function GetBigSize(ByVal PathName As String) As Currency
Dim hFile As Long, nSize As Currency
hFile = CreateFile(PathName, GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, ByVal 0&, ByVal 0&)
GetFileSizeEx hFile, nSize
CloseHandle hFile
GetBigSize = nSize * 10000
End Function


试试这个
苦寒 2010-12-27
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 of123 的回复:]
超过 2G 的超大文件,不要用 Get, Put 处理,必须要 API:

Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpS……
[/Quote]

这个不错,非常感谢各位的关注。
苦寒 2010-12-27
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 yiguangqiang88 的回复:]
VB code
Dim BytDate() As Byte
Dim FileName As String
Dim lngFile As Long
Dim i As Long
lngFile = FileLen(PutFileName) \ 8192 '取得文件长度
……
[/Quote]

这段代码不行,因为FileLen()函数返回值是长整型,大于2G的文件,它就得返回一个负值。
  • 打赏
  • 举报
回复
    Dim BytDate() As Byte
Dim FileName As String
Dim lngFile As Long
Dim i As Long
lngFile = FileLen(PutFileName) \ 8192 '取得文件长度
For i = 0 To lngFile
ReDim myfile(8191) As Byte '初始化数组
Open PutFileName For Binary As #1 '打开文件
Get #1, i * 8192 + 1, myfile '将文件写入数组
Close #1 '关闭文件
DoEvents
Next i



这个代码似乎读3G的文件都没问题。。。
of123 2010-12-14
  • 打赏
  • 举报
回复

超过 2G 的超大文件,不要用 Get, Put 处理,必须要 API:

Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long

Public Declare Function GetFileType Lib "kernel32" (ByVal hFile As Long) As Long

Public Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long

Public Declare Function GetFileSizeEx Lib "kernel32" (ByVal hFile As Long, lpFileSize As Currency) As Long

Public Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped 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 WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Long) As Long

Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Public Declare Function DeleteFile Lib "kernel32" Alias "DeleteFileA" (ByVal lpFileName As String) As Long

Public Declare Function CopyFile Lib "kernel32" Alias "CopyFileA" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal bFailIfExists As Long) As Long

Public Declare Function GetLastError Lib "kernel32" () As Long
dafu2003 2010-12-13
  • 打赏
  • 举报
回复
你把buffer弄大点不就行了。弄到512K 或 1M 都没问题的。

贝隆 2010-12-13
  • 打赏
  • 举报
回复
我觉得改成数据库是最好的办法。呵呵,有些跑题了。
edison_chen888 2010-12-13
  • 打赏
  • 举报
回复
跪求高手帮忙用VB+sql写个简单可以运行的《酒店客房管理系统》。
或发我邮箱里,zc2836995@126.com,在下感激不尽.
dafu2003 2010-12-13
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 dafu2003 的回复:]
引用 7 楼 yeosn 的回复:
引用 6 楼 dafu2003 的回复:
看来你的理解有问题啊。

redim sbuffer(512 * 1024)
get fd,,sbuffer

这样一次就是读512K字节的数据,怎么会是只读一个字节呢?


是这样的,我试过,如果它第一次读了512*1024字节,那么这时它的记录号就变成了512*1024,下一次它会从512*102……
[/Quote]

估计用winapi能行,你去找找有关的api函数吧。
dafu2003 2010-12-13
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 yeosn 的回复:]
引用 6 楼 dafu2003 的回复:
看来你的理解有问题啊。

redim sbuffer(512 * 1024)
get fd,,sbuffer

这样一次就是读512K字节的数据,怎么会是只读一个字节呢?


是这样的,我试过,如果它第一次读了512*1024字节,那么这时它的记录号就变成了512*1024,下一次它会从512*1024+1的位置开始读。第N次读取,就从(……
[/Quote]

你这样一说,倒成了我的理解问题了。
你的意思是vb内部读写文件大小的限制,如果是这样,估计vb就没法处理了。
苦寒 2010-12-13
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 dafu2003 的回复:]
看来你的理解有问题啊。

redim sbuffer(512 * 1024)
get fd,,sbuffer

这样一次就是读512K字节的数据,怎么会是只读一个字节呢?
[/Quote]

是这样的,我试过,如果它第一次读了512*1024字节,那么这时它的记录号就变成了512*1024,下一次它会从512*1024+1的位置开始读。第N次读取,就从(N-1)*512*1024+1的地方开始读,当(N-1)*512*1024+1大于了长整型变量的表示范围(因为文件记录号是用长整型表示的,是VB默认的,自己无法修改),就会出错,再也不能读取了。
dafu2003 2010-12-13
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 yeosn 的回复:]
引用 2 楼 dafu2003 的回复:
你把buffer弄大点不就行了。弄到512K 或 1M 都没问题的。


把buffer弄大了也不行啊,因为我是以binary方式打开的,不管一次读取多大范围的内容,它都是按“一个字节就是一个记录号”来算的。
[/Quote]

看来你的理解有问题啊。

redim sbuffer(512 * 1024)
get fd,,sbuffer

这样一次就是读512K字节的数据,怎么会是只读一个字节呢?
苦寒 2010-12-13
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 dafu2003 的回复:]
你把buffer弄大点不就行了。弄到512K 或 1M 都没问题的。
[/Quote]

把buffer弄大了也不行啊,因为我是以binary方式打开的,不管一次读取多大范围的内容,它都是按“一个字节就是一个记录号”来算的。
of123 2010-12-13
  • 打赏
  • 举报
回复

分块来读。例如,开 4K 缓存。

Dim Byt_sBuffer(4095)
东方之珠 2010-12-13
  • 打赏
  • 举报
回复
对于大文件,不要指望一次读完,一次写完。
要一块一块地读,一块一块地写!
推荐内存映射方式:
http://topic.csdn.net/u/20090731/08/63642fa7-d60d-4107-8e74-7cbe93e60f4f.html

7,763

社区成员

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

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