[Lib] IniObj() 读取INI到对象

许多实用脚本和封装函数, 可以让您编写脚本更加便捷高效

Moderators: tmplinshi, arcticir

arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

[Lib] IniObj() 读取INI到对象

30 Aug 2014, 22:16

久经考验的自用函数。

特点:
速度快
保留INI次序

参数1:INI 路径或者内容。
参数2,是否自动替换变量。如包含“%A_ScriptDir%”,就会被替换成A_ScriptDir内容。

Code: Select all

b=
(
[测试]
3=3
1=1
B
A=A
2
)

for i,n in IniObj(b).测试
	f.= i "`t" n "`n"

MsgBox % f

Code: Select all

IniObj(h,p=""){
	If !InStr(h,"`n")
		FileRead, h, %h%
	If h:=Trim(h," `t`r`n")
	{
		(p?h:=Z_Spider(h):""),j:=OrderedArray()
		Loop, Parse, h, `r`n, `r `t
		{
			(!A_LoopField or (p:=SubStr(i:=A_LoopField,1,1)) = ";")
				? "" : ((p = "[" and p:=InStr(i,"]",0,0))
					? n:=j[SubStr(i, 2, p-2)]:=OrderedArray(): ((p:=InStr(i,"="))
						? n[Trim(SubStr(i, 1, p-1))] := Trim(SubStr(i, p+1)) : (n[i]:="")))
		}
		return j
	}
}

OrderedArray(prm*)
{
    ; Define prototype object for ordered arrays:
    static base := Object("__Set", "oaSet", "_NewEnum", "oaNewEnum"
                        , "Remove", "oaRemove", "Insert", "oaInsert", "InsertBefore", "oaInsertBefore")
    ; Create and return new ordered array object:
    return Object("_keys", Object(), "base", base, prm*)
}

oaSet(obj, prm*)
{
    ; If this function is called, the key must not already exist.
    ; Sub-class array if necessary then add this new key to the key list
    if prm.maxindex() > 2
        ObjInsert(obj, prm[1], OrderedArray())
    ObjInsert(obj._keys, prm[1])
}

oaNewEnum(obj)
{
    ; Define prototype object for custom enumerator:
    static base := Object("Next", "oaEnumNext")
    ; Return an enumerator wrapping our _keys array's enumerator:
    return Object("obj", obj, "enum", obj._keys._NewEnum(), "base", base)
}

oaEnumNext(e, ByRef k, ByRef v:="")
{
    ; If Enum.Next() returns a "true" value, it has stored a key and
    ; value in the provided variables. In this case, "i" receives the
    ; current index in the _keys array and "k" receives the value at
    ; that index, which is a key in the original object:
    if r := e.enum.Next(i,k)
        ; We want it to appear as though the user is simply enumerating
        ; the key-value pairs of the original object, so store the value
        ; associated with this key in the second output variable:
        v := e.obj[k]
    return r
}

oaRemove(obj, prm*)
{
    r := ObjRemove(obj, prm*)         ; Remove keys from main object
    Removed := []                     
    for k, v in obj._keys             ; Get each index key pair
        if not ObjHasKey(obj, v)      ; if key is not in main object
            Removed.Insert(k)         ; Store that keys index to be removed later
    for k, v in Removed               ; For each key to be removed
        ObjRemove(obj._keys, v, "")   ; remove that key from key list
    return r
}

oaInsert(obj, prm*)
{
    r := ObjInsert(obj, prm*)            ; Insert keys into main object
    enum := ObjNewEnum(obj)              ; Can't use for-loop because it would invoke oaNewEnum
    while enum[k] {                      ; For each key in main object
        if (k = "_keys")
            continue 
        for i, kv in obj._keys           ; Search for key in obj._keys
            if (k = kv)                  ; If found...
                continue 2               ; Get next key in main object
        ObjInsert(obj._keys, k)          ; Else insert key into obj._keys
    }
    return r
}

oaInsertBefore(obj, key, prm*)
{
    OldKeys := obj._keys                 ; Save key list
    obj._keys := []                      ; Clear key list
    for idx, k in OldKeys {              ; Put the keys before key
        if (k = key)                     ; back into key list
            break
        obj._keys.Insert(k)
    }
    
    r := ObjInsert(obj, prm*)            ; Insert keys into main object
    enum := ObjNewEnum(obj)              ; Can't use for-loop because it would invoke oaNewEnum
    while enum[k] {                      ; For each key in main object
        if (k = "_keys")
            continue 
        for i, kv in OldKeys             ; Search for key in OldKeys
            if (k = kv)                  ; If found...
                continue 2               ; Get next key in main object
        ObjInsert(obj._keys, k)          ; Else insert key into obj._keys
    }
    
    for i, k in OldKeys {                ; Put the keys after key
        if (i < idx)                     ; back into key list
            continue
        obj._keys.Insert(k)
    }
    return r
}

