如何检查StringIO文件使用的换行符



我有一个方法可以检测行尾

def getLineEnding(filename):
ret = "rn"
with  open(filename, 'r') as f:
f.readline()
ret = f.newlines
return ret

为了能够在不使用真实文件的情况下对其进行测试,我将其更改为:

def getLineEnding(filehandle):
filehandle.readline()
return filehandle.newlines

这适用于文件。但当我这样做时:

f = StringIO()
f.write('testrn')
f.seek(0)
f.readline()
print(f.newlines)

我得到None

我检查文件结尾的原因是我正在编写一个处理文本文件的程序,并且我希望保留原始的行结尾。

要回答您的问题,io.StringIOnewline参数的默认值与io.TextIOWrapper(由open(..., 'r')返回(的默认值不同。对于StringIO,默认值是'n',而对于TextIOWrapper,默认值为None。文档解释了行为:

newline控制如何处理行尾。它可以是None'''n''r''rn'。它的工作原理如下:

  • 从流中读取输入时,如果换行符为None,则启用通用换行符模式。输入中的行可以以'n''r''rn'结束,这些行在返回给调用者之前被转换为'n'。如果换行符为'',则启用通用换行符模式,但换行符将返回给未翻译的调用者。如果换行符具有任何其他合法值,则输入行仅由给定的字符串终止,并且行结尾未经翻译返回给调用者
  • […]

因此,这意味着默认情况下TextIOWrapper将翻译行尾,而StringIO不会。则newlines属性的文档为:

字符串、字符串元组或None,表示到目前为止翻译的换行符。[…]

因此,如果不执行转换,则不会设置此属性(StringIO就是这样(。

解决方案是通过传递newline=None来构造StringIO对象,即

f = StringIO(newline=None)

则w.r.t.行结尾的行为将类似于TextIOWrapper

然而,如果目标是保持行结尾不变,则可以直接使用newline=''返回未翻译的行结尾,如上文引用的文档所述。

最新更新