1. 程式人生 > >python 中英混合字串格式對齊所引發的思考

python 中英混合字串格式對齊所引發的思考

對字串非中文格式化,我們常用的方式是通過print 方式下的右對齊 n%s(左對齊-n%s)或者ljust\rjust;

但上面存在一個缺點就是對於含有中文字串的處理是不相容,導致打印出來格式還是沒有進行對齊的;

補充下rjust的處理規則:

1. 通過len獲取字串的長度,len的實現方式是對不同的字元進行解碼為unicode,再計算unicode所佔的位元組長度;

2. " "* (width - len) + argu,即補齊相減後的長度的空格,連線原有字串後返回

主要原因是:在終端展示的時候並不是中文並沒有按照三個字元寬的長度去展示,按照等寬字元,每個中文字元佔的就是兩個英文字母(終端或者檔案上面為什麼佔用的兩個字母寬度?)


得到的結果如下:


字串"中文"在rjust進行對齊處理的因為是utf編碼,每個字元的長度(1-6個位元組),導致在取字串長度的時候取的長度是3個位元組;

所以python提供API不滿足中文的對齊方式,需要自行編寫對齊函式進行處理;

在編寫之前引入幾篇文章關於編碼的意義;

既然unicode已經可以表達,為什麼不統一使用unicode來處理,還需要在出現編碼為utf-8和gbk的方式 ?

unicode所使用的二進位制的方式去表達一個字元編碼,卻沒有規定所使用的儲存和傳輸方式,即規定字型檔的一種實現形式;

而後來utf-8則規定了該字符集的一種物理儲存方式和Unicode序號的轉換關係,規範了字符集的儲存方式,規範了儲存空間;


實現程式碼如下:

def is_chinese(uchar):

    """判斷一個unicode是否是漢字"""

    if uchar >= u'\u4e00' and uchar <= u'\u9fa5':

        return True

    else:

        return False

def align( text, width, just = "left" ):  

    stext = str(text)

    utext = stext.decode("utf-8")  #對字串進行轉碼

    cn_count = 0

    for u in utext:

        if is_chinese(u):

            cn_count += 2 # 計算中文字元佔用的寬度

        else:

            cn_count += 1  # 計算英文字元佔用的寬度

    if just == "right":

        return " " * (width - cn_count ) + stext  

    elif just == "left":

        return stext + " " * ( width - cn_count )

def string_ljust( text, width ):

    return align( text, width, "left" )

def string_rjust( text, width ):

    return align( text, width, "right" )

print "str %s|" % string_rjust( "中文", 10 ).decode( "utf-8" ).encode( "gb18030" )

print "str %s|" % string_rjust( "ab", 10 ).decode( "utf-8" ).encode( "gb18030" )

print "str %s|" % string_rjust( "a中文", 10 ).decode( "utf-8" ).encode( "gb18030" )

得到效果如下:


編碼魔爪在程式猿的世界無處不在,只要其中一個編碼過程不統一都會產生亂碼的情況;

經常出現同事糾結在於從db裡面獲取資料的時候出現亂碼問題,或者導資料導到db裡面的時候出現亂碼問題;

1. mysql的db建立需要設定編碼,進行資料獲取需要設定編碼;

2. 不同的客戶端郵件傳送再到開啟檔案需要統一字元編碼;

3. 前端頁面展示需要字元編碼;

遇到問題時可以多猜測和驗證會有編碼的地方,然後通過原始碼去分析清楚問題的存在;

這篇文章主要解決了當前的問題,再發散性地去延伸到字元編碼的問題;

附錄:

utf-8和unicode相關的轉換關係

附上中文在unicode的編碼範圍

字符集和字元編碼: