https://blog.csdn.net/yxp_xa/article/details/72539877
当你不想用 DCL 来交互程序的参数设置时,读取 ini 配置文件可以作为一个备用选择,也能方便用户修改。
AutoLISP 程序设计时常用的数据存储方式,各有优缺点:
1. 非图形对象数据字典
2. Windows 注册表
3. 磁盘文件
第一种方式,程序参数将随 DWG 图一起存储,当新开一个图形后,参数需要重新配置
第二种方式,不符合绿色软件的原则,不适合保存大量数据,如对象 DXF 码。有时候会被杀毒软件屏蔽。
第三种方式,LISP 找不到自己加载的路径,无法将参数文件和程序放在同一目录里
本程序为磁盘存储方式提供了统一接口,可以不设置路径,程序将在支持目录里搜索。
例如下面代码将保存一个对象的 dxf 码到ini文件,文件与当前 dwg 同路径。
(setq ss (strcat (getvar "DWGPREFIX") (getvar "DWGNAME") ".ini"))
(vl-ini-set (list ss "LIST表" "DXF" (entget(car(entsel)))))
如果需要读出刚刚保存的 dxf 数据
(vl-ini-get (list ss "LIST表" "DXF"))
yxp-xa原版
程序源代码如下:
;; 用 Lisp 对 INI 文件解析
;; 版权所有
;; (c) by. yxp QQ:9034598 2015-08-16 明经通道
;; 转载或引用,请注明作者和出处
;;
;; 功能:读取磁盘配置文件
;; 语法:
;; (vl-ini-get ini-list)
;; 参数: ini-list 为表类型
;; ini-list =
;; (inifile [section [key [default]]])
;; inifile 指定的INI文件
;; section INI文件中的段落
;; key INI文件中的关键字
;; default 若INI文件中没有关键字则默认返回值
;; 返回值:
;; 1、只含 INI文件 则返回所有段落名称
;; 2、含 section 则返回指定段落下的所有关键字
;; 3、含 key 则返回指定段落下的指定关键字的值,失败则返回 nil
;; 4、含 default 则返回指定段落下的指定关键字的值,失败则返回 default
;; 示例:
;; (vl-ini-get "CAD.ini")
(vl-load-com)
;;配置文件类别,大写,程序运行过程中可修改, 如
;;(setq yxp_file_ext_key "*.TXT")
;;(setq yxp_file_ext_key "CAD.INI")
;;依赖顺序进行参数合法性判断 vl-ini-get
;;子函数3个: yxp_read_ini yxp_read_sec yxp_read_key
(defun vl-ini-get (ini-list /)
(cond
;;转到帮助
((or (= ini-list '?) (= ini-list "?")) (vl-ini-get-help) (princ))
;;判断参数是否表类型
((/= (type ini-list) 'List) (princ "\n; 错误: 要求表参数") (princ))
;;判断参数数量
((> (length ini-list) 4) (princ "\n; 错误: 表参数太多") (princ))
;;判断第一个表参数是否字符型
((/= (type (car ini-list)) 'Str) (princ "\n; 错误: 要求字符型参数") (princ))
;;判断文件名是否 yxp_file_ext_key 类型
((null (wcmatch (strcase (car ini-list)) yxp_file_ext_key))
(princ (strcat "\n; 错误: 不是有效的 " yxp_file_ext_key " 文件名"))
(princ)
)
;;路径长度限制
((> (strlen (car ini-list)) 256) (princ "\n; 错误: 路径及文件名长度超限") (princ))
;;判断第一个参数是否路径
((null (findfile (car ini-list))) (princ "\n; 错误: 不能读取的路径或文件名称") (princ))
;;第二个参数不存在,则返回 ini 文件所有段落名
((null (cadr ini-list)) (yxp_read_ini (car ini-list)))
;;判断第二个参数是否字符型
((/= (type (cadr ini-list)) 'Str) (princ "\n; 错误: 段落名称类型不正确") (princ))
;;判断段落名称是否合法,不能为空字符
((wcmatch (cadr ini-list) " ") (princ "\n; 错误: 段落名称不合法") (princ))
;;段落字符长度限制
((> (strlen (cadr ini-list)) 64) (princ "\n; 错误: 段落长度超限") (princ))
;;第三个参数不存在,则返回段落名下所有关键字
((null (caddr ini-list)) (yxp_read_sec ini-list))
;;判断关键字是否字符型
((/= (type (caddr ini-list)) 'Str) (princ "\n; 错误: 关键字类型不正确") (princ))
;;关键字是否合法,不能包含 = ,不能是空格
((wcmatch (caddr ini-list) "*=*, ") (princ "\n; 错误: 关键字不合法") (princ))
;;关键字长度限制
((> (strlen (caddr ini-list)) 64) (princ "\n; 错误: 关键字长度超限") (princ))
;;返回关键字的值
(t (yxp_read_key ini-list))
)
)
;;返回所有段落名。 ss 文件名
(defun yxp_read_ini (ss / fn xx rowini)
(setq fn (open (findfile ss) "r"))
(while (setq xx (read-line fn))
(if (wcmatch xx "`[*`]") (setq rowini (cons (vl-string-trim "[ ]" xx) rowini)))
)
(close fn)
(reverse (vl-remove "" rowini)) ;;剔除空段落
)
;;返回指定段落的关键字列表。 ss 表: 文件名、段落
(defun yxp_read_sec (ss / fname sec fn xx FLAG secrow rows nn)
(setq fname (car ss) ;;文件名
sec (vl-string-trim " " (cadr ss)) ;;段落,删除前后空格
fn (open (findfile fname) "r")
)
(while (setq xx (read-line fn))
(if (wcmatch xx "`[*`]") ;;匹配段落
(setq FLAG (= (vl-string-trim "[ ]" xx) sec))
) ;;搜到段落时 FLAG=T,开始记录关键字。
(if FLAG (setq rows (cons xx rows))) ;;读出指定段落的关键字
)
(close fn)
(setq rows (cdr (reverse rows))) ;;删除第一行段落名,只留关键字
(while (setq xx (car rows))
(setq rows (cdr rows)
nn (vl-string-search "=" xx)
) ;;关键字不合法时 nn=nil
(if nn
(setq xx (vl-string-trim " " (substr xx 1 nn))
secrow (cons xx secrow)
)
)
)
(reverse secrow)
)
;;返回指定关键字的值。 ss 表: 文件名、段落名、关键字、值
(defun yxp_read_key (ss / fname sec fn xx secrow rows nn)
(setq fname (car ss)
sec (vl-string-trim " " (cadr ss))
key (vl-string-trim " " (caddr ss)) ;;关键字,删除前后空格
fn (open (findfile fname) "r")
)
(while (setq xx (read-line fn))
(if (wcmatch xx "`[*`]")
(setq FLAG (= (vl-string-trim "[ ]" xx) sec))
)
(if FLAG (setq rows (cons xx rows)))
)
(close fn)
(setq rows (cdr (reverse rows)))
(while (setq xx (car rows))
(setq rows (cdr rows)
nn (vl-string-search "=" xx)
) ;;此前与 yxp_read_sec 函数相同
(if nn
(setq secrow
(cons
(list (vl-string-trim " " (substr xx 1 nn))
(vl-string-trim " " (substr xx (+ 2 nn)))
)
secrow
)
)
)
)
(setq ff (cadr (assoc key (reverse secrow))))
(if ff ff (cadddr ss))
)
;;参数合法性判断vl-ini-set
;;子函数 1 个:yxp_save_ini
(defun vl-ini-set (ini-list)
(cond
;;转到帮助
((or (= ini-list '?) (= ini-list "?")) (vl-ini-set-help) (princ))
;;判断参数是否表类型
((/= (type ini-list) 'List) (princ "\n; 错误: 要求表参数") (princ))
;;判断参数数量
((or (< (length ini-list) 2) (> (length ini-list) 4))
(princ "\n; 错误: 表参数不足或太多")
(princ)
)
;;判断第一个表参数是否字符型
((/= (type (car ini-list)) 'Str) (princ "\n; 错误: 要求字符型参数") (princ))
;;判断文件名是否 yxp_file_ext_key 类型
((null (wcmatch (strcase (car ini-list)) yxp_file_ext_key))
(princ (strcat "\n; 错误: 不是有效的 " yxp_file_ext_key " 文件名"))
(princ)
)
;;判断段落名是否字符型
((/= (type (cadr ini-list)) 'Str) (princ "\n; 错误: 段落名称类型不正确") (princ))
;;判断段落名称是否合法,不能为空字符
((wcmatch (cadr ini-list) " ") (princ "\n; 错误: 段落名称不合法") (princ))
;;判断第三个参数是否字符型
((and (caddr ini-list) (/= (type (caddr ini-list)) 'Str))
(princ "\n; 错误: 关键字类型不正确")
(princ)
)
;;判断关键字是否合法,不能为空字符
((and (caddr ini-list) (wcmatch (caddr ini-list) " "))
(princ "\n; 错误: 关键字不合法")
(princ)
)
;;前三个参数的字长限制
((or (> (strlen (car ini-list)) 256)
(> (strlen (cadr ini-list)) 64)
(and (caddr ini-list) (> (strlen (caddr ini-list)) 64))
)
(princ "\n; 错误: 参数字符长度超限")
(princ)
)
;;如果第三个参数不存在,则保存段落名
(t (yxp_save_ini ini-list))
)
)
;; 读入 ini ,如果不存在,则创建, 如果存在,则修改
;; 算法:从后往前搜索段落名,找到后再从前往后搜索关键字
(defun yxp_save_ini (ss / C wc A B seq qq fa FLAG r1 r2 fb AA)
(setq fa (open (car ss) "r")
sec (vl-string-trim " " (cadr ss))
)
(if (caddr ss)
(setq key (vl-string-trim " " (caddr ss))qq (strcat key " = ")
wc (strcat key "=*," key " =*")
)
)
(if (cadddr ss) (setq qq (strcat qq (vl-princ-to-string (cadddr ss)))))
(if fa
(progn
(while (setq xx (read-line fa)) (setq A (cons xx A)))
(close fa)
(setq AA A)
(if (caddr ss)
(progn
(while (setq r1 (car A))
(if (wcmatch (vl-string-trim " " r1) wc) (setq FLAG t))
(if (wcmatch r1 "`[*`]")
(if (= (vl-string-trim "[ ]" r1) sec)
(progn
(if FLAG
(progn (setq r2 (car B))
(while (null (wcmatch (vl-string-trim " " r2) wc))
(setq A (cons r2 A) B (cdr B) r2 (car B))
)
(setq C (append (reverse A) (cons qq (cdr B))))
)
(setq C (append (reverse A) (cons qq B)))
)
(setq A nil)
)
(setq FLAG nil)
)
)
(setq B (cons r1 B) A (cdr A))
) ;; the end
(if (null C) (setq C (cons (strcat "[" sec "]") (cons qq B))))
)
(progn
(while (setq r1 (car A))
(if (and (wcmatch r1 "`[*`]") (= (vl-string-trim "[ ]" r1) sec))
(setq A nil B nil)
(setq B (cons r1 B) A (cdr A))
)
)
(setq C (if B (cons (strcat "[" sec "]") B)))
)
)
(if (null AA)
(if (caddr ss)
(setq C (list (strcat "[" sec "]") qq))
(setq C (list (strcat "[" sec "]")))
)
)
)
(setq C (list (strcat "[" sec "]") (if qq qq "")))
)
(if C
(progn
(setq fb (open (car ss) "w"))
(foreach x C (write-line x fb))
(close fb)
(if (= 3 (length ss)) "" (last ss))
)
)
)
(defun vl-ini-set-help()
(princ
(strcat "\n" "功能: 保存 ini 配置文件, 程序编写: yxp 2015-8-16" "\n"
"语法: (vl-ini-set ini-list)" "\n"
"参数: ini-list == (inifile section [key [value]])" "\n"
" inifile 必选, 字符型, 路径 + 文件名" "\n" " section 必选, 字符型, 段落名, 长度不大于 64" "\n"
" key 可选, 字符型, 关键字, 长度不大于 64, 未设置时只保存段落" "\n"
" value 可选, 任意类型, 关键字的值, 长度不限, 未设置时关键字为空字符" "\n"
"返回值: 失败时返回 nil, 成功则返回保存的数据" "\n"
)
)
)
(defun vl-ini-get-help()
(princ
(strcat "\n" "功能: 读入 ini 配置文件, 程序编写: yxp 2015-8-16" "\n"
"语法: (vl-ini-get ini-list)" "\n"
"参数: ini-list == (inifile [section [key [default]]])" "\n"
" inifile 必选, 字符型, 路径 + 文件名" "\n" " section 可选, 字符型, 段落名, 长度不大于 64" "\n"
" key 可选, 字符型, 关键字, 长度不大于 64" "\n" " default 可选, 任意类型, 关键字的值, 长度不限"
"\n" "返回值:" "\n" " 1、只含 inifile 返回所有段落名称" "\n" " 2、仅含 section 返回指定段落下的所有关键字"
"\n" " 3、仅含 key 返回指定关键字的值,未找到关键字则返回 nil" "\n"
" 4、含 default 返回指定关键字的值,未找到则返回 default" "\n"
)
)
)
(princ)
自己整理版
;;说明:: 读入 ini 配置文件, 程序编写: yxp 2015-8-16
;; 语法: (vl-ini-get ini-list)
;;参数: ini-list == (inifile [section [key [default]]])
;; inifile 必选, 字符型, 路径 + 文件名
;; section 可选, 字符型, 段落名, 长度不大于 64
;; key 可选, 字符型, 关键字, 长度不大于 64
;; default 可选, 任意类型, 关键字的值, 长度不限
;;返回值:
;; 1、只含 inifile 返回所有段落名称
;; 2、仅含 section 返回指定段落下的所有关键字
;; 3、仅含 key 返回指定关键字的值,未找到关键字则返回 nil
;; 4、含 default 返回指定关键字的值,未找到则返回 default
(defun vl-ini-get (ini-list / vl-ini-get-help yxp_read_ini yxp_read_key yxp_read_sec)
(defun vl-ini-get-help()
(princ
(strcat
"\n功能: 读入 ini 配置文件, 程序编写: yxp 2015-8-16"
"\n语法: (vl-ini-get ini-list)"
"\n参数: ini-list == (inifile [section [key [default]]])"
"\n inifile 必选, 字符型, 路径 + 文件名"
"\n section 可选, 字符型, 段落名, 长度不大于 64"
"\n key 可选, 字符型, 关键字, 长度不大于 64"
"\n default 可选, 任意类型, 关键字的值, 长度不限"
"\n返回值:"
"\n 1、只含 inifile 返回所有段落名称"
"\n 2、仅含 section 返回指定段落下的所有关键字"
"\n 3、仅含 key 返回指定关键字的值,未找到关键字则返回 nil"
"\n 4、含 default 返回指定关键字的值,未找到则返回 default"
)
)
)
;;返回所有段落名。 ss 文件名
(defun yxp_read_ini (ss / fn xx rowini)
(setq fn (open (findfile ss) "r"))
(while (setq xx (read-line fn))
(if (wcmatch xx "`[*`]") (setq rowini (cons (vl-string-trim "[ ]" xx) rowini)))
)
(close fn)
(reverse (vl-remove "" rowini)) ;;剔除空段落
)
;;返回指定段落的关键字列表。 ss 表: 文件名、段落
(defun yxp_read_sec (ss / fname sec fn xx FLAG secrow rows nn)
(setq fname (car ss) ;;文件名
sec (vl-string-trim " " (cadr ss)) ;;段落,删除前后空格
fn (open (findfile fname) "r")
)
(while (setq xx (read-line fn))
(if (wcmatch xx "`[*`]") ;;匹配段落
(setq FLAG (= (vl-string-trim "[ ]" xx) sec))
) ;;搜到段落时 FLAG=T,开始记录关键字。
(if FLAG (setq rows (cons xx rows))) ;;读出指定段落的关键字
)
(close fn)
(setq rows (cdr (reverse rows))) ;;删除第一行段落名,只留关键字
(while (setq xx (car rows))
(setq rows (cdr rows)
nn (vl-string-search "=" xx)
) ;;关键字不合法时 nn=nil
(if nn
(setq xx (vl-string-trim " " (substr xx 1 nn))
secrow (cons xx secrow)
)
)
)
(reverse secrow)
)
;;返回指定关键字的值。 ss 表: 文件名、段落名、关键字、值
(defun yxp_read_key (ss / fname sec fn xx secrow rows nn)
(setq fname (car ss)
sec (vl-string-trim " " (cadr ss))
key (vl-string-trim " " (caddr ss)) ;;关键字,删除前后空格
fn (open (findfile fname) "r")
)
(while (setq xx (read-line fn))
(if (wcmatch xx "`[*`]")
(setq FLAG (= (vl-string-trim "[ ]" xx) sec))
)
(if FLAG (setq rows (cons xx rows)))
)
(close fn)
(setq rows (cdr (reverse rows)))
(while (setq xx (car rows))
(setq rows (cdr rows)
nn (vl-string-search "=" xx)
) ;;此前与 yxp_read_sec 函数相同
(if nn
(setq secrow
(cons
(list (vl-string-trim " " (substr xx 1 nn))
(vl-string-trim " " (substr xx (+ 2 nn)))
)
secrow
)
)
)
)
(setq ff (cadr (assoc key (reverse secrow))))
(if ff ff (cadddr ss))
)
(cond
;;转到帮助
((or (= ini-list '?) (= ini-list "?")) (vl-ini-get-help) (princ))
;;判断参数是否表类型
((/= (type ini-list) 'List) (princ "\n; 错误: 要求表参数") (princ))
;;判断参数数量
((> (length ini-list) 4) (princ "\n; 错误: 表参数太多") (princ))
;;判断第一个表参数是否字符型
((/= (type (car ini-list)) 'Str) (princ "\n; 错误: 要求字符型参数") (princ))
;;判断文件名是否 yxp_file_ext_key 类型
((null (wcmatch (strcase (car ini-list)) "*.INI"))
(princ "\n; 错误: 不是有效的 *.INI 文件名")
(princ)
)
;;路径长度限制
((> (strlen (car ini-list)) 256) (princ "\n; 错误: 路径及文件名长度超限") (princ))
;;判断第一个参数是否路径
((null (findfile (car ini-list))) (princ "\n; 错误: 不能读取的路径或文件名称") (princ))
;;第二个参数不存在,则返回 ini 文件所有段落名
((null (cadr ini-list)) (yxp_read_ini (car ini-list)))
;;判断第二个参数是否字符型
((/= (type (cadr ini-list)) 'Str) (princ "\n; 错误: 段落名称类型不正确") (princ))
;;判断段落名称是否合法,不能为空字符
((wcmatch (cadr ini-list) " ") (princ "\n; 错误: 段落名称不合法") (princ))
;;段落字符长度限制
((> (strlen (cadr ini-list)) 64) (princ "\n; 错误: 段落长度超限") (princ))
;;第三个参数不存在,则返回段落名下所有关键字
((null (caddr ini-list)) (yxp_read_sec ini-list))
;;判断关键字是否字符型
((/= (type (caddr ini-list)) 'Str) (princ "\n; 错误: 关键字类型不正确") (princ))
;;关键字是否合法,不能包含 = ,不能是空格
((wcmatch (caddr ini-list) "*=*, ") (princ "\n; 错误: 关键字不合法") (princ))
;;关键字长度限制
((> (strlen (caddr ini-list)) 64) (princ "\n; 错误: 关键字长度超限") (princ))
;;返回关键字的值
(t (yxp_read_key ini-list))
)
)
;;说明:保存 ini 配置文件, 程序编写: yxp 2015-8-16
;; 语法: (vl-ini-set ini-list)
;;参数: ini-list == (inifile section [key [value]])
;; inifile 必选, 字符型, 路径 + 文件名
;; section 必选, 字符型, 段落名, 长度不大于 64
;; key 可选, 字符型, 关键字, 长度不大于 64, 未设置时只保存段落
;; value 可选, 任意类型, 关键字的值, 长度不限, 未设置时关键字为空字符
;;返回值: 失败时返回 nil, 成功则返回保存的数据
(defun vl-ini-set (ini-list / vl-ini-set-help yxp_save_ini)
(defun vl-ini-set-help()
(princ
(strcat
"\n功能: 保存 ini 配置文件, 程序编写: yxp 2015-8-16"
"\n语法: (vl-ini-set ini-list)"
"\n参数: ini-list == (inifile section [key [value]])"
"\n inifile 必选, 字符型, 路径 + 文件名"
"\n section 必选, 字符型, 段落名, 长度不大于 64"
"\n key 可选, 字符型, 关键字, 长度不大于 64, 未设置时只保存段落"
"\n value 可选, 任意类型, 关键字的值, 长度不限, 未设置时关键字为空字符"
"\n返回值: 失败时返回 nil, 成功则返回保存的数据"
)
)
)
;; 读入 ini ,如果不存在,则创建, 如果存在,则修改
;; 算法:从后往前搜索段落名,找到后再从前往后搜索关键字
(defun yxp_save_ini (ss / C wc A B seq qq fa FLAG r1 r2 fb AA)
(setq fa (open (car ss) "r")
sec (vl-string-trim " " (cadr ss))
)
(if (caddr ss)
(setq key (vl-string-trim " " (caddr ss))qq (strcat key " = ")
wc (strcat key "=*," key " =*")
)
)
(if (cadddr ss) (setq qq (strcat qq (vl-princ-to-string (cadddr ss)))))
(if fa
(progn
(while (setq xx (read-line fa)) (setq A (cons xx A)))
(close fa)
(setq AA A)
(if (caddr ss)
(progn
(while (setq r1 (car A))
(if (wcmatch (vl-string-trim " " r1) wc) (setq FLAG t))
(if (wcmatch r1 "`[*`]")
(if (= (vl-string-trim "[ ]" r1) sec)
(progn
(if FLAG
(progn (setq r2 (car B))
(while (null (wcmatch (vl-string-trim " " r2) wc))
(setq A (cons r2 A) B (cdr B) r2 (car B))
)
(setq C (append (reverse A) (cons qq (cdr B))))
)
(setq C (append (reverse A) (cons qq B)))
)
(setq A nil)
)
(setq FLAG nil)
)
)
(setq B (cons r1 B) A (cdr A))
) ;; the end
(if (null C) (setq C (cons (strcat "[" sec "]") (cons qq B))))
)
(progn
(while (setq r1 (car A))
(if (and (wcmatch r1 "`[*`]") (= (vl-string-trim "[ ]" r1) sec))
(setq A nil B nil)
(setq B (cons r1 B) A (cdr A))
)
)
(setq C (if B (cons (strcat "[" sec "]") B)))
)
)
(if (null AA)
(if (caddr ss)
(setq C (list (strcat "[" sec "]") qq))
(setq C (list (strcat "[" sec "]")))
)
)
)
(setq C (list (strcat "[" sec "]") (if qq qq "")))
)
(if C
(progn
(setq fb (open (car ss) "w"))
(foreach x C (write-line x fb))
(close fb)
(if (= 3 (length ss)) "" (last ss))
)
)
)
(cond
;;转到帮助
((or (= ini-list '?) (= ini-list "?")) (vl-ini-set-help) (princ))
;;判断参数是否表类型
((/= (type ini-list) 'List) (princ "\n; 错误: 要求表参数") (princ))
;;判断参数数量
((or (< (length ini-list) 2) (> (length ini-list) 4))
(princ "\n; 错误: 表参数不足或太多")
(princ)
)
;;判断第一个表参数是否字符型
((/= (type (car ini-list)) 'Str) (princ "\n; 错误: 要求字符型参数") (princ))
;;判断文件名是否 yxp_file_ext_key 类型
((null (wcmatch (strcase (car ini-list)) "*.INI"))
(princ "\n; 错误: 不是有效的 *.INI 文件名")
(princ)
)
;;判断段落名是否字符型
((/= (type (cadr ini-list)) 'Str) (princ "\n; 错误: 段落名称类型不正确") (princ))
;;判断段落名称是否合法,不能为空字符
((wcmatch (cadr ini-list) " ") (princ "\n; 错误: 段落名称不合法") (princ))
;;判断第三个参数是否字符型
((and (caddr ini-list) (/= (type (caddr ini-list)) 'Str))
(princ "\n; 错误: 关键字类型不正确")
(princ)
)
;;判断关键字是否合法,不能为空字符
((and (caddr ini-list) (wcmatch (caddr ini-list) " "))
(princ "\n; 错误: 关键字不合法")
(princ)
)
;;前三个参数的字长限制
((or (> (strlen (car ini-list)) 256)
(> (strlen (cadr ini-list)) 64)
(and (caddr ini-list) (> (strlen (caddr ini-list)) 64))
)
(princ "\n; 错误: 参数字符长度超限")
(princ)
)
;;如果第三个参数不存在,则保存段落名
(t (yxp_save_ini ini-list))
)
)
整理优化版
;;说明:: 读入 ini 配置文件, 程序编写: yxp 2015-8-16
;; 语法: (vl-ini-get ini-list)
;; 注意: section key区分大小写!!!
;;参数: ini-list == (inifile [section [key [default]]])
;; inifile 必选, 字符型, 路径 + 文件名
;; section 可选, 字符型, 段落名, 长度不大于 64
;; key 可选, 字符型, 关键字, 长度不大于 64
;; default 可选, 任意类型, 关键字的值, 长度不限
;;返回值:
;; 1、只含 inifile 返回所有段落名称
;; 2、仅含 section 返回指定段落下的所有关键字
;; 3、仅含 key 返回指定关键字的值,未找到关键字则返回 nil
;; 4、含 default 返回指定关键字的值,未找到则返回 default
(defun vl-ini-get (ini-list / vl-ini-get-help yxp_read_ini yxp_read_key yxp_read_sec)
(defun vl-ini-get-help()
(princ
(strcat
"\n功能: 读入 ini 配置文件, 程序编写: yxp 2015-8-16"
"\n语法: (vl-ini-get ini-list)"
"\n注意: section key区分大小写!!!"
"\n参数: ini-list == (inifile [section [key [default]]])"
"\n inifile 必选, 字符型, 路径 + 文件名"
"\n section 可选, 字符型, 段落名, 长度不大于 64"
"\n key 可选, 字符型, 关键字, 长度不大于 64"
"\n default 可选, 任意类型, 关键字的值, 长度不限"
"\n返回值:"
"\n 1、只含 inifile 返回所有段落名称"
"\n 2、仅含 section 返回指定段落下的所有关键字"
"\n 3、仅含 key 返回指定关键字的值,未找到关键字则返回 nil"
"\n 4、含 default 返回指定关键字的值,未找到则返回 default"
)
)
)
;;返回所有段落名。 ss 文件名
(defun yxp_read_ini (ss / fn xx rowini)
(setq fn (open (findfile ss) "r"))
(while (setq xx (read-line fn))
(if (wcmatch xx "`[*`]") (setq rowini (cons (vl-string-trim "[ ]" xx) rowini)))
)
(close fn)
(reverse (vl-remove "" rowini)) ;;剔除空段落
)
;;返回指定段落的关键字列表。 ss 表: 文件名、段落
(defun yxp_read_sec (ss / fname sec fn xx FLAG secrow rows nn)
(setq fname (car ss) ;;文件名
sec (vl-string-trim " " (cadr ss)) ;;段落,删除前后空格
fn (open (findfile fname) "r")
)
(while (setq xx (read-line fn))
(if (wcmatch xx "`[*`]") ;;匹配段落
(setq FLAG (= (vl-string-trim "[ ]" xx) sec))
) ;;搜到段落时 FLAG=T,开始记录关键字。
(if FLAG (setq rows (cons xx rows))) ;;读出指定段落的关键字
)
(close fn)
(setq rows (cdr (reverse rows))) ;;删除第一行段落名,只留关键字
(while (setq xx (car rows))
(setq rows (cdr rows)
nn (vl-string-search "=" xx)
) ;;关键字不合法时 nn=nil
(if nn
(setq xx (vl-string-trim " " (substr xx 1 nn))
secrow (cons xx secrow)
)
)
)
(reverse secrow)
)
;;返回指定关键字的值。 ss 表: 文件名、段落名、关键字、值
(defun yxp_read_key (ss / fname sec fn xx secrow rows nn)
(setq fname (car ss)
sec (vl-string-trim " " (cadr ss))
key (vl-string-trim " " (caddr ss)) ;;关键字,删除前后空格
fn (open (findfile fname) "r")
)
(while (setq xx (read-line fn))
(if (wcmatch xx "`[*`]")
(setq FLAG (= (vl-string-trim "[ ]" xx) sec))
)
(if FLAG (setq rows (cons xx rows)))
)
(close fn)
(setq rows (cdr (reverse rows)))
(while (setq xx (car rows))
(setq rows (cdr rows)
nn (vl-string-search "=" xx)
) ;;此前与 yxp_read_sec 函数相同
(if nn
(setq secrow
(cons
(list (vl-string-trim " " (substr xx 1 nn))
(vl-string-trim " " (substr xx (+ 2 nn)))
)
secrow
)
)
)
)
(setq ff (cadr (assoc key (reverse secrow))))
(if ff ff (cadddr ss))
)
(cond
;;转到帮助
((or (= ini-list '?) (= ini-list "?")) (vl-ini-get-help) (princ))
;;判断参数是否表类型
((/= (type ini-list) 'List) (princ "\n; 错误: 要求表参数") (princ))
;;判断参数数量
((> (length ini-list) 4) (princ "\n; 错误: 表参数太多") (princ))
;;判断第一个表参数是否字符型
((/= (type (car ini-list)) 'Str) (princ "\n; 错误: 要求字符型参数") (princ))
;;判断文件名是否 yxp_file_ext_key 类型
((null (wcmatch (strcase (car ini-list)) "*.INI"))
(princ "\n; 错误: 不是有效的 *.INI 文件名")
(princ)
)
;;路径长度限制
((> (strlen (car ini-list)) 256) (princ "\n; 错误: 路径及文件名长度超限") (princ))
;;判断第一个参数是否路径
((null (findfile (car ini-list))) (princ "\n; 错误: 不能读取的路径或文件名称") (princ))
;;第二个参数不存在,则返回 ini 文件所有段落名
((null (cadr ini-list)) (yxp_read_ini (car ini-list)))
;;判断第二个参数是否字符型
((/= (type (cadr ini-list)) 'Str) (princ "\n; 错误: 段落名称类型不正确") (princ))
;;判断段落名称是否合法,不能为空字符
((wcmatch (cadr ini-list) " ") (princ "\n; 错误: 段落名称不合法") (princ))
;;段落字符长度限制
((> (strlen (cadr ini-list)) 64) (princ "\n; 错误: 段落长度超限") (princ))
;;第三个参数不存在,则返回段落名下所有关键字
((null (caddr ini-list)) (yxp_read_sec ini-list))
;;判断关键字是否字符型
((/= (type (caddr ini-list)) 'Str) (princ "\n; 错误: 关键字类型不正确") (princ))
;;关键字是否合法,不能包含 = ,不能是空格
((wcmatch (caddr ini-list) "*=*, ") (princ "\n; 错误: 关键字不合法") (princ))
;;关键字长度限制
((> (strlen (caddr ini-list)) 64) (princ "\n; 错误: 关键字长度超限") (princ))
;;返回关键字的值
(t (yxp_read_key ini-list))
)
)
;;说明:保存 ini 配置文件, 程序编写: yxp 2015-8-16
;; 语法: (vl-ini-set ini-list)
;; 注意: 所有参数区分大小写!!!
;;参数: ini-list == (inifile section [key [value]])
;; inifile 必选, 字符型, 路径 + 文件名
;; section 必选, 字符型, 段落名, 长度不大于 64
;; key 可选, 字符型, 关键字, 长度不大于 64, 未设置时只保存段落
;; value 可选, 任意类型, 关键字的值, 长度不限, 未设置时关键字为空字符
;;返回值: 失败时返回 nil, 成功则返回保存的数据
(defun vl-ini-set (ini-list / vl-ini-set-help yxp_save_ini)
(defun vl-ini-set-help()
(princ
(strcat
"\n功能: 保存 ini 配置文件, 程序编写: yxp 2015-8-16"
"\n语法: (vl-ini-set ini-list)"
"\n注意: section key区分大小写!!!"
"\n参数: ini-list == (inifile section [key [value]])"
"\n inifile 必选, 字符型, 路径 + 文件名"
"\n section 必选, 字符型, 段落名, 长度不大于 64"
"\n key 可选, 字符型, 关键字, 长度不大于 64, 未设置时只保存段落"
"\n value 可选, 任意类型, 关键字的值, 长度不限, 未设置时关键字为空字符"
"\n返回值: 失败时返回 nil, 成功则返回保存的数据"
)
)
)
;;(setq C nil wc nil A nil B nil seq nil qq nil fa nil FLAG nil r1 nil r2 nil fb nil AA nil)
;; 读入 ini ,如果不存在,则创建, 如果存在,则修改
;; 算法:从后往前搜索段落名,找到后再从前往后搜索关键字(yxp_save_ini ss)
(defun yxp_save_ini (ss / C wc A B seq qq fa FLAG r1 r2 fb AA)
(setq fa (open (car ss) "r") sec (vl-string-trim " " (cadr ss)))
(if (caddr ss)
(setq key (vl-string-trim " " (caddr ss)) qq (strcat key " = ")
wc (strcat key "=*," key " =*")
)
)
(if (cadddr ss) (setq qq (strcat qq (vl-princ-to-string (cadddr ss)))))
(if fa
(progn
(while (setq xx (read-line fa)) (setq A (cons xx A)))
(close fa)
(setq AA A)
(if (caddr ss)
(progn
(while (setq r1 (car A))
(if (wcmatch (vl-string-trim " " r1) wc) (setq FLAG t))
(if (wcmatch r1 "`[*`]")
(if (= (vl-string-trim "[ ]" r1) sec)
(progn
(if FLAG
(progn (setq r2 (car B))
(while (null (wcmatch (vl-string-trim " " r2) wc))
(setq A (cons r2 A) B (cdr B) r2 (car B))
)
(setq C (append (reverse A) (cons qq (cdr B))))
)
(setq C (append (reverse A) (reverse (cons qq (reverse B)))))
)
(setq A nil)
)
(setq FLAG nil)
)
)
(setq B (cons r1 B) A (cdr A))
) ;; the end
(if (null C) (setq C (reverse (cons qq (cons (strcat "[" sec "]") (reverse B))))))
)
(progn
(while (setq r1 (car A))
(if (and (wcmatch r1 "`[*`]") (= (vl-string-trim "[ ]" r1) sec))
(setq A nil B nil)
(setq B (cons r1 B) A (cdr A))
)
)
(setq C (if B (reverse (cons (strcat "[" sec "]") (reverse B)))))
)
)
(if (null AA)
(if (caddr ss)
(setq C (list (strcat "[" sec "]") qq))
(setq C (list (strcat "[" sec "]")))
)
)
)
(setq C (list (strcat "[" sec "]") (if qq qq "")))
)
(if C
(progn
(setq fb (open (car ss) "w"))
(foreach x C (write-line x fb))
(close fb)
(if (= 3 (length ss)) "" (last ss))
)
)
)
(cond
;;转到帮助
((or (= ini-list '?) (= ini-list "?")) (vl-ini-set-help) (princ))
;;判断参数是否表类型
((/= (type ini-list) 'List) (princ "\n; 错误: 要求表参数") (princ))
;;判断参数数量
((or (< (length ini-list) 2) (> (length ini-list) 4))
(princ "\n; 错误: 表参数不足或太多")
(princ)
)
;;判断第一个表参数是否字符型
((/= (type (car ini-list)) 'Str) (princ "\n; 错误: 要求字符型参数") (princ))
;;判断文件名是否 yxp_file_ext_key 类型
((null (wcmatch (strcase (car ini-list)) "*.INI"))
(princ "\n; 错误: 不是有效的 *.INI 文件名")
(princ)
)
;;判断段落名是否字符型
((/= (type (cadr ini-list)) 'Str) (princ "\n; 错误: 段落名称类型不正确") (princ))
;;判断段落名称是否合法,不能为空字符
((wcmatch (cadr ini-list) " ") (princ "\n; 错误: 段落名称不合法") (princ))
;;判断第三个参数是否字符型
((and (caddr ini-list) (/= (type (caddr ini-list)) 'Str))
(princ "\n; 错误: 关键字类型不正确")
(princ)
)
;;判断关键字是否合法,不能为空字符
((and (caddr ini-list) (wcmatch (caddr ini-list) " "))
(princ "\n; 错误: 关键字不合法")
(princ)
)
;;前三个参数的字长限制
((or (> (strlen (car ini-list)) 256)
(> (strlen (cadr ini-list)) 64)
(and (caddr ini-list) (> (strlen (caddr ini-list)) 64))
)
(princ "\n; 错误: 参数字符长度超限")
(princ)
)
;;如果第三个参数不存在,则保存段落名
(t (yxp_save_ini ini-list))
)
)
读写INI文件
(progn
(setq
path (strcat (vla-get-Path (vlax-get-acad-object)) "\\Support\\WeiYuanBzArgs.INI")
argslst
(list
(list "InDim"
(list "intop" "1") (list "indown" "1") (list "inleft" "1") (list "inright" "1")
(list "inofftop" "80") (list "inoffdown" "80") (list "inoffleft" "80") (list "inoffright" "80")
)
(list "MidDim"
(list "midtop" "1") (list "middown" "1") (list "midleft" "1") (list "midright" "1")
(list "midofftop" "160") (list "midoffdown" "160") (list "midoffleft" "160") (list "midoffright" "160")
)
(list "OutDim"
(list "outtop" "1") (list "outdown" "1") (list "outleft" "1") (list "outright" "1")
(list "outofftop" "260") (list "outoffdown" "260") (list "outoffleft" "260") (list "outoffright" "260")
)
(list "DimDis"
(list "dimdistop" "240") (list "dimdisdown" "240") (list "dimdisleft" "120") (list "dimdisright" "120")
)
(list "FilterSize"
(list "dimfilter" "18/0/0") (list "ltpyes" "1") (list "ltpyno" "0")
(list "dimavoyes" "1") (list "dimavono" "0")
)
(list "DimSyn"
(list "inavoyes" "1") (list "inavono" "0")
(list "midavoyes" "1") (list "midavono" "0")
(list "outavoyes" "1") (list "outavono" "0")
)
)
)
;;说明:将lst表内容批量写入ini文件
;;参数:fptah:有效的ini文件路径,包括文件名和扩展名
;;参数:lst:写入内容表(list (list "段落名" (list "关键字" "值") (list "关键字" "值")···) (list "段落名" (list "关键字" "值") (list "关键字" "值")···)···)
(defun WriteIniFile(fptah lst / alst)
(setq alst '())
;;(if (not (findfile fptah)) (progn (setq file (open fptah "w")) (close file)))
(mapcar '(lambda(x) (setq sec (car x) olst (cdr x) lslst (mapcar '(lambda(y) (append (list fptah sec) y)) olst) alst (if alst (append alst lslst) lslst))) argslst)
(foreach x alst (vl-ini-set x))
(princ "\n写入成功!")
(prin1)
)
(WriteIniFile path argslst)
)