python 使用read函数遇到的问题

我用Python读取二进制文件。
前面的代码使用.read()函数很顺利
read(4)这就是read4个字节的意思。
结果突然,再用read(4),就显示读取了7个字节。
read(2),就显示读取了4个字节。
这是为啥啊?

下面是全部代码
```python

#Source code for 
# -*- coding: utf-8 -*-

import abc#abc模块是AbsructBaseClass的缩写
'''

'''
import os
import json
from typing import Optional, Any
import bz2
import gzip

import numpy as np


from cinrad.constants import MODULE_DIR
from cinrad._typing import Number_T
import struct


# -*- coding: utf-8 -*-
# Author: Puyuan Du

from collections import OrderedDict, defaultdict
from typing import Optional, Union, Any
import datetime
from io import BytesIO

import numpy as np
from xarray import Dataset, DataArray


with open("/mnt/e/config/maps/Z9010_20230512080000Z_HCL_02_164", "r",encoding='ISO-8859-1') as buf:#os.path.join()用来拼接路径gb2312
   ###########################读公共数据块-通用头块32个字节

    #把指标放到8个字节之后
    buf.seek(8)#seek这个不具有累加意味是指针,但是read有累加
    #读取4个字节是公共数据块-通用头块-04文件类型
    a1=buf.read(4).encode()#必须由encode转码成bytes,直接读出来是str   
    print (a1)
    gt = int.from_bytes(a1, byteorder='little', signed=True) # 仅可用于整数的单个数据转换方式是使用 int.from_bytes 函数。
    print(gt )

    #读取4个字节是公共数据块-通用头块-05产品类型。51代表HCL
    a2=buf.read(4).encode()
    print (a2)
    pt = int.from_bytes(a2, byteorder='little', signed=True) # 仅可用于整数的单个数据转换方式是使用 int.from_bytes 函数。
    print(pt )
    
    ###########################读公共数据块-站点配置块128个字节
    buf.seek(32)#seek这个不具有累加意味是指针,但是read有累加
    #读取4个字节是公共数据块-站点配置-01站号。51代表HCL
    a3=buf.read(8).encode()
    print (a3)
    sc = str(a3,'utf-8') # 仅可用于整数的单个数据转换方式是使用 int.from_bytes 函数。
    print(sc )
    
    
    #读取32个字节是公共数据块-站点配置-02站名。51代表HCL
    a4=buf.read(32).encode()
    
    print (a4)
    sn = str(a4,'utf-8') # 仅可用于整数的单个数据转换方式是使用 int.from_bytes 函数。
    print(sn )
    
    #读取4个字节是公共数据块-站点配置-03纬度。51代表HCL
    a5=buf.read(4).encode()
    print (len(a5))

    print (a5)
    slat = struct.unpack('f',a5) 
    print(slat )    


    a6=buf.read(4).encode()#就是这里,读取4个显示7个,读取3个显示6个,读取2个显示4个。搞得我后面用不了。之前都很正常
    print (len(a6))
    print (type(a6))
    print (a6)
    slon =  struct.unpack('f',a6) 
    print(slon)    
    

```

可能是因为文件中存在不可见字符或者换行符等特殊字符,导致读取的字节数不符合预期。建议使用二进制模式打开文件,即将文件打开方式改为"rb",并且使用struct.unpack()函数按照指定格式解析字节流。这样可以避免出现读取字节数不符合预期的情况。

可能是因为在读取数据时,文件指针有偏移,或者数据存在一些对齐的问题。可以尝试在每次读取数据时,打印出当前文件指针位置,以及读取的数据大小,来进一步排查问题。另外,也可以尝试使用其他的二进制文件读取方式来看是否出现同样的问题。

read函数是按照字节数读取数据的,但是它不保证每次读取的字节数总是与输入参数完全一致。这是因为,read函数是尽可能地读取指定数量的字节,但是文件中实际可读取的字节数可能比这个数字少。代码中,由于使用了seek函数来移动读取指针,可能会出现读取数量不一致的情况。
解决这个问题的一个方法是,使用一个循环来反复调用read函数。在每次读取之后,检查实际读取的字节数是否满足要求,如果不满足,则再次调用read函数读取剩余的数据,直到达到指定数量为止。另外,对于文件中可能存在的分段读取情况,也需要考虑相应的处理方法,例如,需要使用tell函数来获取当前读取指针的位置,并根据这个位置来确定下一次读取的起始点。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/7595918
  • 这篇博客也不错, 你可以看下12.6 Python read()函数:按字节(字符)读取文件
  • 除此之外, 这篇博客: Python 文件读取的4种方式中的 2.用read()打开 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    with open('filepath','r') as f:
        ff=f.read()
    

    这个函数把文件全部内容一次性读到一个字符串中。就是一坨的那种,如果把ff用循环读取的方式输出,会是一个一个字符,因为ff是字符串,本质上是tuple。

  • 以下回答来自chatgpt:

    这个问题的原因是文件的编码不是ASCII编码或者UTF-8编码,使用read()可以一次读取所有的数据,但使用read(num)指定读的字节数量时,可能因为编码的问题导致读取的数据长度不是预期的长度,具体原因需要根据文件的编码类型来确定。可以尝试使用二进制读取文件,这样可以避免编码产生的影响,即在open()函数中使用“rb”模式打开文件:

    with open('file.bin', 'rb') as f:
        data = f.read(4)  # 读取4个字节
    

    如果无法确定文件的编码类型,可以使用Python chardet模块检测文件的编码类型:

    import chardet
    
    with open('file.bin', 'rb') as f:
        data = f.read()
    
    # 检测文件编码类型
    encoding = chardet.detect(data)['encoding']
    print('File encoding:', encoding)
    
    # 以检测到的编码类型读取文件
    with open('file.bin', encoding=encoding) as f:
        data = f.read(4)  # 读取4个字节
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^