Z_Spider(h){
	j:="a_workingdir\A_ScriptDir\h_dir\h_temp\h_drive\A_AppData\A_AppDataCommon\A_ProgramFiles\A_Temp\A_Is64bitOS\A_MyDocuments\A_DesktopCommon\A_Desktop"
	Loop,Parse,j,\
		InStr(h,"`%" A_LoopField "`%") ? h:=StrReplace(h,"`%" A_LoopField "`%",%A_LoopField%) : ""
	return h	
	}
User avatar
RobertL
Posts: 546
Joined: 18 Jan 2014, 01:14
Location: China

学习笔记 V0.3

03 Sep 2014, 04:41

  • 打算写个IniObj,但不实现保留顺序OrderedArray
    想实现,(变量释放时自动、更新项时自动、手动)保存至文件(你没写保存部分?)、自动转义、验证。
  • 学习了你的解析Ini至对象的过程..很精炼了,复制-粘贴即可..
    记录
  • 牢骚:
    嗯,习惯对象语法后,希望所有的命令都可以这样调用..

    还就是感概,这些东西散,如果像手册一样,有个目录/索引能一下查到,随用随查就好了。
    这点目前可以靠大伙的分享,比如就一个需求,经多方尝试对比出的结果。
  • 将发布在AHK8,等好了贴链接过来..存储ini至对象(AHK8)
Last edited by RobertL on 16 Sep 2014, 10:06, edited 5 times in total.
我为人人,人人为己?
User avatar
huyaowen
Posts: 109
Joined: 28 Jul 2014, 01:15

Re: [Lib] IniObj() 读取INI到对象

13 Sep 2014, 10:01

给个初级点的例子吧
User avatar
RobertL
Posts: 546
Joined: 18 Jan 2014, 01:14
Location: China

Re: [Lib] IniObj() 读取INI到对象

15 Sep 2014, 10:14

huyaowen wrote:给个初级点的例子吧
例子不就在最上面吗..
我为人人,人人为己?
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: [Lib] IniObj() 读取INI到对象

15 Sep 2014, 16:13

恰好我又重写了一次。
需要 OrderedArray 属性的情况少之又少,所以OrderedArray现在作为外附参数。

这样不仅更加灵活,而且方便一个对象读取多个INI。

Code: Select all

io("Test.ini",1,OrderedArray()) ;可以传递各种类型的对象
io("Test.ini",,CriticalObject()) 
f:=io("Test.ini",,New Down)
f:=io("Test2.ini",,f)

Code: Select all

io(d,b:="",byref n:=""){
	If d:=Trim(InStr(d,"`n")?d:FileRead(d)," `t`r`n")
	{
		(b?d:=Z_Spider(d):""),f:=n?n:[]
		Loop, Parse, d, `r`n, `r `t
			(A_LoopField and (b:=SubStr(i:=A_LoopField,1,1)) != ";")
				? (b = "[" and b:=InStr(i,"]",0,0))
					? n:=SubStr(i,2,b-2) : ((b:=InStr(i,"="))
						? f[n,RTrim(SubStr(i, 1, b-1))] := LTrim(SubStr(i, b+1)) : (f[n,i]:=""))
				: ""
		return f
	}
}
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: [Lib] IniObj() 读取INI到对象

15 Sep 2014, 16:24

你以为“ `r `t 和 % " `t" or %A_Space%`t 比起来字符更少”,这么明显的事我会告诉你吗
User avatar
RobertL
Posts: 546
Joined: 18 Jan 2014, 01:14
Location: China

制表符-注释 & 新版分析 V0.1

15 Sep 2014, 19:21

  • arcticir wrote:你以为“ `r `t 和 % " `t" or %A_Space%`t 比起来字符更少”,这么明显的事我会告诉你吗
    我本来是问为什么Loop, Parse, h, `r`n, `r `t及其他地方`t制表符空格
    是用于支持以下吗?

    Code: Select all

    [a]	;注释1
    b=c	;注释2
    ;注释3
  • 代码笔记
  • 功能小缺陷..
  • 我也把自己想实现的功能更新了一点点..
  • 我也实现了,见存储ini至对象(AHK8)
我为人人,人人为己?

Return to “脚本函数”

Who is online

Users browsing this forum: No registered users and 20 guests