为什么Python每两行写一个错误编码的行?

时间:2014-03-14 11:54:49

标签: python sql-server encoding

我正在尝试将表格列的内容从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
਍ऀ                 愀猀 匀漀氀搀䐀攀戀椀琀漀爀Ⰰഀഀ

1 个答案:

答案 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字符串而不是字节字符串。