[BlueDog] 我写了一个二进制文件读写提速类,不知道有没有用呀。

BlueDog 2005-02-03 10:04:28
方法
Create
PutByte
GetByte
FSeek
与VB自带的Put Get比较了一下
在我的机器上测试,GetByte 比Get方法约快20倍左右
PutByte 比Put方法约快50倍左右

...全文
434 41 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
BlueDog 2005-03-03
  • 打赏
  • 举报
回复
呵呵,好久没来了,一看居然有这么多高手回复。

其实也没什么,就是减少硬盘的读写次数。
之所以定成512字节,是因为这是磁盘的基本单元。
你爱用就用,不用拉倒。呵呵。
yaveymao 2005-02-23
  • 打赏
  • 举报
回复
几乎没什么用,如果为了性能我干嘛不用C写DLL给VB用?
zyl910 2005-02-22
  • 打赏
  • 举报
回复
最小4K

因为FAT簇与内存页都是4K的
flyingscv 2005-02-22
  • 打赏
  • 举报
回复
如果用GetByte 遍历文件,和用Get8k8k的读有1.1倍的差距就可以发表了
8k也许大了,1k1k的也行
cleogo 2005-02-22
  • 打赏
  • 举报
回复
能提供测试结果吗? 包括兼容性与速度,我想比较一下再决定是否购买...

我这里用API读文件:(机器配置: 450兆cpu, PII,256兆内存,win2000Pro);
40兆文件(read),总计耗时2650ms(粗测,按Byte读入)
8兆文件(Read),总计耗时289ms.(粗测,按Byte读入)
2兆文件(Read),总计耗时65ms.(粗测,按Byte读入)
1兆文件(Read),总计耗时29 - 35ms左右.(粗测,按Byte读入)
上面是利用标准API OpenFile,ReadFile的测试结果
nik_Amis 2005-02-22
  • 打赏
  • 举报
回复
hehe
zyl910 2005-02-22
  • 打赏
  • 举报
回复
对于复制硬盘上文件而言
由于FAT32的的簇大小一般为4KB
所以缓冲区应该是4KB的倍数

一般来说
缓冲区越大速度越快
但是对于现在的计算机系统
8MB以上的缓冲区提速效果可以忽略不计

如果是单纯的读文件
文件映射是最好的方法
这是操作系统利用虚拟内存实现的
效率是最高的
而且不占内存、有很好的cache性能


如果真的想达到复制文件的极限的话
想办法进Ring0
直接访问硬盘控制器
控制DMA让数据在硬盘与物理内存之间交换
不响应其他硬件
完全占有系统总线
这样速度是最快的,但是无法执行其他任务(Windows的多任务优势就这样丢掉了)

qiqi5521 2005-02-22
  • 打赏
  • 举报
回复
to:viena
我也是菜鸟,做 2 进制处理的时间不长,有些认识也很片面,愿共同探讨。
整个文件一次性读取,在某些场合也是个不错的方法,处理小文件很不错,就像我说的做离线增量升级包,体现了够用就好的原则。只是出于习惯,我不爱用这个方法,所以几乎没用过,等我以后试试再发表意见吧。

循环读取的好处就是可以适应任意大小的文件。

其实处理文件的软件分两类,一类是专门同文件打交道的,我不说也可以想到,WinRAR,WinZip之类;
另一类是处理文件只是它的附属功能,像离线增量升级包。
前者通常需要处理各种大小的文件,那么
循环读取是它不二的选择;
至于后者,通常都是处理固定的几个文件,都是能预知大小的,应该本着够用就好的原则,选自己爱用的,顺手的方法就可以了。
viena 2005-02-21
  • 打赏
  • 举报
回复
我没有读写过很大的文件~
viena 2005-02-21
  • 打赏
  • 举报
回复
我是菜鸟,不太懂,缓冲区到底起什么作用?
我以前二进制读写文件都是Byte数组直接设为文件的长度(lof得到字节数-1),用一个get或put语句就可解决,读几十兆的文件都没有问题,我不明白循环读取到底有什么优势,是否文件很大的时候能提高效率呢?

楼上或其他的高手能否给解释一下?
lang_csdn 2005-02-21
  • 打赏
  • 举报
