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

強制清空遠端repo所有資料

強制清空遠端repo所有資料

git

我如何刪除,我GitHub上的遠端分支

我如何刪除,我GitHub上的遠端分支。 首先,可先用指令查看origin git remote -v 這時可能顯示如下: origin https://github.com/DevinY/dlaravel.git (fetch) ​​​​​​​origin https://github.com/DevinY/dlaravel.git (push)

docker,git

用docker-compose快速建立私有的git服務

如何快速建立一個開箱即用的Gogs環境呢? 本文介紹採用docker-compose.yml快速建立gogs環境。