376394482 发表于 2024-1-4 11:26:14

求一个读取文件的LISP代码

有一种数据文件,用Matlab读取,代码为:

Fp_ID = fopen(f_path,'rb');f_path文件路径
Data = fread (Fp_ID,'int16');% 16位2字节有符号整数格式读取文件数据

读取后Data数据为786544×1 Double。
前20行数据为:

4
0
2368
2500
2500
12288
4
-4161
-8040
3087
5218
-4473
-8496
2454
6658
-4680
-7774
1923
7499
-4707

读取后的数据我可以用LISP实现处理与制图。但每次都需要用Matlab先转换一道手续,形不成一个完整的LISP工具。
现请各位高手帮忙研究下用LISP怎么正确读取这个文件。

baitang36 发表于 2024-1-6 22:42:24

376394482 发表于 2024-1-5 15:51
用@nonsmall 不死猫的binaryToText函数:

lst1返回:(4 0 1344 2372 2372 12288 4 32627 32623 32621...

syz-bin.fas只是转化了两个保留函数。syz-read-bin对应于保留函数_read-nb
syz-write-bin 对应于保留函数_write-nb-str
关于内部隐藏保留函数的用法,请在论坛搜。

baitang36 发表于 2024-1-4 12:12:14

本帖最后由 baitang36 于 2024-1-4 14:17 编辑

你的意思是把tg文件变成这种文本文件?
实验了一下,大文件处理很慢,cad直接死了。看来还需要优化。lsp处理这种二进制文件没有优势,最快的方法是用汇编写个tg2txt,可以优化到极致。

(load "c:/00/syz-bin.fas")
(setq fi (open "d:/00/test.tg" "r"))
(setq str1 (syz-read-bin 8000000 fi)) ;用read-char读到1a就会结束,文件读不全,改用二进制读。
(setq len12 (/ (strlen str1) 2))
(close fi)
(setq i 1)
(setq str2 "")
(repeat      8000      ;len12 文件大了很慢,cad死了
(setq num1 (ascii (substr str1 i 1)))
(setq num2 (ascii (substr str1 (+ i 1) 1)))
(setq num (+ num1 (* 256 num2)))
(if (> num 32767)
    (setq num (- num 65536))
) ;_ if
(setq str2 (strcat str2 (itoa num) "\n"))
(setq i (+ i 2))
) ;_ repeat
(setq fo (open "d:/00/test1.txt" "w"))
;(write-line str2 fo);write-line慢,改成二进制写试试
(syz-write-bin str2 fo)
(close fo)


liuhe 发表于 2024-1-5 08:48:03

baitang36 发表于 2024-1-4 12:12
你的意思是把tg文件变成这种文本文件?
实验了一下,大文件处理很慢,cad直接死了。看来还需要优化。lsp处 ...

大佬,这个lsp字符串是不是有大小限制啊

376394482 发表于 2024-1-5 15:51:21

baitang36 发表于 2024-1-4 12:12
你的意思是把tg文件变成这种文本文件?
实验了一下,大文件处理很慢,cad直接死了。看来还需要优化。lsp处 ...
用@nonsmall 不死猫的binaryToText函数:
;Subject:binary conversion to text by lisp 二进制文件转文本
;Writen:nonsmall(不死猫)
;Date:2009 10 18
;All Rights Reserved 版权所有 nonsmall(不死猫)
;Contact: QQ:43797405 Email:nonsmall@163.com
(defun binaryToText(FileName / ADODB.Stream)
(Setq ADODB.Stream (Vlax-Get-Or-Create-Object "ADODB.Stream" ))
(Vlax-Put-Property ADODB.Stream 'Type 1 )
(Vlax-Invoke ADODB.Stream 'Open )
(Vlax-Invoke-Method ADODB.Stream 'LoadFromFile FileName )
(Vlax-Put-Property ADODB.Stream 'Position 0 )
(Vlax-Invoke-Method ADODB.Stream 'Write (car (list (Vlax-Invoke-Method ADODB.Stream 'Read (Vlax-Get ADODB.Stream 'Size )) (Vlax-Put-Property ADODB.Stream 'Position 0 ))))
(Vlax-Put-Property ADODB.Stream 'Position 0 )
(Vlax-Put-Property ADODB.Stream 'Type 2 )
(Vlax-Put-Property ADODB.Stream 'CharSet "us-ascii" )
(Vlax-Invoke ADODB.Stream 'ReadText)
;(vlax-release-object ADODB.Stream)
)

(setq data (binaryToText (setq filename (getfiled "" (if filename filename "") "" 8))))
(setq lst1 nil)
(setq i 1)
(repeat20      
(setq num1 (ascii (substr data i 1)))
(setq num2 (ascii (substr data (+ i 1) 1)))

(setq num (+ num1 (* 256 num2)))
(if (> num 32767)
    (setq num (- num 65536))
) ;_ if
(setq lst1 (append lst1 (list num)))
(setq i (+ i 2))
)
lst1返回:(4 0 1344 2372 2372 12288 4 32627 32623 32621 32608 32627 32623 32621 32608 32627 32623 32621 32608 32627)

用@baitang36 的syz-read-bin函数:
(vl-load-com)
(or syz-read-bin (load (setq sysname (getfiled "" (if sysname sysname "") "" 8))))
(setq fi (open (getfiled "" (if filename filename "") "" 8) "r"))
(setq data2 (syz-read-bin 8000000 fi))
(close fi)
(setq i 1)
(setq lst2 nil)
(repeat20   
(setq num1 (ascii (substr data2 i 1)))
(setq num2 (ascii (substr data2 (+ i 1) 1)))
(setq num (+ num1 (* 256 num2)))
(if (> num 32767)
    (setq num (- num 65536))
) ;_ if
(setq lst2 (append lst2 (list num)))
(setq i (+ i 2))
)
lst2返回:(4 0 2368 2500 2500 12288 4 -4161 -8040 3087 5218 -4473 -8496 2454 6658 -4680 -7774 1923 7499 -4707)
lst2和Matlab的一致,
请问@nonsmall 不死猫的binaryToText函数要怎么用?
还有,@baitang36 的syz-read-bin函数能给源码吗?

baitang36 发表于 2024-1-6 22:47:17

本帖最后由 baitang36 于 2024-1-6 22:49 编辑

liuhe 发表于 2024-1-5 08:48
大佬,这个lsp字符串是不是有大小限制啊
在lsp程序中定义的字符串,大小不能超过65535,因为表示字符串的55h指令是用两个字节来表示字符串长度。两个字节能表示的最大数字是65535.

运行过程中生成的字符串的大小没有限制,但实际实验中6M以下没问题,6M以上有时不稳定,没找到原因,可能跟内存使用有关

liuhe 发表于 2024-1-7 08:30:57

baitang36 发表于 2024-1-6 22:47
在lsp程序中定义的字符串,大小不能超过65535,因为表示字符串的55h指令是用两个字节来表示字符串长度。 ...

大佬   多谢指点。我现在搞那个文件,想把文件打包成16位的字符串,写在lsp文件里面,直接报警字符串太长。

baitang36 发表于 2024-1-7 08:35:57

本帖最后由 baitang36 于 2024-1-7 08:37 编辑

liuhe 发表于 2024-1-7 08:30
大佬   多谢指点。我现在搞那个文件,想把文件打包成16位的字符串,写在lsp文件里面,直接报警字符串太长 ...
你可以弄成多个小字符串,用strcat 连接起来。或弄成短一点的表,使用时用append连接起来

baitang36 发表于 2024-1-24 08:18:00

376394482 发表于 2024-1-5 15:51
用@nonsmall 不死猫的binaryToText函数:

lst1返回:(4 0 1344 2372 2372 12288 4 32627 32623 32621...

syz-bin.fas的源码
(setq syz-read-bin _read-nb)
(setq syz-write-bin _write-nb-str)

_read-nb和 _write-nb-str是系统保留函数,需要转换成普通函数才能用。
转换工具trf_9.fas
用法:加载后(tranf "_read-nb")

页: [1]
查看完整版本: 求一个读取文件的LISP代码