找回密码
 加入
搜索
查看: 12907|回复: 27

[效率算法] 为什么官方ini读取速度如此之快

 火.. [复制链接]
发表于 2011-8-5 11:23:17 | 显示全部楼层 |阅读模式
本帖最后由 minterz 于 2011-8-5 11:24 编辑

iniread() 是au3的一个基本函数,有一些不足,但是读取速度确实非常惊人的.
我的是windows 7 2g内存 e7400 2.8g的cpu

今天生成了一百万行数据
$ini = "[1]"&@CRLF
For $i = 1 To 1000000
        $ini &= $i&"="&Random(1,100000000000)&@CRLF
Next
FileWrite("initest.ini",$ini)
大概有24m大小
读取某一个值,只用了50微秒.
Local $begin = TimerInit()
$read = IniRead("initest.ini",1,99999,1)
Local $dif = TimerDiff($begin)
MsgBox(0,"时间差,这个计时的精度比sleep高",$dif)
MsgBox(0,"读取内容",$read)
但是先读取文件,再用正则读取,却要花费1000多微秒
超过20倍.

Local $begin = TimerInit()
$q = FileRead("f:/initest.ini")
$ini = _StringBetween($q,"99999=",@CRLF)
Local $dif = TimerDiff($begin)
MsgBox(0,"时间差,这个计时的精度比sleep高",$dif)
MsgBox(0,"读取内容",$ini[0])


请问,官方ini读取用的是什么方法,为什么速度哪么快呢?
 楼主| 发表于 2011-8-5 11:46:13 | 显示全部楼层
即便ini文件只有1万行左右,官方iniread的读取速度
仍然是 先读文件,再正则读 速度的20倍

官方iniread的机制是什么啊  
这么快..
发表于 2011-8-5 14:05:15 | 显示全部楼层
你用读一行的方式和文件搜索的方式时间当然没法比
发表于 2011-8-5 14:27:01 | 显示全部楼层
楼上正解。就像一个是知道门牌号,一个不知道门牌号,你说谁找得快
 楼主| 发表于 2011-8-5 16:02:29 | 显示全部楼层
回复 3# lainline


    哦,原来ini读取某一不定键值,是读取某一行啊

听着真新鲜啊...
 楼主| 发表于 2011-8-5 16:04:57 | 显示全部楼层
楼上正解。就像一个是知道门牌号,一个不知道门牌号,你说谁找得快
wa18239 发表于 2011-8-5 14:27



ini读取也有一个读取整个文件,然后在判断的过程
如果此键值不存在,就返回默认的值

咋就是知道门牌号?

又不是读取固定的某一行..

请解惑..
发表于 2011-8-5 19:39:46 | 显示全部楼层
不太明白原理,高手解答一下!
发表于 2011-8-5 20:40:50 | 显示全部楼层
ini 文件格式    [字段名]
                     关键字=数值
小弟认为IniRead 先查找 字段 ,再找关键字,然后读取数值,固定格式查找。
而 FileRead 把字段,关键字,数值,连在一起,当成一个很长的字符串,
_StringBetween 则 把 99999 与这字符串一个个比较,当然也包括其中的数值,
所以花费时间要长,不知这样回答是否说得通。
 楼主| 发表于 2011-8-5 22:11:00 | 显示全部楼层
ini 文件格式    [字段名]
                     关键字=数值
小弟认为IniRead 先查找 字段 ,再找关键字 ...
wa18239 发表于 2011-8-5 20:40



    iniread 当你读的ini文件只有一个字段, 而且读取的是最后几行的一个关键词的时候, iniread 还是要将ini文件中所有内容读取,然后再通过某种方式找到匹配该关键字的数值.
_StringBetween  是正则 找匹配,按说速度是很快,并不是那种一个个字符字符的比较那种笨方法. 但是就是比官方iniread慢...
 楼主| 发表于 2011-8-5 22:13:13 | 显示全部楼层
现在也不是说不说的通, 而是找到官方iniread读取的机制和方法,再借鉴到其他读取文件,然后找匹配上

这样即便文件比较大,也能快速读取...
发表于 2011-8-5 23:00:18 | 显示全部楼层
首先你要明白字符查找的算法,有一种效率比较高的叫做折半查找法,INI读取数据,首先是知道你的字段,也知道你的键值的,这样有目的的折半查找,比起全文件的字符挨个查找,你说省了多少时间?
 楼主| 发表于 2011-8-5 23:49:52 | 显示全部楼层
本帖最后由 minterz 于 2011-8-5 23:58 编辑
首先你要明白字符查找的算法,有一种效率比较高的叫做折半查找法,INI读取数据,首先是知道你的字段,也知道 ...
asdasdasd 发表于 2011-8-5 23:00


搜了下,你说的折半查找法 需要数组是有序的

iniread 能满足这个条件吗?..
发表于 2011-8-6 00:04:56 | 显示全部楼层
IniRead 调用了Kernel32.dll中的GetPrivateProfileStringW函数,关键是这个API的算法合理。正则引擎 要考虑的情况的太多,光是分析表达式就足够浪费效率了,远不如 GetPrivateProfileStringW的效率快。GetPrivateProfileStringW会检查 [、]、=、回车、换行 这几个字符,而正则 还要检查“贪婪匹配”、“零宽断言”之类的。 应该用合理的方法解决合理的问题,你若用正则从一堆杂乱的字符串中 匹配网址、IP地址,才能真正显示出正则的强大,显然GetPrivateProfileStringW不能满足这样的要求。

评分

参与人数 1金钱 +30 收起 理由
minterz + 30 谢谢解答疑惑.

查看全部评分

发表于 2011-8-6 00:08:52 | 显示全部楼层
Local $begin = TimerInit()
;~ $read = IniRead("initest.ini",1,99999,1)
$read=_MSDN_IniRead(@ScriptDir&"\initest.ini", "1", "99999")
Local $dif = TimerDiff($begin)
MsgBox(0,"时间差,这个计时的精度比sleep高",$dif&@CRLF&$read)
MsgBox(0,"读取内容",$read)




Func _MSDN_IniRead($hFile, $sSection, $sKey, $sDefault = "")
    Local $tST = DllStructCreate("char[32767]")
    Local $aGPPS = DllCall("Kernel32.dll", "int", "GetPrivateProfileString", _
        "str", $sSection, "str", $sKey, "str", $sDefault, "ptr", DllStructGetPtr($tST), _
        "dword", 32766, "str", $hFile)
    If IsArray($aGPPS) = 0 Or $aGPPS[0] = 0 Then Return SetError(1, 0, $sDefault)
    Return DllStructGetData($tST, 1)
EndFunc

评分

参与人数 1金钱 +30 收起 理由
minterz + 30 谢谢解答..

查看全部评分

发表于 2011-8-6 00:27:15 | 显示全部楼层
回复 14# 3mile


    你动作还真快呢!


对了,你们是怎么知道IniRead是调用GetPrivateProfileString函数的?

我是看了ahk源码后才知道的(现在连autoit老的源码包我都找不到在那里下载了)
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-11-15 01:10 , Processed in 0.086188 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表