VB 关于读取文件字节的效率问题

dinojy2011 2011-03-24 02:03:12
有代码如下
dim a() as byte :dim b() as byte
open "C:\a.txt" for binary as #1 /90K的文件 这里代码运行,大概的时间是 3 - 4 秒
open "C:\b.txt" for binary as #2 /60K 的文件
redim a (1 to filelen("C:\a.txt") )
redim b (1 to filelen("C:\b.txt") )
dim strA as string ,strB as string ,i as long
'/--- 这里开始如何加大读取的效率
for i = 1 to ubound(a)
strA = strA + format(a(i),"000" '避免 '4' & '40' = '440' '44' & '0' = '440' 的情况
next i
for i = 1 to ubound(b)
strB = strB + format(a(i),"000"
next i
' 在实际应用,文件大概有 1M - 3M之间,这个速度让我很头痛
'/--- 这里结束
最终的目的是为了 instr(strA,strB)
如何提高读取的效率
而且 a.txt 和 b.txt 又不知道可不可以用读取字符串的方法来读取,据我观察应该是不可以的
假设 a.txt 中的文字为
"..中国人" 他的16进制用UltraEdit 看为 12 13 AD FE FA D1 2A E4 (真正的情况 这八个字符不一定是 12 13 AD FE FA D1 2A E4 只是举例)
且 b.txt 中的文字为
".中国人" 对应的16进制为 18 AD FE FA D1 2A E4 ( 后面 AD FE FA D1 2A E4 是相同的 )
这里的"." 用字符串读出来看起来是相同的,但是代表这个"." 的16进制可能是 12 13 或者 18
...全文
256 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
menglv_1978 2012-09-06
  • 打赏
  • 举报
回复
思路的问题,谢谢十九楼!
嗷嗷叫的老马 2011-03-25
  • 打赏
  • 举报
回复
dim Buff1() as byte,buff2() as byte,IsOK as boolean
dim I as long,J as long
Const lST as long=44 '比较的开始地址
dim FileName1 as string,FileName2 as string

open filename1 for binary as #1
open filename2 for binart as #2
redim buff1(lof(1)-1)
redim buff2(lof(2)-1)

get #1,,buff1()
get #2,,buff2()
close

for i= To ubound(buff1)
if buff1(i)=buff2(lst) then
isok=true
for j=0 To ubound(buff2)-92
if buff1(i+j)<>buff2(lst+j) then
isok=false
exit for
end if
next
If idok=true Then
Msgbox "匹配开始地址为:" & i
exit for
end if
endif
next
andy95800 2011-03-25
  • 打赏
  • 举报
回复
思路问题,这么简单的逻辑还需要代码也就太...太.
嗷嗷叫的老马 2011-03-25
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 dinojy2011 的回复:]用途是对比两个 wav 文件 [/Quote]
晕倒,这个就直接操作二进制啊.

给你写个例子吧.
andy95800 2011-03-25
  • 打赏
  • 举报
回复
要我说 楼主的思路有问题
大部分代码都非常浪费时间
既然只是出于比较的目的 为何非得连接 不连接就不能比较了么
因为是顺序比较 所以就相对好处理一些
一个主循环遍历数组 若查到被查字符的第一个字节 则激活子循环继续查后续的第二字符是否匹配
这样只是单纯的查找,不会浪费多少时间了
yachong 2011-03-25
  • 打赏
  • 举报
回复
转化成字符串再比较本身就效率低,不如直接在BYTE数组中找。
即使转换成字符串,也不应该循环做字符串连接操作,很费时。
应该先申请一个足够大的字符串,然后用Mid语句搞。

    Open sFileName For Binary As #1
nFileLen = LOF(1)

ReDim byt(0 To nFileLen - 1) As Byte
Get #1, , byt
Close 1

sResult = Space(nFileLen * 3)'足够大的字符串
For i = 0 To nFileLen - 1
s = Right("0" & Hex(byt(i)), 2)
Mid(sResult, i * 3 + 1, 2) = s '用mid比字符串连接快很多
Next

?sResult
king06 2011-03-25
  • 打赏
  • 举报
回复
    Dim buff() As Byte
ReDim buff(44)
Open "c:\test.txt" For Binary As #1
Get #1, 1, buff '从第1个字节开始读44字节
Close #1
Debug.Print StrConv(buff, vbUnicode)
dinojy2011 2011-03-25
  • 打赏
  • 举报
回复
思路的问题,谢谢十九楼!
of123 2011-03-25
  • 打赏
  • 举报
回复
字符串的拼接是最慢的,何况你是不断重新分配内存。可以直接二进制比较:

Dim a() As Byte, b() As Byte, i As Long, j As Long
Open "C:\a.txt" For Binary As #1 /90K的文件 这里代码运行,大概的时间是 3 - 4 秒
Redim a(LOF(1) - 1)
Get #1, , a
Close #1
Open "C:\b.txt" For Binary As #1 /60K 的文件
Redim b(LOF(1) - 1)
Get #1, , b
Close #1

For i = 0 To Ubound(b) - Ubound(a) - 1
If b(i) = a(0)
For j = 1 To Ubound(a)
If b(i + j) <> a(j) Then Exit For
Next j
If j = Ubound(b) + 1
MsgBox i
Exit Sub
End If
End If
Nexit i
MsgBox "0"
superNANA_MUMU 2011-03-24
  • 打赏
  • 举报
回复
过来捡自己有用的~我经常需要读取批量文件的字符串
贝隆 2011-03-24
  • 打赏
  • 举报
回复
我试验了下,单单是读文件的话,没有遇到楼主所说的问题。很快
dinojy2011 2011-03-24
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 king06 的回复:]
LZ这样比较的话,慢是不可避免的,不过那代码本身写的就不规范也有稍许影响

