Python 读取文件请教

2022-05-06 21:43:49 +08:00
 zxCoder

读取一种类型的文本文件,里面内容是这样的:

00401000 56 8D 44 24 08 50 8B F1 E8 94 B7 01 00 C7 06 74
00401010 BE 54 00 8B C6 5E C2 04 00 CC CC CC CC CC CC CC
00401020 C7 01 74 BE 54 00 E9 9E B8 01 00 CC CC CC CC CC
00401030 56 8B F1 C7 06 74 BE 54 00 E8 8B B8 01 00 F6 44
00401040 24 08 01 74 09 56 E8 E4 BA 01 00 83 C4 04 8B C6
00401050 5E C2 04 00 CC CC CC CC CC CC CC CC CC CC CC CC
00401060 8B 44 24 08 C3 CC CC CC CC CC CC CC CC CC CC CC
00401070 C3 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
00401080 8B 44 24 08 66 8B 08 8B 54 24 04 66 89 0A C3 CC
00401090 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
.....

有好几十万行。

我想把后面那些 16 进制的数字依次转换成 10 进制,存到一个 list 里。

我现在代码读取很慢,读一个文件要几十分钟

with open(f"{file_name}", "r") as rd:
    arr = []
    for line in tqdm(rd.readlines()):
        arr.extend([int(f"0x{a}", 16) for a in line.strip().split(" ")[1:]])
    return np.array(arr, dtype=np.ubyte)

有没有更快的方法,求大佬解答

1415 次点击
所在节点    问与答
16 条回复
ysc3839
2022-05-06 21:52:29 +08:00
没太看懂你的需求和代码,你是要转成十进制整数字符串吗?代码中好像没有相关操作
至于解决的话,试试改成流式处理,即不要预先读取过多数据
zxCoder
2022-05-06 22:05:50 +08:00
@ysc3839 [int(f"0x{a}", 16) for a in line.strip().split(" ")[1:]] 我这里是把一行的十六进制转成十进制的。太多行了,跑半天
ynyounuo
2022-05-06 22:15:02 +08:00
你这个需求似乎没有必要 serial
zxCoder
2022-05-06 22:18:19 +08:00
@ynyounuo 啥意思老哥
imn1
2022-05-06 22:31:22 +08:00
@zxCoder #3 的意思是让你整个文件读入 numpy 或者 pandas ,然后用一个函数 apply 到每个单元格

内存足够的话整体读入,不够才需要逐行读入
ysc3839
2022-05-06 22:38:11 +08:00
@zxCoder 你这是转成整数,整数在计算机里是二进制的,并不是十进制。一般提到十进制、十六进制等指的都是相应进制的数字文本。
zxCoder
2022-05-06 22:40:39 +08:00
@imn1 懂了懂了 多谢
dcsuibian
2022-05-06 22:44:19 +08:00
很久没接触 Python 了,看不太懂 arr.extend
你这一行是 56 个字符,加一个回车一行 57 个。都是 ascii 算一个字节。一行就 57 个字节。算一百万行,就是 57x100x10000/1024/1024=54.3MB ,这么小的量。
直接读进来放内存里,一秒都不到,明显是你这处理方式有问题。
dcsuibian
2022-05-06 22:47:19 +08:00
而且仔细看才发现,你这 rd.readlines()函数调用的时候就已经全部读到内存了。
clino
2022-05-06 22:50:19 +08:00
读取应该花不了太多时间,但是处理数据花的时间会比较多,你可以把处理数据的代码去掉测试一下看看。
chi1st
2022-05-06 22:57:33 +08:00
用 pandas
misaka19000
2022-05-06 23:19:34 +08:00
先看一下瓶颈在哪啊,是 CPU 满了还是内存满了
wangyongbo
2022-05-06 23:56:19 +08:00
你可以把你的文件发出来,让大家测试一下吗?
ysc3839
2022-05-07 04:09:07 +08:00
用你给的数据重复了 500000 次(你给的数据有十行,总共有五百万行了)输出到文件,然后用你的代码去掉 tqdm 后在本地跑了下,也就耗时 23 秒,哪要几十分钟?

自己写的代码耗时 5 秒
```
with open('test.txt', 'r') as f:
arr = bytearray()
for line in f:
i = line.find(' ')
if i == -1:
print('!')
break
arr.extend(bytes.fromhex(line[i + 1:]))
print(len(arr))
```
空格请自行补全
yzwduck
2022-05-07 07:40:59 +08:00
@ysc3839 如果不介意多耗一点内存的话,这样写的代码会跑得更快。

```
with open('test.txt', 'r') as fi:
data.fi.read()

arr = bytes.fromhex(re.sub(r'^[0-9A-Fa-f]+ ', '', data, flags=re.MULTILINE))
```
BingoXuan
2022-05-07 09:41:58 +08:00
想起客户提供的同行的烂代码,处理 30 秒 wave 文件要 35 秒

pattern = re.compile('[0-9A-F]{2}')
def read_file(name):
----with open(name,'r') as f:
--------while True:
------------l = f.readline()
------------if not l:
----------------break
------------for x in pattern.findall(l):
----------------yield int(x,16)
result = [y for y in read_file('some file')]

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/851249

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX