我在Python中有一个浮点值列表:
floats = [3.14, 2.7, 0.0, -1.0, 1.1]
Run Code Online (Sandbox Code Playgroud)
我想使用IEEE 32位编码将这些值写入二进制文件.在Python中执行此操作的最佳方法是什么?我的列表实际上包含大约200 MB的数据,所以"不太慢"的东西是最好的.
由于有5个值,我只想要一个20字节的文件作为输出.
Nad*_*mli 40
亚历克斯是绝对正确的,这样做效率更高:
from array import array
output_file = open('file', 'wb')
float_array = array('d', [3.14, 2.7, 0.0, -1.0, 1.1])
float_array.tofile(output_file)
output_file.close()
Run Code Online (Sandbox Code Playgroud)
然后像这样读取数组:
input_file = open('file', 'rb')
float_array = array('d')
float_array.fromstring(input_file.read())
Run Code Online (Sandbox Code Playgroud)
array.array.fromfile如果您事先知道项目的数量(例如,从文件大小或其他一些机制),对象也有一个可用于读取文件的方法
the*_*met 20
请参阅:Python的struct模块
import struct
s = struct.pack('f'*len(floats), *floats)
f = open('file','wb')
f.write(s)
f.close()
Run Code Online (Sandbox Code Playgroud)
Gra*_*ant 10
我不确定NumPy会如何比较你的应用程序的性能,但它可能值得研究.
使用NumPy:
from numpy import array
a = array(floats,'float32')
output_file = open('file', 'wb')
a.tofile(output_file)
output_file.close()
Run Code Online (Sandbox Code Playgroud)
导致20字节的文件.
我在无意中编写 100+ GB 的 csv 文件时遇到了类似的问题。这里的答案非常有帮助,但是为了深入了解,我概述了提到的所有解决方案,然后是一些。所有分析运行均在配备 SSD 的 2014 Macbook Pro 上使用 python 2.7 完成。据我所知,从struct性能的角度来看,该方法绝对是最快的:
6.465 seconds print_approach print list of floats
4.621 seconds csv_approach write csv file
4.819 seconds csvgz_approach compress csv output using gzip
0.374 seconds array_approach array.array.tofile
0.238 seconds numpy_approach numpy.array.tofile
0.178 seconds struct_approach struct.pack method
Run Code Online (Sandbox Code Playgroud)
我的“答案”实际上是对各种答案的评论。我无法发表评论,因为我没有 50 声望。
如果要通过 Python 读回该文件,则使用“pickle”模块。这一工具可以以二进制方式读取和写入许多内容。
但问题的提出方式是“IEEE 32 位编码”,听起来该文件将以其他语言读回。在这种情况下,应指定字节顺序。问题是大多数机器都是 x86,采用小端字节顺序,但排名第一的数据处理语言是 Java/JVM,使用大端字节顺序。所以Python的“tofile()”会使用C语言,由于机器是little-endian,C语言使用little endian,然后Java/JVM上的数据处理代码将使用big endian进行解码,从而导致错误。
要使用 JVM:
# convert to bytes, BIG endian, for use by Java
import struct
f = [3.14, 2.7, 0.0, -1.0, 1.1]
b = struct.pack('>'+'f'*len(f), *f)
with open("f.bin", "wb") as file:
file.write(b)
Run Code Online (Sandbox Code Playgroud)
在Java方面:
try(var stream = new DataInputStream(new FileInputStream("f.bin")))
{
for(int i = 0; i < 5; i++)
System.out.println(stream.readFloat());
}
catch(Exception ex) {}
Run Code Online (Sandbox Code Playgroud)
现在的问题是Python'f'*len(f)代码——希望解释器实际上不会创建一个超长的“ffffff...”字符串。
我会使用 numpy 数组和 byteswap
import numpy, sys
f = numpy.array([3.14, 2.7, 0.0, -1.0, 1.1], dtype=numpy.float32)
if sys.byteorder == "little":
f.byteswap().tofile("f.bin") # using BIG endian, for use by Java
else:
f.tofile("f.bin")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
43337 次 |
| 最近记录: |