String和locale

参考文章

Java中String使用及分析(UTF-8简单编码/解码器实现)
Locale详解
linux中文乱码问题及locale详解
国际化的locale类详解

Java中的字符串(String)

在 Java 语言中, char 定义一个字符变量,保存一个字符(可以是一个英文字母例如 ‘A’,一个汉字 ‘啊’,也可以是一个韩语文字例如 ‘남’)。String 表示一个字符串,使用 char 类型的数组保存组成该字符串的字符序列。

equals 和 ==

 public static void main(String[] args) {
        String a =  new String("你好啊");
        String b =  new String("你好啊");
        System.out.println(a == b);// false
        System.out.println(a.equals(b));// true

        String c =  new String("你好啊");
        String d = "你好啊";
        System.out.println(c == d);// false
        System.out.println(c.equals(d));// true

        String e = "你好啊";
        String f = "你好啊";
        System.out.println(e == f);// true
        System.out.println(e.equals(f));// true
    }

说明:
java运行时内存分五部分:
  线程共享:堆内存(object实例)、方法区(包括常量池)
  线程私有:栈内存、本地方法栈、程序计数器
String s = “你好啊”;
  s的引用存在栈内存中,引用指向的haha存在方法区的常量池中(先判断常量池中是否有一个haha,存在则直接指向)
String s = new String(“你好啊”);
  s的引用存在于栈内存中,引用指向的haha对象,存在堆内存中(每new一次,在堆中创建一个新的haha对象)

参考文章 : Java中String使用及分析

Unicode 字符集

Java 语言使用 Unicode 字符集,Unicode 为每一个字符都分配的一个唯一的数字,即 这个数字便代表与之对应的字符。如下:

    public static void main(String[] args) {
        System.out.println("好");
        System.out.println((char)22909);
        System.out.println("\u597d");
    }

运行结果
在这里插入图片描述
说明: 22909 等于 ‘\u597d’,都是 字符 ‘好 ’ 的 Unicode 的数字, ‘\u597d’ 为 十六进制编 ,22909 为 十进制 。

Unicode字节存储