回复
关注.
qiqi5521 2005-02-20
  • 打赏
  • 举报
回复
昨天没有说完,今天闲了下来,比较一下几种方法,列个表

代码可复用度 性能 使用的方便性
免维护缓冲区 高 较低 随场合不同,有很大差异
半维护缓冲区 中 高 大部分情况下很方便
手工维护缓冲区 低 极高 随场合不同,有很大差异

呵呵,这么个小问题,如果我再说下去就显得太罗嗦了。只是我看了最前面的较为火药味的争论,觉得有必要说这些:萝卜白菜各有所爱,这纯属每个人的风格不同,谈不上谁对谁错的问题。
qiqi5521 2005-02-19
  • 打赏
  • 举报
回复
说实话,putbyte写的不错,楼主的 GetByte 写得不是很好,太多的判断语句,造成了很大的瓶颈。其实没必要用api函数,反而变得复杂了。

看一下我的代码,没有用api函数,GetByte快了一些:http://lqweb.crcoo.com/mycode/AutoFastFileB.rar

这个类其实还是有用的,但应用面比较窄,其实说白了就是个“免维护缓冲区”,对于上层程序来说,缓冲区是不可见的,不需要维护的,它的特点就是用起来快捷方便,运行时性能还过得去。一旦经过了
充分的测试,就可以签入“可复用代码库”,方便以后复用。

目前我在两种场合用到了它:1。编写自动化测试工具,这种东西不会发布,又很难写的通用,一般用完就扔。能写快点就写快点,对性能没太大要求。
2.处理小文件。我给我的程序写了一个离线增量升级包,方便用户升级。这个包的大小不会超过2M去,
因此用这个足够快了,而且为了让用户看清拷贝了哪些文件,我还故意延时了 2 秒呢。

当然了,个人性格不同,并不是所有人都喜欢这样用:)

我现在比较喜欢用“半维护缓冲区”,既方便性能又高,开源交流一下吧:
http://lqweb.crcoo.com/mycode/FileReadBlock2.rar
homezj 2005-02-17
  • 打赏
  • 举报
回复
无意中测试了楼主Blog中的代码。的确很慢!
在我的机器上复制同一个1.8M的文件,用类为3.6秒,逐字节为7.8秒。
还有,复制的目标文件存在时,会出现丢失字节的现象。

而我临时写了个过程,复制上述文件只用0.07秒。Api的CopyFile或VB的FileCopy大致也是这个速度。

一时不太明白这个类可能的用途?
viena 2005-02-06
  • 打赏
  • 举报
回复
支持楼主,
封装为类,方便了我这样的菜鸟,呵呵~
只是有点小问题,是否文件名不能包含空格?我放在桌面上,打开文件就出错了~
BlueDog 2005-02-05
  • 打赏
  • 举报
回复
Chice_wxg(学)(习) 讲的倒是不错,不过我想你没有自已动手写一个试试。效率提不提高了,呵呵,等会我放出代码来,大家试试就好了。请访问我的blog
blog.csdn.net/BlueDog
至于MapViewOfFile能多大程度提高速度,你可以再仔细看看map file的机制
如果真的要求极速访问,自已动手分配内存,呵呵。
thirdapple 2005-02-05
  • 打赏
  • 举报
回复
Chice难得这么有兴致哦,这方面我没什么了解,发不了言
BlueDog 2005-02-05
  • 打赏
  • 举报
回复
呵呵,上面的老兄,你的第三种方法就是我现在的方法的基础,但是你认为你这种方式,在编程时很方便么,如果很方便的话我也就不说什么了。
至于说“逐字节读写文件编程的方便性”有什么用,也许你不需要,并不代表别人不需要
好了。如果大家觉得这个代码有用的话,发个E-mail告诉我。呵呵
xtlxs1976@163.com
Chice_wxg 2005-02-05
  • 打赏
  • 举报
回复


我还是那句话,


针对不同的方式采取特定的缓冲方式才能有更好的效果,不是一个通用类能解决的。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
或者说,一个通用方法用在不同需求下,绝大多数情况下效率更差。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



希望你能明白这一点。



