【问题标题】:Character reading from file in Python在 Python 中从文件中读取字符
【发布时间】:2010-09-13 22:44:47
【问题描述】:

在一个文本文件中,有一个字符串“我不喜欢这个”。

但是,当我将它读入字符串时,它变成了“我不喜欢这样\xe2\x80\x98t”。我知道 \u2018 是“'”的 unicode 表示。我用

f1 = open (file1, "r")
text = f1.read()

执行读取的命令。

现在,是否有可能以这样的方式读取字符串,当它被读入字符串时,它是“我不喜欢这个”,而不是“我不喜欢这样\xe2\x80\x98t这个”?

第二次编辑:我看到有人使用映射来解决这个问题,但实际上,没有内置的转换可以进行这种 ANSI 到 unicode(反之亦然)的转换吗?

【问题讨论】:

  • 一些cmets:我看到有人使用映射来解决这个问题,但实际上,没有内置的转换可以进行这种ANSI到unicode(反之亦然)的转换吗?谢谢!
  • 没有,因为有数十万个 Unicode 代码点。你将如何决定哪些应该映射到哪些 ASCII 字符?
  • 顺便说一句,你的文本文件坏了! U+2018 是“左单引号”,而不是撇号(U+0027 最常见)。
  • 约翰,您的评论是错误的,至少在一般意义上是错误的。 iconv 库可用于将 unicode 字符音译为 ascii(甚至取决于语言环境。$ python -c 'print u"\u2018".encode("utf-8")' | iconv -t 'ascii//translit' | xxd 0000000: 270a
  • 问题是,您需要将 UNICODE 转换为 ASCII(而不是相反)。

标签: python unicode encoding ascii


【解决方案1】:

实际上,U+2018 是特殊字符‘ 的 Unicode 表示。如果需要,可以使用以下代码将该字符的实例转换为 U+0027:

text = text.replace (u"\u2018", "'")

另外,你用什么来写文件? f1.read() 应该返回一个如下所示的字符串:

'I don\xe2\x80\x98t like this'

如果它返回 this 字符串,则文件写入不正确:

'I don\u2018t like this'

【讨论】:

  • 对不起!正如你所说,它正在返回'I don\xe2\x80\x98t like this'
  • 您所看到的“我不喜欢这样\xe2\x80\x98t”就是Python 所说的str。它似乎是 u'I don\u2018t like this' 的 utf-8 编码,它是 Python 中的 unicode 实例。尝试在前者上调用 .decode('utf-8') 或在后者上调用 .encode('utf-8')。
  • @hop: 哎呀,忘了 ord() 返回十进制而不是十六进制。谢谢你的收获。
【解决方案2】:

这是 Python 向您展示 unicode 编码字符串的方式。但我认为您应该能够在屏幕上打印字符串或将其写入新文件而不会出现任何问题。

>>> test = u"I don\u2018t like this"
>>> test
u'I don\u2018t like this'
>>> print test
I don‘t like this

【讨论】:

    【解决方案3】:

    参考:http://docs.python.org/howto/unicode

    因此从文件中读取 Unicode 很简单:

    import codecs
    with codecs.open('unicode.rst', encoding='utf-8') as f:
        for line in f:
            print repr(line)
    

    也可以在更新模式下打开文件,允许读写:

    with codecs.open('test', encoding='utf-8', mode='w+') as f:
        f.write(u'\u4500 blah blah blah\n')
        f.seek(0)
        print repr(f.readline()[:1])
    

    编辑:我假设您的预期目标只是能够将文件正确读入 Python 中的字符串。如果您尝试从 Unicode 转换为 ASCII 字符串,那么实际上没有直接的方法可以这样做,因为 Unicode 字符不一定存在于 ASCII 中。

    如果您尝试转换为 ASCII 字符串,请尝试以下方法之一:

    1. 如果您只想处理一些特殊情况,例如这个特定示例,请将特定的 unicode 字符替换为 ASCII 等效字符

    2. 使用unicodedata 模块的normalize()string.encode() 方法尽可能转换为下一个最接近的ASCII 等效项(参考https://web.archive.org/web/20090228203858/http://techxplorer.com/2006/07/18/converting-unicode-to-ascii-using-python):

      >>> teststr
      u'I don\xe2\x80\x98t like this'
      >>> unicodedata.normalize('NFKD', teststr).encode('ascii', 'ignore')
      'I donat like this'
      

    【讨论】:

    • codecs 模块无法正确处理通用换行符模式。在 Python 2.7+ 上使用 io.open() 代替(它在 Python 3 上内置 open())。
    【解决方案4】:

    但它确实是“我不喜欢这个”而不是“我不喜欢这个”。字符 u'\u2018' 是一个与“'”完全不同的字符(并且在视觉上应该更对应于 '`')。

    如果您尝试将编码的 unicode 转换为纯 ASCII,您也许可以保留一个您想要转换为 ASCII 的 unicode 标点符号的映射。

    punctuation = {
      u'\u2018': "'",
      u'\u2019': "'",
    }
    for src, dest in punctuation.iteritems():
      text = text.replace(src, dest)
    

    不过,punctuation characters in unicode 的数量非常多,但我想您只能指望其中的几个实际上被创建您正在阅读的文档的任何应用程序所使用。

    【讨论】:

    • 实际上,如果您将 dict 将 Unicode 序数映射为 Unicode 序数 ({0x2018: 0x27, 0x2019: 0x27}),您只需将整个 dict 传递给 text.translate() 即可完成所有替换一口气。
    【解决方案5】:

    有几点需要考虑。

    \u2018 字符可能仅作为 Python 中 unicode 字符串表示的片段出现,例如如果你写:

    >>> text = u'‘'
    >>> print repr(text)
    u'\u2018'
    

    现在,如果您只是想漂亮地打印 unicode 字符串,只需使用 unicode 的 encode 方法:

    >>> text = u'I don\u2018t like this'
    >>> print text.encode('utf-8')
    I don‘t like this
    

    为了确保任何文件中的每一行都被读取为 unicode,您最好使用codecs.open 函数而不是仅仅使用open,它允许您指定文件的编码:

    >>> import codecs
    >>> f1 = codecs.open(file1, "r", "utf-8")
    >>> text = f1.read()
    >>> print type(text)
    <type 'unicode'>
    >>> print text.encode('utf-8')
    I don‘t like this
    

    【讨论】:

      【解决方案6】:

      有可能你有一个带有 unicode 转义字符的非 unicode 字符串,例如:

      >>> print repr(text)
      'I don\\u2018t like this'
      

      这实际上曾经发生在我身上。您可以使用unicode_escape 编解码器将字符串解码为 un​​icode,然后将其编码为您想要的任何格式:

      >>> uni = text.decode('unicode_escape')
      >>> print type(uni)
      <type 'unicode'>
      >>> print uni.encode('utf-8')
      I don‘t like this
      

      【讨论】:

        【解决方案7】:

        暂且不说您的文本文件已损坏(U+2018 是左引号,而不是撇号):iconv 可用于将 unicode 字符音译为 ascii。

        您必须在谷歌上搜索“iconvcodec”,因为该模块似乎不再受支持,而且我找不到它的规范主页。

        >>> import iconvcodec
        >>> from locale import setlocale, LC_ALL
        >>> setlocale(LC_ALL, '')
        >>> u'\u2018'.encode('ascii//translit')
        "'"
        

        您也可以使用iconv 命令行实用程序来清理您的文件:

        $ xxd foo
        0000000: e280 980a                                ....
        $ iconv -t 'ascii//translit' foo | xxd
        0000000: 270a                                     '.
        

        【讨论】:

          【解决方案8】:

          也可以使用python 3读取方​​法读取编码的文本文件:

          f = open (file.txt, 'r', encoding='utf-8')
          text = f.read()
          f.close()
          

          使用此变体,无需导入任何其他库

          【讨论】:

            【解决方案9】:

            不确定 (errors="ignore") 选项,但它似乎适用于具有奇怪 Unicode 字符的文件。

            with open(fName, "rb") as fData:
                lines = fData.read().splitlines()
                lines = [line.decode("utf-8", errors="ignore") for line in lines]
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-05-04
              • 2016-04-11
              • 2015-01-28
              • 2010-12-25
              • 2012-09-05
              • 2018-12-06
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多