将 float 写为 bytearray 在 python 中产生换行符

writing float as bytearray produces newline in python

首先是短版,然后是长版:

短:

我有一个 float32 的二维矩阵。我想将它作为 bytearray 写入 .txt 文件。我还想保留结构,这意味着在一行的末尾添加一个换行符。一些数字,如 683.61,在转换为 bytearray 时包含 \n ,它会产生不需要的换行符,并将文件的读取弄乱为行。我该怎么做?

长:

我正在编写一个程序来处理大量数据(二维矩阵)。为此,我需要将阵列存储在磁盘上而不是存储在我的内存中,因为数据对于计算机的内存来说可能太大了。我创建了我自己的文件类型,该文件将由程序读取。它有一个 header,重要参数为字节,后跟矩阵为字节数组。

当我一次一个 float32 将数据写入文件时,我在矩阵一行的末尾添加了一个换行符 (\n),所以我保留了结构。

写入顺利,但读取会出现问题,因为某些数字一旦转换为字节数组,就会包含 \n。

举个例子:

struct.pack('f',683.61)

将产生

b'\n\xe7*D'

这会剪切我的矩阵行,有时还会在字节数组的中间剪切,从而导致字节数组大小错误。

来自这个问题:

我发现 str 可以用 'unicode_escape' 编码来加倍反斜杠,避免阅读时混淆。

Some_string.encode('unicode_escape')

但是,此方法仅适用于字符串,不适用于字节或字节数组。 (我试过了)意思是直接把float32转成bytearray写入文件就不能用了

我也试过将 float 转换为 bytearray,将 bytearray 解码为 str 并像这样重新编码:

struct.pack('f',683.61).decode('utf-8').encode('unicode_escape')

但解码无法解码字节数组。

我也试过直接将 bytearray 转换为字符串,然后像这样编码:

str(struct.pack('f',683.61)).encode('unicode_escape')

这会产生一个混乱,可以从中获得正确的字节:

bytes("b'\n\xe7*D'"[2:-1],'utf-8')

最后,当我实际读取字节数组时,无论是否使用了 unicode_escape,我都会得到两个不同的结果:

numpy.frombuffer(b'\n\xe7*D', dtype=float32)
    yields : array([683.61], dtype=float32)

numpy.frombuffer(b'\n\xe7*D', dtype=float32)
    yields : array([1.7883495e+34, 6.8086554e+02], dtype=float32)

我期待最高的结果,而不是最低的结果。所以我回到原点。

--> 如何在多行上将我的浮点矩阵编码为字节数组,而不受字节数组中换行符的影响?

F.Y.I。我用 numpy 解码 bytearray,因为这是我发现的工作方法,但这可能不是最好的方法。刚开始玩字节。

谢谢你的帮助。如果我的问题有任何问题,请告诉我,如果有错误,我很乐意正确重写。

您要么将数据写成二进制数据,要么您使用换行符来保持它的可读性——否则它甚至没有意义。

当您尝试将 "bytes" 记录到文件中,并将 float32 值原始作为 4 字节序列时,当然,这些字节中的每一个都可以具有 0-255 之间的任何值 - 还有一些其中将是控制字符。

备选方案是使用协议 0 序列化为一种格式,将字节值编码为可打印 ASCII 范围内的字符,例如 base64、Json,甚至 pickle。

也许对您来说最舒服的就是将原始字节写入二进制字节,然后更改您用来与之交互的程序 - 使用和 hexeditor像 "hexedit" 或午夜指挥官。两者都允许您以舒适的方式通过十六进制表示形式浏览字节,并将在文件中显示最终的 ASCII 文本序列。

对于任何和我有同样问题的人,试图让 readline 函数与字节一起工作,@jsbueno 的先前回答让我想到了其他方法来继续而不是修改字节。

如果您像我一样正在制作自己的字节数据文件,那么这里有一个替代方案。在经典的 read() 函数的基础上编写您自己的 readline() 函数,但具有自定义的 "newline character"。这是我的计算结果:

def readline(file, newline=b'Some_byte',size=None):
    buffer = bytearray()
    if size is None :
        while 1 :
            buffer += file.read(1)
            if buffer.endswith(newline):
                break
    else :
        while len(buffer) < size :
            buffer += file.read(1)
            if buffer.endswith(newline):
                break
    return buffer