Chice_wxg 2005-02-05
  • 打赏
  • 举报
回复
to BlueDog() ( ) 信誉:83

我觉得你有句话说的很好:“你试试代码再发言吧,呵呵”

这句话对你是很合适的,你自己的代码肯定没经过多少测试


可惜我最近很忙,也没多少时间来CSDN,

不过为了证明你的错误我随便写了点代码,你看看到底哪个效率高吧!


PS: 你的代码风格不错,技术也不错,但你如果不把精力放在这种没意义的劳动上或许会更好一点。
而且靠代码卖钱也不是这样卖的,呵呵



测试代码,自己看吧。



Option Explicit

Private cfb1 As CFileBuff
Private cfb2 As CFileBuff
Private fh1 As Long
Private fh2 As Long

Private Sub Command1_Click()
Dim fn1 As String
Dim fn2 As String
Dim fn3 As String
Dim fn4 As String
Dim ch As Byte
Dim i As Long
Dim st1 As Single, et1 As Single
Dim st2 As Single, et2 As Single
Dim st3 As Single, et3 As Single
Dim st4 As Single, et4 As Single
Dim st5 As Single, et5 As Single

fn1 = App.Path & "\D.DAT"
fn2 = App.Path & "\D.BAK"
fn3 = App.Path & "\D.BAK2"
fn4 = App.Path & "\D.BAK3"

st1 = Timer
Set cfb1 = New CFileBuff
Set cfb2 = New CFileBuff

If cfb1.Create(fn1) = True Then
cfb2.Create (fn2)
Do

If cfb1.GetByte(ch) = 1 Then

cfb2.PutByte ch
Else
Exit Do
End If
Loop While cfb1.FEof = False

Else
Debug.Print "Error Open File!"
End If
Set cfb1 = Nothing
Set cfb2 = Nothing
et1 = Timer



st2 = Timer
fh1 = FreeFile(0)
Open fn1 For Binary As fh1

fh2 = FreeFile(0)
Open fn3 For Binary As fh2
Do
Get fh1, , ch
Put fh2, , ch
Loop While EOF(fh1) = False
Close fh1
Close fh2
et2 = Timer






'===================================
st3 = Timer
fh1 = FreeFile(0)
Open fn1 For Binary As fh1

fh2 = FreeFile(0)
Open fn4 For Binary As fh2


Const MAX_BUF_SIZE As Long = 1024& * 1024&
Dim nBufSize As Long
Dim bBuf() As Byte
Dim nFileLen As Long

Dim nCurPos As Long

nFileLen = FileLen(fn1)
nBufSize = nFileLen
If (nBufSize > MAX_BUF_SIZE) Then nBufSize = MAX_BUF_SIZE
ReDim bBuf(MAX_BUF_SIZE - 1)

For nCurPos = 0 To nFileLen - 1 Step MAX_BUF_SIZE
If nFileLen - nCurPos < MAX_BUF_SIZE Then
ReDim bBuf(nFileLen - nCurPos - 1)
End If
Get #fh1, , bBuf
Put #fh2, , bBuf
Next
Close fh1
Close fh2
et3 = Timer



MsgBox CStr(et1 - st1) & " " & CStr(et2 - st2) & " " & CStr(et3 - st3)




MsgBox "Random Test!"



Const RANDOM_COUNT = 1000000
'===================================
st4 = Timer
Set cfb1 = New CFileBuff
If cfb1.Create(fn1) = True Then
For i = 0 To RANDOM_COUNT
cfb1.FSeek Rnd * nFileLen, FS_BEGIN
cfb1.GetByte ch
Next

End If
Set cfb1 = Nothing
et4 = Timer



st5 = Timer
fh1 = FreeFile(0)
Open fn1 For Binary As fh1
nFileLen = FileLen(fn1)
For i = 0 To RANDOM_COUNT
Seek #fh1, Rnd * nFileLen
Get #fh1, , ch
Next
Close fh1
Close fh2
et5 = Timer

MsgBox CStr(et4 - st4) & " " & CStr(et5 - st5)



Debug.Print "Success!"
End Sub
加载更多回复(21)

7,785

社区成员

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

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