by Devin Yang

建立于: 6年前 ( 更新: 6年前 )

不同中文编码时的乱码问题

这里举例,例如同时有三个不同编码的php档,会显示成怎样。
我们直接透过 git log -p 来看一下结果,会发觉到有看不懂的乱码,如下图。
git diff乱码
在上方的个例字中,看不出到底修改了什么,因为编码不是utf-8。
但是透过Git属性的diff设置后,情况就不同了,画面如下,正常的显示出三种不同编码的文本档:

其时,这是透过git属性达成的。

关於Git属性

使用属性,你可以对个别文件或目录定义不同的合并策略,也可以让 Git 知道怎样比较非文本档
例如比较两个word文档变更,因为这样的特性,
我们也可以让不同编码的文档,统一使用一种编码显示於终端机上。

在本文中,我将示范透过git属性的功能,将不同编码的文件使用UTF-8编码,显示於终端机上。
Git属性可以透过新建 .gitattributes 档进行设置,通常放在项目的目录上,
如果不想设置的Git属性被一起提交,也可以设置在自己 .git/info/attributes 上。

一、先创建.git/info/attributes内容如下:
*.php diff=big5
*.html diff=big5
*.htm diff=big5

上例的语法,非常明显示,我针对了*.php、*.html及*.htm三种文件,在进行diff时,使用big5这个转码器。
也就是说.php或是.html档,都会透过big5这个转换器,将编码采转换后,采用UTF-8的方式显示并比较。

二、手动编辑在.git/config文件中,添加如下设置:
[diff "big5"]
textconv = hkscs2utf8

或者我们也可以命令的方式新建设置
git config diff.big5.textconv hkscs2utf8

上方的hkscs2utf8是我写的简易版转码bash,用於将gb2312及big5转换成utf8显示。
也就是说,当git进行diff时,都会采用我们在git属性中定义的副档为.php及.html或.html等文件,
经由hkscs2utf8这只自己写的bash档进转码,并比较结果。

三、将下方的bash,放入/usr/local/bin/hkscs2utf8。
可echo $PATH,确认这个路径/usr/local/bin是有设置的。
注: 这个bash只适合用於MacOS的系统上。当然这并代表Windows或Linux无法达到这个效果,
本文主要传达的是Git属性的概念及用例,您可采用不同的方式进行转码,例如Python,或在不同的平台上,
使用自己写出的更严谨的转码进程。
#!/bin/bash
file -I "$1" |grep utf-8 >/dev/null 2>&1
#判断文件为utf-8吗?
#ansi档会有不同的编码,或在Widnows上称为CodePage不好判定文件是Big5或Gb2312编码,
#DBCS中,因为不同字集两边的编码可能是一样的。
#所以我先判定文件是否为UTF-8
#这样回传的错误码为0代表,没有错误,那么直接将UTF-8编码的文档cat出来。
if [ $? -eq 0 ]; then
    cat ${1}
    exit 0;
fi
#上方的UTF-8判定失败了,开始尝试其他的编码。
#先尝试以gb2312简体转utf-8,将大於0的错误信息隐藏,
#失败了代表该档非GB2312,因此我们使用big5-hkscs进行转码。
#如果尝试转码成功,回传为0,我们就重新运行GB2312转码,变更为UTF-8输出。
iconv -f gb2312 -t utf-8 "$1" >/dev/null 2>&1
if [ $? -eq 1 ]; then
    iconv -f big5-hkscs//IGNORE -t utf-8 "$1"
    else
    iconv -f gb2312 -t utf-8 "$1"
fi
记得哦,要chmod 700 hkscs2utf8,否则该bash是不能被运行的。
以上就完成设置了,如果打了git log -p
就可以看到正常中文本罗,magic.

四、另外,我也用Python写了另一只转码进程,效果应该比bash版的来较没问题哦
如果您电脑可以跑python可以试看看。

1.创建cv.py到/usr/local/bin目录下
2.设置使用cv.py,运行命令: git config diff.big5.textconv cv.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
#检测是否为UTF-8编码
def isUTF8(data):
    try:
        decoded = data.decode('UTF-8')
    except UnicodeDecodeError:
        return False
    else:
        for ch in decoded:
            if 0xD800 <= ord(ch) <= 0xDFFF:
                return False
        return True

#取得binary的文件内容
def get_bytes_from_file(filename):
    return open(filename, "rb").read()

#取得档名
filename = sys.argv[1]
data = get_bytes_from_file(filename)

#检测文件是否为UTF8
result = isUTF8(data)

#非UTF-8进行转码
if(result == False):
    #udata = data.decode("hkscs")
    try:
        udata = data.decode("gb2312")
    except:
        udata = data.decode("hkscs")
    data = udata.encode("utf-8","ignore")
    print(data)
else:
    print(data)
在utf-8的环境下,显示的注解是乱码,用下方命令就能正常了
git config --global i18n.logOutputEncoding utf8

 

Tags: git

Devin Yang

文章内容无法一一说明,如果您有什么不了解处,欢印提问哦:)

No Comment

Post your comment

需要登入才可留言!

类似文章


git

用git logt命令快速列出自己或别人的commit

这里有两个命令,可以快速列出自己或别人所有的commit

git

强制清空远程repo所有数据

强制清空远程repo所有数据

git

git别名之昨日报表

我们可以透过 git config --global alias.[别名] "将常常要运行的长长git子命令"缩减成简化的别名。 所以您也可以透过git别名设置,将自己常用的git命令添加到全局的git别名中。 让我们来看看我的实际范例,如何将长长的子命令简化成简单易用的别名。