繁体   English   中英

codecs.open(utf-8)无法读取纯ASCII文件

[英]codecs.open(utf-8) fails to read plain ASCII file

我有一个普通的ASCII文件。 当我尝试使用codecs.open(..., "utf-8")打开它时,我无法读取单个字符。 ASCII是UTF-8的子集,那么为什么codecs不能在UTF-8模式下打开这样的文件?

# test.py

import codecs

f = codecs.open("test.py", "r", "utf-8")

# ASCII is supposed to be a subset of UTF-8:
# http://www.fileformat.info/info/unicode/utf8.htm

assert len(f.read(1)) == 1 # OK
f.readline()
c = f.read(1)
print len(c)
print "'%s'" % c
assert len(c) == 1 # fails

# max% p test.py
# 63
# '
# import codecs
#
# f = codecs.open("test.py", "r", "utf-8")
#
# # ASC'
# Traceback (most recent call last):
#   File "test.py", line 15, in <module>
#     assert len(c) == 1 # fails
# AssertionError
# max%

系统:

Linux max 4.4.0-89-generic #112~14.04.1-Ubuntu SMP Tue Aug 1 22:08:32 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

当然,它可以定期open 如果我删除"utf-8"选项,它也将起作用。 还有63是什么意思? 就像第三行的中间。 我不明白

发现您的问题:

传递编码时, codecs.open返回StreamReaderWriter ,它实际上只是StreamReaderStreamWriter的包装器( 不是其子类;它是“组成”的关系,而不是继承)。 问题是:

  1. StreamReaderWriter提供了一种“常规” read方法(也就是说,它具有一个size参数,仅此而已)
  2. 它委派给内部StreamReader.read方法 ,其中size参数仅是关于要读取的字节数的提示,而不是限制。 第二个参数chars是严格的限制器,但是StreamReaderWriter永远不会传递该参数(它不接受)
  3. 如果提示了size ,但未使用chars上限,则如果StreamReader已缓冲数据,并且其大小足以匹配size提示,则StreamReader.read盲目返回缓冲区的内容,而不是根据size提示以任何方式对其进行限制(之后全部,只有chars强制使用最大返回值)

StreamReader.read的API以及该API的size / chars含义是此处唯一记录的内容; codecs.open返回StreamReaderWriter的事实不是契约性的, StreamReaderWriter封装StreamReader的事实也不是,我只是使用ipython?? 魔术读取codecs模块的源代码以验证此行为。 但是无论是否有记录,这都是它的作用(可以随意阅读StreamReaderWriter的源代码,它全部是Python级别的,所以很容易)。

最好的解决方案是切换到io.open ,这在每种标准情况下都更快,更正确( codecs.open支持在bytes [Py2 str ]和str [Py2 unicode ]之间不转换的怪异编解码器,但是,将strstr或将bytesbytes编码,但这是一个非常有限的用例;大多数时候,您是在bytesstr之间进行转换。 您需要做的只是import io而不是codecs ,并将codecs.open行更改为:

f = io.open("test.py", encoding="utf-8")

您的其余代码可以保持不变(并且可能会以更快的速度启动)。

或者,您可以显式地绕过StreamReaderWriter以获得StreamReaderread方法并直接传递限制参数,例如,change:

c = f.read(1)

至:

# Pass second, character limiting argument after size hint
c = f.reader.read(6, 1)  # 6 is sort of arbitrary; should ensure a full char read in one go

我怀疑Python的错误#8260 ,它涵盖交织readlinereadcodecs.open创建的文件对象,适用于这里,正式,它的“固定”的,但如果你读了评论,修复是不完全的(并且可能无法完成给定的文档化API); 的任意组合怪异readreadline将能打破它。

同样,只需使用io.open 只要您使用的是Python 2.6或更高版本,它就可以使用,并且会更好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM