0

我需要一个遍历文件中所有行的函数。
这是我到目前为止所拥有的:

def LineFeed(file):
    ret = ""
    for byte in file:
        ret = ret + str(byte)
        if str(byte) == '\r':
            yield ret
            ret = ""

文件中的所有行都以 \r(不是 \n)结尾,我正在以"rb" 模式读取它,(我必须以二进制格式读取此文件)。yield不起作用并且什么也不返回。也许有问题与比较?我只是不确定你如何在 python 中表示一个字节/字符。

我的想法是,如果您在“rb”文件上循环,它仍然会尝试迭代行而不是字节......,我该如何迭代字节?我的问题是我没有标准的行尾。我的文件也充满了 0x00 字节,我想把它们全部删除,所以我想我需要第二个 yield 函数,我怎么能实现它,我只是不知道如何在 python 中表示 0x00 字节或 NULL 字符。

4

5 回答 5

2

我认为您对“for x in file”的作用感到困惑。假设你有像“file = open(file_name)”这样的句柄,在这种情况下,字节将是一整行,而不是单个字符。因此,只有当整行包含一个回车符时,您才调用 yield。尝试将“byte”更改为“line”并使用第二个循环对其进行迭代。

于 2009-12-17T22:31:32.247 回答
2

也许如果你要解释这个文件代表什么,为什么它有很多'\x00',为什么你认为你需要以二进制模式阅读它,我们可以帮助你解决你的潜在问题。

否则,请尝试以下代码;它避免了对操作系统行尾约定的任何依赖(或干扰)。

lines = open("the_file", "rb").read().split("\r")
for line in lines:
    process(line)

编辑:ASCII NUL(不是“NULL”)字节是“\x00”。

于 2009-12-17T23:14:46.893 回答
1

如果您可以控制打开文件的方式,我建议您使用通用换行符打开它,因为如果您仅使用 'rb' 模式,\r 不会被识别为换行符,但如果您使用 '乌尔布'。

这仅在您的二进制文件中没有包含 \n 和 \r 时才有效,因为在使用通用换行符时会丢失 \r 和 \n 之间的区别。

假设您希望您的屈服线仍然被 \r 终止:

NUL = '\x00'
def lines_without_nulls(path):
    with open(path, 'Urb') as f:
        for line in f:
            yield line.replace(NUL, '').replace('\n', '\r')
于 2009-12-18T02:36:13.053 回答
0

编辑:

  • string1 += string2字符串连接很慢。尝试加入字符串列表。

  • structddaa 是对的——如果二进制文件只包含 ASCII,则不需要该包。此外,我的生成器在 EOF 之前返回最后一个 '\r' 之后的字符串。通过这两个小修复,我的代码与这个更新的答案可疑地相似(实际上相同)。

代码片段:

def LineFeed(f):
    ret = []
    while True:
        oneByte = f.read(1)
        if not oneByte: break
        # Return everything up to, but not including the carriage return
        if oneByte == '\r':
            yield ''.join(ret)
            ret = []
        else:
            ret.append(oneByte)
    if oneByte:
        yield ''.join(ret)
if __name__ == '__main__':
    lf = LineFeed( open('filename','rb') )

    for something in lf:
        doSomething(something)
于 2009-12-17T22:35:35.960 回答
0

因此,您的问题是遍历以二进制模式打开的文件中'\r'用作行分隔符的行。由于该文件处于二进制模式,因此您不能使用通用换行功能,事实证明,'\r'它不会被解释为二进制模式下的行分隔符。

在 Python 中按字符读取文件是一件非常低效的事情,但这里是您可以迭代行的方法:

def cr_lines(the_file):
    line = []
    while True:
        byte = the_file.read(1)
        if not byte:
            break
        line.append(byte)
        if byte == '\r':
            yield ''.join(line)
            line = []
    if line:
        yield ''.join(line)

为了提高效率,您需要读取更大的文本块并在迭代器中处理缓冲。请记住,如果在迭代时进行搜索,您可能会遇到奇怪的错误。防止这些错误需要文件的子类,以便您可以在搜索时清除缓冲区。

注意''.join(line)成语的使用。累积一个字符串+=具有糟糕的性能,并且是初学者经常犯的错误。

于 2009-12-17T23:06:37.453 回答