Python - 从一个文件读取数据并有选择地写入新文件

时间:2014-12-05 22:08:39

标签: python writing

提前感谢您的帮助。

我是Python的新手,我正在尝试将文件从一种格式转换为另一种格式。

这是我的代码:

fs = open('sample_data.txt','r')
fnew = open('sample_output.txt','w')
with fs as f:
    while True:
        line = f.readline()
        if line and line[0]=='#':
            print(line)
            fnew.write(line + '\n')
        else:
            data=line.split()
            fnew.write(data[0])
        if not line:  break

print('end of program')
fs.close
fnew.close

文件的基本格式在顶部包含注释标题,后跟数据行。

我遇到的问题是我的fnew.write(data [0])行。我收到以下错误:

IndexError:列表索引超出范围

分割线分解了八列数据,其中我要删除前两列。所以,最终,我想要做的是重写整个文件减去前两列。我需要做一些更复杂的重新格式化,但我希望如果我能理解这一步中的错误,我可能会想出如何完成其​​余的工作。

-------------- UPDATE

abarnet,你是​​对的。这是导致错误的换行符。但是,在尝试添加支票时,我遇到了另一个问题,就像你说的那样。当我执行下面的代码时,一切都冻结在我身上。如果我删除“if data:”检查,那么它会运行,但会给我相同的“索引超出范围”错误。

我还尝试按下面的方法运行它,删除了“if data:”检查,并且使用了一个不包含换行符的示例数据文件,它也冻结了我。

任何人都可以解释可能造成这种情况的原因吗?

fs = open('sample_data.txt','r')
fnew = open('sample_output.txt','w')
with fs as f:
    while True:
        line = f.readline()
        for line in f:
            if line[0]=='#':
                print(line)
                fnew.write(line + '\n')
            else:
                data=line.split()
                if data:
                    print(data[0])
                    fnew.write(data[0] + '\n')

print('end of program')
fs.close
fnew.close

--------------更新2

以下代码有效。感谢abarnet澄清无限循环问题。我遇到的最后一个问题是数据的第一行,无论是换行还是标题行都被忽略,并且不会在输出中打印。

with open('sample_data.txt','r') as f, open('sample_output.txt','w') as fnew:
    line = f.readline()
    for line in f:
        if line[0]=='#':
            print(line)
            fnew.write(line + '\n')
        else:
            data=line.split()
            if data:
                print(data[0])
                fnew.write(data[0] + '\n')

print('end of program')
fnew.close()

1 个答案:

答案 0 :(得分:1)

首先,如果line为空,会发生什么?

您最终会到达if not line: break。但是在你到达那里之前,你将会到达第一个else:(因为line and line[0]=='#'并非如此)。因此,您的data = line.split()会给您data = []。然后data[0]会提出IndexError

首先移动if not line: break测试:

while True:
    line = f.readline()
    if not line:
        break
    elif line[0]=='#':
        print(line)
        fnew.write(line + '\n')
    else:
        data=line.split()
        fnew.write(data[0])

话虽如此,首先要写一个更简单的方法。循环遍历文件将逐个给出每一行,就像while周围的readline循环一样,除了当它到达EOF时,循环自动结束而不需要测试任何内容或{{ 1}}。

break

但如果行不是为空,如果它只是空白或纯空白,会发生什么?例如,当您在for line in f: if line[0]=='#': print(line) fnew.write(line + '\n') else: data=line.split() fnew.write(data[0]) 上致电split()时会发生什么?再次,你得到一个空列表。所以,如果可能的话,你又会遇到同样的问题 - 当然,在这种情况下你可能不想' \n'。我不确定你想做什么,但是让我们说你想跳过空白链接。所以只需将break块替换为:

else

作为旁注,在第一种情况下执行data=line.split() if data: fnew.write(data[0]) 非常奇怪,其中该行已在fnew.write(line + '\n')中结束,因此您只需添加额外的换行符,但在另一种情况下为\n,其中fnew.write(data[0])并未在换行符中结束,因此您只需将第一列的一行合并为一个巨大的单词与下一个评论到底......


新代码的问题在于,您使用data[0]循环代替替换<{em> while True: readline()周围的for line in f:循环两个

所以,第一次通过while循环,它读取第一行,然后读取文件中的每一行,然后完成。然后,第二次通过while循环,它读取结尾处剩下的所有内容,然后读取剩下的所有0行,然后结束。它会一直持续下去,一遍又一遍地阅读最后的0行,直到时间结束,因为你永远不会breakwhile True:

您的更新代码中还有一些其他问题。

  • fs.close只是引用方法,而不实际调用它。您需要括号来进行通话,例如fs.close()
  • 但你无论如何都不想要fs.close(); with语句的重点在于它会自动关闭文件。
  • 您可能也想对with使用fnew语句。

所以:

with open('sample_data.txt','r') as f, open('sample_output.txt','w') as fnew:
    for line in f:
        if line[0]=='#':
            print(line)
            fnew.write(line + '\n')
        else:
            data=line.split()
            if data:
                print(data[0])
                fnew.write(data[0] + '\n')

print('end of program')