对字符串非中文格式化,我们常用的方式是通过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相关的转换关系
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
附上中文在unicode的编码范围
http://jicheng.tw/hanzi/unicode.html?s=4E00&e=9FA5
字符集和字符编码:
http://cenalulu.github.io/linux/character-encoding/