众所周知,地球上的语言多种多样,在计算机世界,自然也是要适应各种语言.我们安装各种系统的时候也是明示了要选择语言环境和支持的语言环境.
而linux系统的字符编码设置尤为复杂,这可能也是没有考虑到非技术人员去研究这些东西吧.
我遇到的事情是这样的,我们使用了docker,但是docker容器里的语言环境经常莫名错乱,搞得很头痛,所以偶尔就要切换,或者生成其他字符集.所以现在假设我们需要切换一个中文语言环境,而切换了之后是乱码的,也就是没用的.
基本上,乱码的原因就是没加载到合适的字符编码环境,即使是显示到下面这样的,其实也未必是加载到,只是证明这些变量更改成功而已.
#查看环境变量 vim /etc/profile export LANG=zh_CN.UTF-8 export LANGUAGE=zh_CN.UTF-8 export LC_TIME=zh_CN.UTF-8 #加载一下 source /etc/profile #看一下加载成功没 locale LANG=zh_CN.UTF-8 LC_CTYPE="zh_CN.UTF-8" LC_NUMERIC="zh_CN.UTF-8" LC_TIME=zh_CN.UTF-8 LC_COLLATE="zh_CN.UTF-8" LC_MONETARY="zh_CN.UTF-8" LC_MESSAGES="zh_CN.UTF-8" LC_PAPER="zh_CN.UTF-8" LC_NAME="zh_CN.UTF-8" LC_ADDRESS="zh_CN.UTF-8" LC_TELEPHONE="zh_CN.UTF-8" LC_MEASUREMENT="zh_CN.UTF-8" LC_IDENTIFICATION="zh_CN.UTF-8" LC_ALL=
还要看看locale -a有没有加载到系统上,
locale -a locale: Cannot set LC_CTYPE to default locale: No such file or directory locale: Cannot set LC_MESSAGES to default locale: No such file or directory locale: Cannot set LC_COLLATE to default locale: No such file or directory C POSIX en_US.utf8
大家看到了,系统上根本就没有zh_CN.UTF-8的字符编码,所以即使改了,也是没有任何意义,所以你看到的还是会出现乱码.
要解决这个问题,就要我们对linux字符编码有比较透彻的理解.
首先,我们要看看我们的系统有哪些可支持的语言,都存在大名鼎鼎的i18n里面,
#系统支持的语言环境 ll /usr/share/i18n/locales/ aa_DJ ar_LY ber_DZ ca_FR de_LU@euro en_IN es_EC eu_ES fur_IT hi_IN it_CH kw_GB ml_IN nl_BE POSIX sid_ET sv_FI@euro translit_circle tt_RU@iqtelif yi_US aa_ER ar_MA ber_MA ca_IT doi_IN en_NG es_ES eu_ES@euro fy_DE hne_IN it_IT ky_KG mni_IN nl_BE@euro ps_AF si_LK sv_SE translit_cjk_compat ug_CN yo_NG aa_ER@saaho ar_OM bg_BG crh_UA dv_MV en_NZ es_ES@euro fa_IR fy_NL hr_HR it_IT@euro lb_LU mn_MN nl_NL pt_BR sk_SK sw_KE translit_cjk_variants uk_UA yue_HK aa_ET ar_QA bho_IN csb_PL dz_BT en_PH es_GT ff_SN ga_IE hsb_DE iu_CA lg_UG mr_IN nl_NL@euro pt_PT sl_SI sw_TZ translit_combining unm_US zh_CN af_ZA ar_SA bn_BD cs_CZ el_CY en_SG es_HN fi_FI ga_IE@euro ht_HT iw_IL li_BE ms_MY nn_NO pt_PT@euro so_DJ szl_PL translit_compat ur_IN zh_HK am_ET ar_SD bn_IN cv_RU el_GR en_US es_MX fi_FI@euro gd_GB hu_HU ja_JP lij_IT mt_MT nr_ZA ro_RO so_ET ta_IN translit_font ur_PK zh_SG an_ES ar_SY bo_CN cy_GB el_GR@euro en_ZA es_NI fil_PH gez_ER hy_AM ka_GE li_NL my_MM nso_ZA ru_RU so_KE ta_LK translit_fraction uz_UZ zh_TW ar_AE ar_TN bo_IN da_DK en_AG en_ZM es_PA fo_FO gez_ER@abegede i18n kk_KZ lo_LA nan_TW@latin oc_FR ru_UA so_SO te_IN translit_hangul uz_UZ@cyrillic zu_ZA ar_BH ar_YE br_FR de_AT en_AU en_ZW es_PE fr_BE gez_ET ia_FR kl_GL lt_LT nb_NO om_ET rw_RW sq_AL tg_TJ translit_narrow ve_ZA ar_DZ as_IN br_FR@euro de_AT@euro en_BW es_AR es_PR fr_BE@euro gez_ET@abegede id_ID km_KH lv_LV nds_DE om_KE sa_IN sq_MK th_TH translit_neutral vi_VN ar_EG ast_ES brx_IN de_BE en_CA es_BO es_PY fr_CA gl_ES ig_NG kn_IN mag_IN nds_NL or_IN sat_IN sr_ME ti_ER translit_small wa_BE ar_IN ayc_PE bs_BA de_BE@euro en_DK es_CL es_SV fr_CH gl_ES@euro ik_CA kok_IN mai_IN ne_NP os_RU sc_IT sr_RS ti_ET translit_wide wa_BE@euro ar_IQ az_AZ byn_ER de_CH en_GB es_CO es_US fr_FR gu_IN is_IS ko_KR mg_MG nhn_MX pa_IN sd_IN sr_RS@latin tig_ER tr_CY wae_CH ar_JO be_BY ca_AD de_DE en_HK es_CR es_UY fr_FR@euro gv_GB iso14651_t1 ks_IN mhr_RU niu_NU pap_AN sd_IN@devanagari ss_ZA tk_TM tr_TR wal_ET ar_KW be_BY@latin ca_ES de_DE@euro en_IE es_CU es_VE fr_LU ha_NG iso14651_t1_common ks_IN@devanagari mi_NZ niu_NZ pa_PK se_NO st_ZA tl_PH ts_ZA wo_SN ar_LB bem_ZM ca_ES@euro de_LU en_IE@euro es_DO et_EE fr_LU@euro he_IL iso14651_t1_pinyin ku_TR mk_MK nl_AW pl_PL shs_CA sv_FI tn_ZA tt_RU xh_ZA #语言确实博大精深,不过我们直奔主题,我们需要的只是中文,只要看到这个就足够了 zh_CN
假如没有怎么办,也确实是有可能的,那我们就需要安装了
#ubuntu安装 apt-get -y install language-pack-zh-hans language-pack-zh-hans-base #centos安装 yum install kde-l10n-Chinese yum reinstall glibc-common
如果是一般的物理机,或者kvm/vmware的虚拟机,到了这一步,然后再source一遍,一般也能解决的了,然鹅,我的docker还是不行,真是ri了狗.
不过,就算他没有,我们也可以自己造一个啊,听起来很玄乎,但是真的可以,利用localedef命令来做
---------------------------------------------------
先看看这个命令的介绍:
转化语言环境和字符集描述(charmap)源文件以生成语言环境数据库。
语法localedef [ -c ] [ -f Charmap ] [ -i SourceFile ] [ -L LinkOptions ] [ -m MethodFile ] LocaleName
参数
-c 就算发出了警告消息,仍然强制语言环境表的创建。
-f CharMap 指定包含了字符符号映射以及将元素符号整理为实际字符编码的文件名称。一个语言环境与且仅与一个代码集关联。如果没有指定该标志,那么采用 ISO 8859-1 代码集。注:完全支持系统提供的某些 CharMap 文件。然而,当用户提供的正确定义的 CharMap 文件可能正常工作时,仍不能保证这样使用的结果。
-i SourceFile 指定包含语言环境类别源定义的文件的路径名。如果没有给出此标志,那么源定义从标准输入上读取。
-L LinkOptions 将指定的链接选项发送给构建语言环境的 ld 命令。
-m MethodFile 指定描述构造语言环境时覆盖的方法的方法文件的名称。方法文件指定用户提供的覆盖现有定义的子例程以及包含指定的子例程的库的路径名。当构造语言环境对象的时候,localedef 命令读取方法文件并使用入口点。指定的代码集方法也可用来分析由 CharMap 变量指向的文件。注:要创建 64 位语言环境,方法文件必须将库的路径指定为具有包含指定的子例程的两个共享对象(一个 32 位,另一个 64 位)的单一压缩文档。对 32 位和 64 位共享对象指定不同的路径导致 localedef 命令由于不兼容 XCOFF 格式而失败。
LocaleName 指定要创建的语言环境名称。它是后来可以用于访问此语言环境信息的名称。
----------------------------------------------------------
看完介绍,也确定有这个语言支持,那就来造一个吧
#造一个中文的utf-8字符编码, #意思就是指定zh_CN的语言环境,然后指定UTF-8编码,命名为zh_CN.UTF-8 localedef -i zh_CN -f UTF-8 zh_CN.UTF-8 #在看看系统有没有这个字符编码没有, locale -a C POSIX zh_CN.utf8 #可以看到存在了,在加载一下 source /etc/profile
然后,一切都回归正常,不再乱码了.
原文地址:http://arthur376.blog.51cto.com/2918801/1915170