我正在尝试将表格列的内容从SQL Server 2K转储到文本文件中,我希望稍后用Python处理并输出新的文本文件。
我的问题是我无法让python使用正确的编码,虽然输入文件在我的文本编辑器中显示正常,但输出文件显然每两行都会破坏一次。< / p>
我的python代码可以简化为:
input = open('input', 'r')
string = input.read()
# Do stuff
output = open('output', 'w+')
output.write(string)
在Windows shell中打印此字符串会为我提供所需的字符,尽管它们彼此相隔一个空格太多。
但是当我打开输出文件时,每两行一次都被打破(虽然“添加”的空格已经消失)
某些上下文:要将列转储到文件,我正在使用此脚本:spWriteStringTofile
我相信它使用的是默认服务器编码。
经过一些研究,看来这个编码是SQL_Latin1_General_CP1_CI_AS
。我尝试在脚本开头添加# -*- coding: latin_1 -*
,我尝试将SQL Server内部的编码转换为Latin1_General_CI_AS
,我尝试string.decode('latin_1').encode('utf8')
但它没有改变任何东西(除了最后一个)尝试输出只有破碎的字符。)
我可以尝试什么?
编辑2:我尝试了newFile.write(line.decode('utf-16-be').encode('utf-16-le'))
解决方案,并在文件的第一行抛出错误。来自python GUI:
(Pdb) print line
ÿþ
(Pdb) print repr(line)
'\xff\xfe\n'
(Pdb) line.decode('utf-16-be').encode('utf-16-le')
*** UnicodeDecodeError: 'utf16' codec can't decode byte 0x0a in position 2: truncated data
第一行只有Sublime Text 2中出现换行符......
当我绕过它(try: ... except: pass
,快速和肮脏)时,在正确和不正确的行之间添加换行符,但是破碎的字符仍在此处。
编辑:我逐行浏览了文档
newFile = open('newfile', 'a+')
with open('input') as fp:
for line in fp:
import pdb
pdb.set_trace()
newFile.write(line)
在pdb中,在错误的行上:
(Pdb) print line
a s S o l d D e b i t o r , # <-- Not actual copy paste
(Pdb) print repr(line)
'\x00\t\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00a\x00s\x00 \x00S\x00o\x00l\x00d\x00D\x00e\x00b\x00i\x00t\x00o\x00r\x00,\x00\r\x00\n'
然而由于某些原因我无法复制/粘贴print line
值:我可以复制单个字母字符,但不能在我选择“空白”时将其复制。 ..
输入:
r <= @Data2 then (case when @Deviza='' or @Deviza=@sMoneda
then isnull(Debit,0) else isnull(DevDebit,0) end)
else 0 end)
- Sum(case when DataInr >= @BeginDate and DataInr <= @Data2
then (case when @Deviza='' or @Deviza=@sMoneda
then isnull(Credit,0) else isnull(DevCredit,0) end)
else 0 end)
else 0 end
as SoldDebitor,
输出:
r <= @Data2 then (case when @Deviza='' or @Deviza=@sMoneda
then isnull(Debit,0) else isnull(DevDebit,0) end)
ऀ 攀氀猀攀 攀渀搀⤀ ഀഀ
- Sum(case when DataInr >= @BeginDate and DataInr <= @Data2
then (case when @Deviza='' or @Deviza=@sMoneda
then isnull(Credit,0) else isnull(DevCredit,0) end)
ऀ 攀氀猀攀 攀渀搀⤀ ഀഀ
else 0 end
ऀ 愀猀 匀漀氀搀䐀攀戀椀琀漀爀Ⰰഀഀ
答案 0 :(得分:1)
您的损坏数据是UTF-16,使用大端字节顺序:
>>> line = '\x00\t\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00a\x00s\x00 \x00S\x00o\x00l\x00d\x00D\x00e\x00b\x00i\x00t\x00o\x00r\x00,\x00\r\x00\n'
>>> line.decode('utf-16-be')
u'\t as SoldDebitor,\r\n'
但无论再次阅读你的文件是以 little endian 字节顺序解释数据UTF-16:
>>> print data.decode('utf-16-le')
ऀ 愀猀 匀漀氀搀䐀攀戀椀琀漀爀Ⰰഀ
这很可能是因为您没有在文件开头包含BOM,或者您损坏了输入数据。
你真的不应该在没有解码的情况下以文本模式读取UTF-16数据,因为以两个字节编码的换行符几乎保证被破坏,导致逐个字节顺序错误,这也可能导致每隔一行或几乎所有其他行被破坏。
使用io.open()
来读取 unicode 数据:
import io
with io.open('input', 'r', encoding='utf16') as infh:
string = infh.read()
# Do stuff
with io.open('output', 'w+', encoding='utf16') as outfh:
outfh.write(string)
因为您的输入文件已经出现了UTF-16 BOM。
这意味着需要调整其余代码来处理Unicode字符串而不是字节字符串。