Python二进制EOF

时间:2014-08-23 19:51:01

标签: python binary eof

我想通读二进制文件。 谷歌搜索" python二进制文件"带领我here

现在,问题:

  1. 为什么容器(SO答案中的x)不包含单个(当前)字节,而是包含大量字节?我做错了什么?
  2. 如果它应该如此,我没有做错什么,怎么读一个字节?我的意思是,有没有办法在用read(1)方法读取文件时检测EOF?

4 个答案:

答案 0 :(得分:8)

引用documentation

  

<强> file.read([size])

     

从文件中读取最多大小字节(如果读取命中EOF ,则在获取大小字节之前减去)。如果size参数为负数或省略,则读取所有数据,直到达到EOF。字节作为字符串对象返回。 立即遇到EOF时会返回空字符串。 (对于某些文件,如ttys,在EOF被命中后继续读取是有意义的。)注意,此方法可能多次调用底层C函数fread(),以尽可能接近大小字节。另请注意,在非阻塞模式下,即使没有给出大小参数,也可能返回的数据少于请求的数据。

这意味着(对于regular file):

  • f.read(1)将返回一个包含1字节或0字节的字节对象,并且已达到EOF
  • f.read(2)将返回一个包含2个字节的字节对象,如果在第一个字节后达到EOF则返回1个字节,如果立即遇到EOF,则返回0个字节。
  • ...

如果您想一次读取一个字节的文件,则必须在循环中read(1)并测试&#34;空白&#34;结果:

# From answer by @Daniel
with open(filename, 'rb') as f:
    while True:
        b = f.read(1)
        if not b:
            # eof
            break
        do_something(b)

如果你想通过&#34; chunk&#34;来阅读你的文件。比方说,一次50个字节,你必须在循环中read(50)

with open(filename, 'rb') as f:
    while True:
        b = f.read(50)
        if not b:
            # eof
            break
        do_something(b) # <- be prepared to handle a last chunk of length < 50
                        #    if the file length *is not* a multiple of 50

事实上,你甚至可能更早地打破一次迭代:

with open(filename, 'rb') as f:
    while True:
        b = f.read(50)
        do_something(b) # <- be prepared to handle a last chunk of size 0
                        #    if the file length *is* a multiple of 50
                        #    (incl. 0 byte-length file!)
                        #    and be prepared to handle a last chunk of length < 50
                        #    if the file length *is not* a multiple of 50
        if len(b) < 50:
            break

关于你问题的其他部分:

  

为什么容器[..]包含[..]一大堆[bytes]?

参考that code

for x in file:  
   i=i+1  
   print(x)  

再次引用the doc

  

文件对象是它自己的迭代器,[..]。当文件用作迭代器时,通常在for循环中(例如,对于f:print line.strip()中的行),将重复调用next()方法。此方法返回下一个输入行,或者当文件打开以进行读取时触发EOF时引发StopIteration(当文件打开以进行写入时,行为未定义)。

上面的代码逐行读取二进制文件。这是在EOL char(\n)每次出现时停止的。通常,这导致各种长度的块,因为大多数二进制文件包含随机分布的char的出现。

我不鼓励您以某种方式阅读二进制文件。请选择基于read(size)的解决方案。

答案 1 :(得分:4)

""将表示文件的结尾

with open(filename, 'rb') as f:
    for ch in iter(lambda: f.read(1),""): # keep calling f.read(1) until end of the data
        print ch

答案 2 :(得分:1)

逐字节读取:

with open(filename, 'rb') as f:
    while True:
        b = f.read(1)
        if not b:
            # eof
            break
        do_something(b)

答案 3 :(得分:0)

这就是我所做的。当read的调用遇到文件末尾时,返回一个伪造的值,这终止了循环。使用while ch != "":复制了图像,但是却给了我一个死循环。

from sys import argv
donor = argv[1]
recipient = argv[2]
# read from donor and write into recipient
# with statement ends, file gets closed
with open(donor, "rb") as fp_in:
    with open(recipient, "wb") as fp_out:
        ch = fp_in.read(1)
        while ch:
            fp_out.write(ch)
            ch = fp_in.read(1)