解决编码问题追踪

背景:现有的文件编码类型是“UTF-8 Unicode text”类型的,但是需要文件的类型是“ISO-8859 text, with CRLF line terminators”的

在这样的需求之下并不能直接将文件类型转换成“ISO-8859”类型,ISO-8859有ISO-8859-1,ISO-8859-2,.....,ISO-8859-9多个形式,无法直接转成ISO-8859。

       之前是通过“cat filename | iconv -f'utf8' -t'gb18030'”的命令就可以转换了,但是这次发现同样的命令却换成了“Non-ISO extended-ASCII text”类型。后来发现是因为在filename中某行文件比较不同,例如转换前627行,可以转换成功,但是转换628行的时候就失败,然后将628行去掉之后就能成功,说明该行有问题,但是不知道是什么问题。

文件末尾出现“with CRLF line terminators”说明文件是dos编码的,不是linux的编码,我们用cat -v test.sh 可以看到^M (\r的十六进制为0D,对应的控制符为^M)。 cat -v可以看到文件中的非打印字符。

可以通过打开vim设置:

:set ff=unix

:set ff=dos

来改变。

通过"file -b filename"可以查看文件的编码类型:

通过“file -b --mime-encoding synonym_dict_qtt” 可以显示更详细的信息:

 

再查了很多资料之后还是束手无策,问题就是由于文件中的某行数据不规范,在用iconv转换的过程中会使得转换失败,因此需要去除不规范的那一行。可以写一个shell脚本,脚本处理过程是逐行遍历转换成数据,转换之后用file和grep查看数据是不是正确的格式,如果不是说明此行有误,就去掉改行;若没错就继续遍历。shell代码如下所示:

function get_real_symdata(){

    file_length=`wc -l $table_name | cut -d" " -f1`

    echo "file length is "$file_length

    for ((line=1; line<$file_length; line++))
    do
        echo $line
        head -$line  $table_name | iconv -f'utf8' -t'gb18030' > ttttt
        zhuangtai=`file ttttt | grep Non`
        zt_len=${#zhuangtai}
        if [ $zt_len -gt 0 ]
        then
            echo "drop this line"
            sed -i $line'd' $table_name
            line=$[$line-1]
        else
            echo "continue"
        fi

    done
}

这样就能无误的转换了。

 

二,codecs库

import codecs
fw = codecs.open('test1.txt','a','utf-8')
fw.write(line2)

# 更快速的写法
test_docs = [x.strip().split() for x in codecs.open(test_docs, "r", "utf-8").readlines()]

 

而codecs提供的方法可以指定一个编码打开文件,使用这个方法打开的文件读取返回的将是unicode。写入时,如果参数是unicode,则使用open()时指定的编码进行编码后写入;如果是str,则先根据源代码文件声明的字符编码,解码成unicode后再进行前述 操作。相对内置的open()来说,这个方法不容易在编码上出现问题。

参考链接:https://www.cnblogs.com/Detector/p/8744992.html

参考链接:http://www.freecls.com/a/2712/78

 

你可能感兴趣的:(配置工具类,iconv,编码)