字符 ‘A’ 的Unicode数字为 65,数值 65 使用一个字节便可存储(一个字节有8位,每一位两种状态1或者0,所以最大数11111111转化为十进制为255),但显然对于字符 ‘好’(对应数值为 22909 ) 一个字节无法存储, 那么它需要多少个字节才合适呢?

    public static void main(String[] args) {
        try {
            System.out.println("A".getBytes("UTF-8").length);
            System.out.println("好".getBytes("UTF-8").length);
            System.out.println("你好啊".getBytes("UTF-8").length);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

运行结果:
在这里插入图片描述
从结果可以看到’好’需要3个字节存储,是不是很奇怪。按理 ‘好’(22909 )应该2个字节(最大值 65535)就可以存储。那这是为什么呢?这与字符(即 数值)的编码(即 存储)方式有关。UTF-8 中 中文 需要3个字节存储。GBK 中 中文则只需要2个字节存储。如下:

    public static void main(String[] args) {
        try {
            System.out.println("A".getBytes("gbk").length);
            System.out.println("好".getBytes("gbk").length);
            System.out.println("你好啊".getBytes("gbk").length);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

运行结果:

在这里插入图片描述

编码解码-UTF-8编码

Unicode 只是一个字符集,它为每个字符分配一个唯一的数字,从而可以用数字来表达字符,而 UTF-8 是一种编码方式,描述怎样实际传输 、存储 Unicode 字符对应的数值。linux中所有的字符集都放在/usr/share/i18n/charmaps 。

我们知道 Unicode 给每个字符分配一个唯一的数值来代表该字符,例如任一一篇文章很可能会有多个字符,但是在存储或传输该文章时,并不能就直接依次存储或传输与每个字符对应的十进制数字序列,这里需要考虑 2 个问题,第一如何从数字序列中识别一个字符,即每个字符的 ‘数字表示’ 其自身应当是一个整体,必须与其它的数字即与其相邻的数字区分开,第二个问题:成本,字符 ‘A’ 使用 1 个字节即可存储,但是字符 ‘好’ 却要使用至少 2 个字节才能满足,这时,如果要求每个字符都是使用例如 2 个字节存储,那么对于英语国家的用户来说,相当于增加并浪费了 1 倍的成本。这是不能被接受!UTF-8 便是一种可变长度的 Unicode 字符编码解决方案。

UTF-8字符集就是目前流行的对字符的编码方式,UTF-8用一个字节表示常用的拉丁字母,用两个字节表示常用的符号,包括常用的中文字符,用三个表示不常用的字符,用四个字节表示其他的古灵精怪的字符。而GB2312字符集就是用两个字节表示所有的字符。

UTF-8 编码

UTF-8 使用 1 - 4 个字节来编码 Unicode 字符对应的数字编号,规则如下图:
在这里插入图片描述
“好 ”字符的 Unicode 编号为 22909,而 22909 位于 2048 和 65535 之间,所以它使用 3 个字节进行编码并存储。在进行编码时,只需将 26976 的二进制码从低位到高位依次填入‘可用编码位’ 即可得到字符 ‘好’ 对应的 UTF-8 编码,如下图:
在这里插入图片描述

UTF-8的解码

解码是编码的反向操作,编码是将数值位依次插入到对应的可编码位,解码时则从可编码位提取对应的数值位并将它们拼接在一起,从而还原出原来的数值

每一套编码都有自己的一套编辑解码规则。 所以编码用用UTF-8,解码就用UTF-8,否则会出现乱码。
如 “好”用UTF-8编码后是3个字节的二进制: 11100101 10100101 10111101,如果解码时用GBK,这只会取2个字节 10100101 10111101,再把转成Unicode 数字时,必定不是26976 。翻译成字符时可就是乱码了。

扩展

		//获取utf-8的字节数组
		byte[] b_utf8 = "中".getBytes("UTF-8"); 
		String s_iso88591 = new String(b_utf8,"ISO8859-1"); 
		System.out.println(s_iso88591);//中

		//还原
		byte[] bytes = s_iso88591.getBytes("ISO8859-1");
		s_iso88591 = new String(b_utf8,"UTF-8"); 
		System.out.println(s_iso88591);//中

locale

什么是locale?

Locale是根据计算机用户所使用的语言,所在国家或者地区,以及当地的文化传统所定义的一个软件运行时的语言环境。locale定义文件放在/usr/share/i18n/locales目录下面,例如en_US, zh_CN and de_DE@euro都是locale的定义文件。

一个locale的书写格式为: [语言[_地域][.字符集] [@修正值]。 它包括语言(Language), 地域 (Territory) 和字符集(Codeset),总是和一定的字符集相联系。如:
zh_CN.GB2312=中文_中华人民共和国+国标2312字符集。
zh_CN.GB18030=中文_中华人民共和国+国标18030字符集。
zh_TW.BIG5=中文_台湾.大五码字符集
en_GB.ISO-8859-1=英文_大不列颠.ISO-8859-1字符集。
de_DE.UTF-8@euro=德语_德国.UTF-8字符集@按照欧洲习惯加以修正 。

系统默认语言及中文乱码问题

记录系统默认使用语言的文件是/etc/sysconfig/i18n,如果默认安装的是中文的系统,i18n的内容如下:
LANG=“zh_CN.UTF-8” SYSFONT=“latarcyrheb-sun16” SUPPORTED=“zh_CN.UTF-8:zh_CN:zh” LINUXTYPE=targeted

LANG变量是language的简称,决定系统的默认语言的,即系统的菜单、程序的工具栏语言、输入法默认语言等。
SYSFONT是system font的简称,决定系统默认用哪一种字体。
SUPPORTED变量决 定系统支持的语言,即系统能够显示的语言。需要说明的是,由于计算机起源于英语国家,因此,不管你把这些变量设置成什么,英语总是默认支持的,而且不管用什么字体,英文字体总包含在其中。

临时调整终端乱码现象:# LANG=“zh_CN.UTF-8” 即把系统的语言临时设置成中文,

永久解决终端乱码现象:修改 i18n文件中的LANG变量,设置成中文的”zh_CN.UTF-8”
命令:vi etc/sysconfig/i18n
修改后的文件如下:
#LANG=“zh_CN.UTF-8” SYSFONT=“latarcyrheb-sun16” SUPPORTED=“zh_CN.UTF-8:zh_CN:zh”

请不要把LANG变量简单的清空,因为这个变量不仅在字符模式下用到,在图形界面下也用到,简单清空在字符模式下确实不会有问题,但在图形界面下,却会造成中文无法正常显示的情况,在过去Redhat系列的版本中i18n文件中还有一个叫LANGUAGE的变量,专门控制图形界面下的语言设置,现在的FC系列中已经把这两个变量整合成一个变量了。

linux 中 locale常用操作

1、查看现有语言环境:
locale
2、可用语言环境:
locale -a
3、临时修改语言环境:
AIX:
export LANG=en_US
export LANG=zh_CN

Linux:
export LANG=en_US.UTF-8
export LANG=zh_CN.UTF-8
4、永久修改系统级字符集:
修改/etc/sysconfig/i18n
英文版系统:
LANG=“en_US.UTF-8”
SYSFONT=“latarcyrheb-sun16”

中文版系统:
LANG="zh_CN.UTF-8"或者LANG=“zh_CN.gbk”
SYSFONT=“latarcyrheb-sun16”

locale的五脏六腑

locale把按照所涉及到的文化传统的各个方面分成12个大类,这12个大类分别是:

1、语言符号及其分类(LC_CTYPE)

2、数字(LC_NUMERIC)

3、比较和排序习惯(LC_COLLATE)

4、时间显示格式(LC_TIME)

5、货币单位(LC_MONETARY)

6、信息主要是提示信息,错误信息, 状态信息, 标题, 标签, 按钮和菜单等(LC_MESSAGES)

7、姓名书写方式(LC_NAME)

8、地址书写方式(LC_ADDRESS)

9、电话号码书写方式(LC_TELEPHONE)

10、度量衡表达方式(LC_MEASUREMENT)

11、默认纸张尺寸大小(LC_PAPER)

12、对locale自身包含信息的概述(LC_IDENTIFICATION)。

其中,与中文输入关系最密切的就是 LC_CTYPE, LC_CTYPE 规定了系统内有效的字符以及这些字符的分类,诸如什么是大写字母,小写字母,大小写转换,标点符号、可打印字符和其他的字符属性等方面。而locale定义zh_CN中最最重要的一项就是定义了汉字(Class “hanzi”)这一个大类,当然也是用Unicode描述的,这就让中文字符在Linux系统中成为合法的有效字符,而且不论它们是用什么字符集编码的。

另外非常重要的一点就是这些分类是彼此独立的,也就是说LC_CTYPE,LC_COLLATE和 LC_MESSAGES等等分类彼此之间是独立的,可以根据用户的需要设定成不同的值。这一点对很多用户是有利的,甚至是必须的。例如,我就需要一个能够输入中文的英文环境,所以我可以把LC_CTYPE设定成zh_CN.GB18030,而其他所有的项都是en_US.UTF-8。

怎样设定locale呢

设定locale就是设定12大类的locale分类属性,即 12个LC_。除了这12个变量可以设定以外,为了简便起见,还有两个变量:LC_ALL和LANG。它们之间有一个优先级的关系: LC_ALL>LC_>LANG 可以这么说,LC_ALL是最上级设定或者强制设定,而LANG是默认设定值。

1、如果你设定了LC_ALL=zh_CN.UTF-8,那么不管LC_*和LANG设定成什么值,它们都会被强制服从LC_ALL的设定,成为 zh_CN.UTF-8。

2、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_=en_US.UTF-8,并且没有设定LC_ALL的话,那么系统的locale设定以LC_=en_US.UTF-8。

3、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_*,和LC_ALL均未设定的话,系统会将LC_*设定成默认值,也就是LANG的值 zh_CN.UTF-8 。

4、假如你设定了LANG=zh_CN.UTF-8,而其他的LC_CTYPE=en_US.UTF-8,其他的LC_*,和LC_ALL均未设定的话,那么系统的locale设定将是:LC_CTYPE=en_US.UTF-8,其余的 LC_COLLATE,LC_MESSAGES等等均会采用默认值,也就是LANG的值,也就是LC_COLLATE=LC_MESSAGES=……= LC_PAPER=LANG=zh_CN.UTF-8。

Java中Date与 Locale

Java中Locale对象的3种常用创建方式

获取默认的Locale

Locale locale = Locale.getDefault()

直接使用Locale的静态对象Locale.java中提供了以下静态对象

Locale locale = Locale.SIMPLIFIED_CHINESE ; # 中国(大陆)

通过Locale的构造函数创建Locale对象

Locale(String language)

Locale(String language, String country)

Locale(String language, String country, String variant)

Locale和Date

在操作 Date, Calendar等表示日期/时间的对象时,经常会用到;因为不同的区域,时间表示方式都不同。


import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

public class TempTest {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);
        // 创建“简体中文”的Locale
        Locale localeCN = Locale.SIMPLIFIED_CHINESE;
        // 创建“英文/美国”的Locale
        Locale localeUS = new Locale("en", "US");
        // 获取“简体中文”对应的date字符串
        String cn = DateFormat.getDateInstance(DateFormat.MEDIUM, localeCN).format(date);
        // 获取“英文/美国”对应的date字符串
        String us = DateFormat.getDateInstance(DateFormat.MEDIUM, localeUS).format(date);
        System.out.printf("cn=%s\nus=%s\n", cn, us);
    }
}

执行结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值