【问题标题】:io.UnsupportedOperation: not readableio.UnsupportedOperation:不可读
【发布时间】:2012-11-02 10:53:11
【问题描述】:

我正在处理一个问题,它说要制作一个程序来获取用户对文件的输入,然后在文件中删除用户指定的字符串。我不知道如何从我所拥有的(下面)到问题所要求的。一如既往,非常感谢任何和所有帮助。

def main():
    outfile = open(input("Enter a file name: "), "a")
    string = input("Enter the string to be removed: ")
    for string in outfile.readlines():
        string = string.replace(string, "")
    outfile.close()
    print("Done")

main()

我接受了其中一个建议并试图让它工作,但正如我在下面的评论中所说,下面的代码不会返回错误,它会创建一个空文件。为了使新文件成为删除字符串的旧文件,我缺少什么?

def main():
    inpath = input("Enter an input file: ")
    line = input("Enter what you want to remove: ")
    outpath = input("Enter an output file: ")
    with open(inpath, "r") as infile, open(outpath, "w") as outfile:
        for line in infile:
            outfile.write(line.replace(line, "") + "\n")
    print("Done.")

main()

【问题讨论】:

  • 您必须以读取模式打开文件。试试"a+"
  • 附带说明,您有太多名为 string 的变量。你可能想要string1 = input(...),然后是string = string.replace(string1,"")。最后,您实际上需要将字符串写回文件中。就地替换文件中的字符串有点困难。通常,您使用修改后的内容创建一个新文件,然后在一天结束时将新文件移到旧文件之上。
  • @JBernardo:确实如此,但在这种情况下并没有真正的帮助。你不能只是在迭代读取文件的过程中写入文件——或者更确切地说,你可以,但它会做不愉快的事情,并且在不同的平台上会做不同的不愉快的事情。尽管如此,它仍然是一个起点——它是对 OP 标题提到的错误的直接解释。
  • @user60561 我的问题较旧,因此您提到的线程将是重复的。

标签: python python-3.x


【解决方案1】:

在进入细节之前有几点说明:当您调用string.replace(string, "") 时,您是在告诉字符串将其整个自身替换为空字符串——您不妨直接调用string = ""。大概第一个string 是要替换的搜索字符串,所以给它一个不同的名称,然后将其用作例如string.replace(searchString, "")。此外,您不想命名变量string,因为它是标准库模块的名称。您将输入文件称为“outfile”,这很容易造成混淆。您可能想要使用with 语句而不是显式关闭。最后,您可以使用 for line in f: 迭代文件中的行;你不需要for line in f.readlines()(而且,如果你需要处理Python 2.x,你会更乐意避免readlines(),因为它会将整个文件读入内存,然后生成一个巨大的列表内存中的行数)。

正如 JBernardo 指出的那样,第一个问题是您以“a”模式打开文件,这意味着“只写,追加到末尾”。如果要读写,可以使用“a+”或“r+”。

但是,这并不能真正帮助您。毕竟,你不能在读取过程中写入文件。

有几种常见的解决方法。

首先,只需写入标准输出,然后让用户对结果做任何他想做的事——例如,将其重定向到文件。 (在这种情况下,您将提示、“完成”消息等打印到标准错误,因此它们不会被重定向到文件。)这是许多 Unix 工具(如 sedsort)所做的, 所以如果你正在构建一个 Unix 风格的工具是合适的,但可能不适合其他目的。

def stderrinput(prompt):
    sys.stderr.write(prompt)
    sys.stderr.flush()
    return input()

def main():
    with open(stderrinput("Enter a file name: "), "r") as infile:
        searchString = stderrinput("Enter the string to be removed: ")
        for line in infile:
            print(infile.replace(searchString, ""))
    sys.stderr.write("Done\n")

其次,写入另一个文件。以“r”模式打开输入文件,以“w”模式打开输出文件,然后你只是在复制行:

def main():
    inpath = input("Enter an input file: ")
    outpath = input("Enter an output file: ")
    with open(inpath, "r") as infile, open("outpath", "w") as outfile:
        for line in infile:
            outfile.write(line.replace(searchString, "") + "\n")

第三,读取并处理内存中的整个文件,然后截断并重写整个文件:

def main():
    path = input("Enter an input/output file: ")
    with open(path, "r+") as inoutfile:
        lines = [line.replace(searchString, "") for line in inoutfile]
        inoutfile.seek(0)
        inoutfile.truncate()
        inoutfile.writelines(lines)

最后,写入一个临时文件(与第二个选项一样),然后将该临时文件移到原始输入文件的顶部。像这样的:

def main():
    path = input("Enter an input/output file: ")
    with open(path, "r") as infile, tempfile.NamedTemporaryFile("w", delete=False) as outfile:
        for line in infile:
            outfile.write(line.replace(searchString, ""))
        shutil.move(outfile.name, pathname)

最后一个有点棘手,因为 POSIX 和 Windows 之间存在差异。但是,它有一些很大的优势。 (例如,如果您的程序在运行过程中被杀死,那么无论发生什么情况,都可以保证您拥有原始文件或新文件,而不是写一半的乱七八糟的东西。)

【讨论】:

  • 你应该评论string = string.replace(string,"")在这个循环中是无稽之谈。在第二行,您要替换的字符串是第一行。
  • 情况更糟。在第二行,您的替换字符串是第二行。在每一行,您的替换字符串都是当前行。
  • 其实,想想看,既然第一行肯定是""both 语句结果都是真的……
  • 我知道我所拥有的有什么问题,问题是你有什么可能的解决方案我不明白我应该用它们做什么。一个就足够了,还是有必要将多个组合起来以获得所需的结果,或者我只是过于复杂了我需要为程序做的事情。
  • @JohnDziendziel:你只需要四个之一。但是你必须决定哪一个是你想要的,这意味着你必须了​​解它们的不同之处,并且还要了解你想要完成什么。
猜你喜欢
  • 2018-02-17
  • 1970-01-01
  • 2013-09-28
  • 2020-02-10
  • 1970-01-01
  • 2021-05-30
  • 2017-12-07
  • 1970-01-01
相关资源
最近更新 更多