minterz 发表于 2011-8-5 11:23:17

为什么官方ini读取速度如此之快

本帖最后由 minterz 于 2011-8-5 11:24 编辑

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

今天生成了一百万行数据$ini = ""&@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)

请问,官方ini读取用的是什么方法,为什么速度哪么快呢?

minterz 发表于 2011-8-5 11:46:13

即便ini文件只有1万行左右,官方iniread的读取速度
仍然是 先读文件,再正则读 速度的20倍

官方iniread的机制是什么啊
这么快..

lainline 发表于 2011-8-5 14:05:15

你用读一行的方式和文件搜索的方式时间当然没法比

wa18239 发表于 2011-8-5 14:27:01

楼上正解。就像一个是知道门牌号,一个不知道门牌号,你说谁找得快

minterz 发表于 2011-8-5 16:02:29

回复 3# lainline


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

听着真新鲜啊...

minterz 发表于 2011-8-5 16:04:57

楼上正解。就像一个是知道门牌号,一个不知道门牌号,你说谁找得快
wa18239 发表于 2011-8-5 14:27 http://autoitx.com/images/common/back.gif


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

咋就是知道门牌号?

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

请解惑..

卫和谐 发表于 2011-8-5 19:39:46

不太明白原理,高手解答一下!

wa18239 发表于 2011-8-5 20:40:50

ini 文件格式    [字段名]
                     关键字=数值
小弟认为IniRead 先查找 字段 ,再找关键字,然后读取数值,固定格式查找。
而 FileRead 把字段,关键字,数值,连在一起,当成一个很长的字符串,
_StringBetween 则 把 99999 与这字符串一个个比较,当然也包括其中的数值,
所以花费时间要长,不知这样回答是否说得通。

minterz 发表于 2011-8-5 22:11:00

ini 文件格式    [字段名]
                     关键字=数值
小弟认为IniRead 先查找 字段 ,再找关键字 ...
wa18239 发表于 2011-8-5 20:40 http://autoitx.com/images/common/back.gif


    iniread 当你读的ini文件只有一个字段, 而且读取的是最后几行的一个关键词的时候, iniread 还是要将ini文件中所有内容读取,然后再通过某种方式找到匹配该关键字的数值.
_StringBetween是正则 找匹配,按说速度是很快,并不是那种一个个字符字符的比较那种笨方法. 但是就是比官方iniread慢...

minterz 发表于 2011-8-5 22:13:13

现在也不是说不说的通, 而是找到官方iniread读取的机制和方法,再借鉴到其他读取文件,然后找匹配上

这样即便文件比较大,也能快速读取...

asdasdasd 发表于 2011-8-5 23:00:18

首先你要明白字符查找的算法,有一种效率比较高的叫做折半查找法,INI读取数据,首先是知道你的字段,也知道你的键值的,这样有目的的折半查找,比起全文件的字符挨个查找,你说省了多少时间?

minterz 发表于 2011-8-5 23:49:52

本帖最后由 minterz 于 2011-8-5 23:58 编辑

首先你要明白字符查找的算法,有一种效率比较高的叫做折半查找法,INI读取数据,首先是知道你的字段,也知道 ...
asdasdasd 发表于 2011-8-5 23:00 http://autoitx.com/images/common/back.gif

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

iniread 能满足这个条件吗?..

pusofalse 发表于 2011-8-6 00:04:56

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

3mile 发表于 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")
    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 Then Return SetError(1, 0, $sDefault)
    Return DllStructGetData($tST, 1)
EndFunc

happytc 发表于 2011-8-6 00:27:15

回复 14# 3mile


    你动作还真快呢!


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

我是看了ahk源码后才知道的(现在连autoit老的源码包我都找不到在那里下载了)
页: [1] 2
查看完整版本: 为什么官方ini读取速度如此之快