VB code
for i = 1 to ubound(a)
strA = strA & format$(a(i),"000")
next
[/Quote]
用途是对比两个 wav 文件 ,查找 1.wav,2.wav(把1.mav 截取部份的音频片断 )截取的位置
wav 格式详见 WAVERIFF 格式 或 wav 音乐格式分析
格式 头部 (44 个字节 ) + 中间 N个字节(数据) + 尾部( 48 个字节 )
将头部与尾部截取后 可以用来比较

获得 strA 与 strB后(这个过程慢 )

Startposition = instr( strA , strB )
'/------------
'一些换算位置的代码
'------------/
在这个目标前提下,如何实现
对字节数组的操作比起对字符串数组的操作是要快的?
那代码是临时写的 ,我平时也不喜欢加 + 直接用 &
strA = strA & format(a(i),"000") 会好一点
jiashie 2011-03-24
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 myjian 的回复:]

关键在于你读这个文件,是为了干什么.

做查找?做替换?做转换?

从目前你给的代码来看,就是进行二进制级的判断.那么为什么不直接用字节来读取呢?

对字节数组的操作比起对字符串数组的操作是要快的.
[/Quote]

另外 :字符串连接的地方可以优化一下
strA=space$(ubound(a)*3) '//! lBound(a)=1 还真不习惯
for i = 1 to ubound(a)
'strA = strA + format(a(i),"000" '避免 '4' & '40' = '440' '44' & '0' = '440' 的情况
mid$(strA,(i-1) * 3 + 1,3) = format$(a(i),"000")
next i
嗷嗷叫的老马 2011-03-24
  • 打赏
  • 举报
回复
关键在于你读这个文件,是为了干什么.

做查找?做替换?做转换?

从目前你给的代码来看,就是进行二进制级的判断.那么为什么不直接用字节来读取呢?

对字节数组的操作比起对字符串数组的操作是要快的.

king06 2011-03-24
  • 打赏
  • 举报
回复
LZ这样比较的话,慢是不可避免的,不过那代码本身写的就不规范也有稍许影响
for i = 1 to ubound(a)   
strA = strA & format$(a(i),"000")
next

dinojy2011 2011-03-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 king06 的回复:]
你用的的是filelen函数得到的字节数,"for i = 1 to ubound(a)"
如果是90K的文件,其中ubound(a)=90*1024,当然循环半天了.
要直接得到字符串,见3F
[/Quote]
我并非想找字符串
我说一个例子,好理解一下(用UltraEdit 观察)
是文本 "中国人" 的 16进制代码 D6 D0 B8 FA C8 CB
而文本 "abc" 的 16进制代码 61 62 63
将 61 62 63 从第四位开始 插入进 D6 D0 B8 FA C8 CB 会得到
D6 D0 B8 61 62 63 FA C8 CB (这九个16进制,显示为文本"中筧bc")
我们用 instr( "D6 D0 B8 61 62 63 FA C8 CB" ,"61 62 63")可以返回非0值
可是用 instr( "中筧bc", "abc") 则只能返回 0
所以用字符串比较的方法可能是错的
我的问题在于 如何优化这两个循环 或者用其他方法达到这个目的
for i = 1 to ubound(a)
strA = strA + format(a(i),"000")
next i
for i = 1 to ubound(b)
strB = strB + format(b(i),"000") ' 这里 b(i) 返回不大于256的十进制,我直接把它转 "000"
'避免 '4' & '40' = '440' '44' & '0' = '440' 的情况
'因为 "004" & "040" = "004040" 而 "044" & "000" = "044000" 这两个值是不同的,不用Format就会出现上面的情况
next i
king06 2011-03-24
  • 打赏
  • 举报
回复
你用的的是filelen函数得到的字节数,"for i = 1 to ubound(a)"
如果是90K的文件,其中ubound(a)=90*1024,当然循环半天了.
要直接得到字符串,见3F
dinojy2011 2011-03-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 king06 的回复:]
引用楼主 dinojy2011 的回复:
open "C:\a.txt" for binary as #1 /90K的文件 这里代码运行,大概的时间是 3 - 4 秒

你机器有问题,就这么一句不超过1ms
[/Quote]
我写的注释让你误解了
主要是这里的代码时间长
debug.print "开始" & time()
for i = 1 to ubound(a)
strA = strA + format(a(i),"000" '避免 '4' & '40' = '440' '44' & '0' = '440' 的情况
next i
for i = 1 to ubound(b)
strB = strB + format(a(i),"000"
next i
debug.print “结束" & time()
king06 2011-03-24
  • 打赏
  • 举报
回复
Open "C:\a.txt" For Binary As #1
str = StrConv(InputB(LOF(1), #1), vbUnicode)
king06 2011-03-24
  • 打赏
  • 举报
回复
[Quote=引用楼主 dinojy2011 的回复:]
open "C:\a.txt" for binary as #1 /90K的文件 这里代码运行,大概的时间是 3 - 4 秒
[/Quote]
你机器有问题,就这么一句不超过1ms
加载更多回复(1)

7,763

社区成员

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

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