Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中,在开始读取之前,如何判断文件是否具有utf-8签名_Python_Python 2.7_Utf 8 - Fatal编程技术网

在Python中,在开始读取之前,如何判断文件是否具有utf-8签名

在Python中,在开始读取之前,如何判断文件是否具有utf-8签名,python,python-2.7,utf-8,Python,Python 2.7,Utf 8,我正在编写一个过滤器,它读取一个文件(可能是stdin),也可能写入stdout。如果输入文件以字节顺序标记开头,我希望输出文件有一个字节顺序标记,否则就没有。如果我打开一个BOM为utf-8的文件,那么程序读取的第一个字符就是BOM(\uFEFF),这是我不想要的。如果我以utf-8-sig的形式打开一个没有BOM表的文件,它会正确地读取该文件,但我无法判断是以utf-8(没有签名)还是以utf-8-sig的形式打开输出,这将以签名标记开始文件。所以我想做的是查看文件的第一个字符,并根据其值决

我正在编写一个过滤器,它读取一个文件(可能是
stdin
),也可能写入
stdout
。如果输入文件以字节顺序标记开头,我希望输出文件有一个字节顺序标记,否则就没有。如果我打开一个BOM为
utf-8
的文件,那么程序读取的第一个字符就是BOM(
\uFEFF
),这是我不想要的。如果我以
utf-8-sig
的形式打开一个没有BOM表的文件,它会正确地读取该文件,但我无法判断是以
utf-8
(没有签名)还是以
utf-8-sig
的形式打开输出,这将以签名标记开始文件。所以我想做的是查看文件的第一个字符,并根据其值决定使用哪种编码来打开文件。如果它是一个磁盘文件,我可以简单地关闭它并重新打开它,但因为它可能是stdin,我不能这样做。我可以通过让我的程序检查它读取的第一个字符来解决这个问题,如果它是一个签名标记,我就输出它,但是我想知道是否有更好的方法。我注意到,如果我按如下方式打开文件

f = io.open(inFile, encoding="utf-8", buffering=1)
然后执行
f.buffer.peek(1)
我得到一个包含文件第一个字符的Unicode对象。这似乎有点奇怪,因为我从缓冲
iobase
类的
peek(
)中所期望的是长度为1的Unicode对象。现在,我可以查看peek返回的第一个字符,如果它是一个签名标记,则读取一个字符并将其写入输出,或者丢弃它,然后使用
utf-8-sig
打开输出文件,但我真的不喜欢基于这么多观察到的、而不是记录的行为来创建解决方案

有什么办法可以做到这一点吗

[我通过让解析逻辑忽略BOM解决了这个问题。]

我还发现,当我打开输出时

fOut = io.open(sys.stdout.fileno(), mode="at", encoding="utf-8", closefd=False)
我在每一行(
)的末尾都会得到一个额外的
,如果我打开一个实际的文件,就不会得到这个额外的

我尝试用mode=“ab”打开,但没有成功。似乎有效的方法是添加换行符=“\n”:

我认为这种“有效”的原因是同样的反常现象。按照编码,应使用LF作为终止符。事实上,如果您使用UNIX行终止符为其输入,它仍然会输出DOS行终止符

我正在Windows10上运行Python 2.7.13

谢谢


Gary

您是否尝试过
fOut=io.open(sys.stdout.fileno(),mode=“ab”,closefd=False)
\uFEFF
是一个字节顺序标记。非utf8文件可以以这两个字节开头,utf8文件不需要以字节顺序标记开头。您可以在打开的文件周围编写一个包装器,检查第一个字符并将其保存到属性,但不返回。如果您只需要迭代行,那么这个包装器可以是一个简单的迭代器,专门处理第一行。如果您需要
.seek()
,它可以从
io.TextIOWrapper
继承。您真的需要猜测文件的编码吗?您是否同意所有人正在使用的发件人的意见,或者每次都让用户告诉您您的程序是否允许他们为文件提供自己选择的编码?
fOut = io.open(sys.stdout.fileno(), mode="at", encoding="utf-8", newline="\n", closefd=False)