JAVA是是如何处理字符的。
String s = "fs123fdsa";//String变量 byte b[] = s.getBytes();//String转换为byte[] String t = new String(b);//bytep[]转换为String
做JAVA经常会碰到中文乱码问题,还有各种编码的问题,特别是String类的内容需要重新编码的问题。要解决这些问题,必须了解清楚JAVA对于字符串是怎么处理的。
1. “字符”是由数字来表示的
先来重新了解一下计算机是如何处理“字符”的,这个原理是大家必须记住的,特别是在用JAVA写程序的时候,万万不可模糊。我们知道,计算机把任何东西都用数字来表示,“字符”也不例外。比如我们要显示一个阿拉伯数字“3”,在我们的PC里,其实并不是仅仅用一个数字3来代表我们要写的“3”,而是以十六进制的0x33来代表,包括放在内存或者是写到文件里,其实都是写着0x33的,不信你可以编辑一个文本文件,写一个“3”,然后用ultraEdit看他的原始码。
2. 一切“字符”都必定用数字+编码表表示。
这时候,有一个问题:为什么一定要用0x33来代表“3”呢?而不用0x43来代表呢?或者是直接用0x03来代替?其实用什么来代表都可以,只不过大家都习惯了用ASCII编码表(是美国国家信息交换表)来确定各字符应该是用什么数字代表的。同样,为了表示中国字,我国也指定了中文的编码表,其中最广泛使用的是GB2312。比如中文的“当”字,就是用0xB5, 0xB1这两个八位的数字来表示的。所以如果显示字符的程序不知道一列数字到底是按什么编码表编码的,他也无法去判断到底这些是什么文字。如果随便用一个不对的编码表来处理这些数字,处理出来的字符很可能完全是错的。比如在英文系统上,没有GB2312编码表,送给他一个0xB5,0xB1,他就傻傻的当作ASCII来处理(操作系统通常都有自己默认的编码表),结果显示出来就是两个奇怪的符号,因为这两个字在ASCII表里就是那两个符号。同样在繁体中文系统里,他的编码表是BIG5,显示出来也是一个奇怪的中文,不是“当”字。
3. UNICODE让全世界都说一种语言
看完上面的文字,是否觉得,世界有那么多语言,每个都有自己的一套编码表,很麻烦呢?就算是中文,也有两套流行的编码表,一个是GB2312,一个是BIG5。要使用不同中文的编码的字符时,还要转来转去,的确很麻烦。不光这个,如果想要写一篇包含很多过国文字的文章,就麻烦了,必须要让处理这个文章的程序知道,哪个字是什么编码标准的。如果你想要在文章里找一个字,也必须指定你要找的是哪种编码的哪个字。否则,你要找一个0xB5,0xB1的中文“当”字,很可能把同样数字表示的日文、波兰文这些不相干的字一起给你找出来,够麻烦的吧!
所以人们想,不如大家都用同一个编码标准吧,各种文字都在编码表里有一席之地,处理文字的程序只需要都按这个编码表来处理就可以了。不过要一个编码表里包含所有的文字,这张表就大了,本来英文字+数字一共只有128个以内。但加上中文后,忽然就多了数万个,所以存放一个字符需要的大小也大了很多。现在UNICODE规定了一个字符必须由2个8位数字来表示,想想,8x8x8x8x = 65536 ,是多大的一个数字啊!所以全世界的文字才能都包含进去。当然拉,也有人说中国字可能都不止6万个拉,还要包括别的文字,但人家外国人觉得你们中国人常用的也没那么多,所以就这么定了,我们也没办法。需要注意的是GB2312和UNICODE虽然都是用两个8位数来代表一个中文字,但具体的规格可不一样,比如0xB5,0xB1在UNICODE里面可不是“当”字,而是另外一国的文字来的。
4. C是如何简洁的处理字符的
我们来谈谈C的字符串。C语言诞生在JAVA之前,C语言的基本数据类型是没有字符串这个类型的,它只有char[]。也就是C把字符顺序放入一个字节数组就完了。而且C也不管放在数组里的是什么文字,也不管那些字是按什么编码标准的。而且他的char的大小也不一定是8位数字,有时候是16位也可能,这要看具体的机器和操作系统。所以写程序的人必须要知道正在处理的char[]的内容到底是按什么编码表表示的字符串,要知道如果比较两国文字是否相同,可是没任何意义的哦!
5. JAVA是是如何处理字符的。
世界总会进步的,JAVA就是一个例子。JAVA终于有了String类了,它是解决字符问题的最好工具。在JAVA里,一个基本的要点是:String类对象是不需要指定编码表的!为什么它会自己知道一堆数字各代表什么字符呢?就是因为String里的字符信息是用UNICODE编码存放的。而JAVA为了表示字符(注意是单个字符),也有char这个数据类型,而且他的大小是固定2个8位16进制数字长度,也就是0~65535罗。为的就是对应UNICODE里面的一个字符。大家如果想取一个String里的按UNICODE数字,可以用getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 方法取得一个char[],这个char[]里就是表示String字符的,按UNICODE编码表编码的数字。
可惜现在绝大多数的系统和程序都不是按UNICODE来处理字符,而JAVA程序总是要和别的程序和系统交换数据的,所以在接收一个字符,或者是发送一个字符的时候,就必须要留意当前系统和UNICODE的关系了。比如你从网络或者文件接受到一数字:0xB5,0xB1,JAVA程序并不知道这两个字到底是中文呢?还是日文,或者英文。你如果不指明这个两个数字的编码表,JAVA就会按当前系统默认的编码表来处理。如果这两个数字是从中文WIN98发出去的,JAVA程序又是在英文LINUX上运行的,那就出现了所谓的乱码问题了。也就是JAVA按英文的编码表ASCII来处理这两个数字,当通过new String({0xB5,0xB1})得到的String的时候,这个String代表的已经不是中文的“当”字,而是两个英文的奇怪字符了。不过如果你知道这两个数字一定是中文的话,就可以指定用new String({0xB5,0xB1},"GB2312")来处理,这时候新建立的String才真的是一个“当”字。当然拉,如果你要把一个“当”字的JAVA的String显示在中文WIN98上,必须把这个字输出成两个8位数字:0xB5,0xB1,不管是写成文件还是输出到浏览器上,都必须是0xB5,0xB1。如何把“当”字用GB2312输出?String.getBytes("GB2312")就可以拉!所以有一点要记住:和外界交换任何信息都是以byte[]来进行的!。你可以留意一下JAVA大多数的I/O类,都有以byte[]作为参数和返回值的方法。不过,也有很多写的比较糊涂的程序,没有提供byte[]交换信息的方法,害的不同文字平台的程序员很头疼。Servlet的HttpRequest.getParameter()就是这样。好在有的JSP/SERVLET容易还提供先指定编码表的方法,才能比较简单的解决这个问题。
6. 网上关于JAVA中文问题的一些错误处理方法。
一个是最常见的,不管什么内容,都用new String(...,"ISO-8859-1")来建立字符串,然后使用的时候按默认的编码格式(通常在服务器上都是英文系统)输出字符串。这样其实你使用的String并不是按UNICODE来代表真正的字符,而是强行把BYTE数组复制到String的char[]里,一旦你的运行环境改变,你就被迫要修改一大堆的代码。而且也无法在同一个字符串里处理几种不同编码的文字。
另一个是把一种编码格式的字符串,比如是GB2312,转换成另一种格式的字符串,比如UTF-8,然后不指明是UTF-8编码,而直接用new String(...)来建立String,这样放在String里面的字符也是无法确定的,它在不同的系统上代表不同的字符。如果要求别人用“UTF-8格式”的String来交换信息的时候,其实已经破坏了JAVA为了兼容各种语言所做的规定。这种错误的本质思想是还按写C语言的方式,把字符串纯粹当作可以自己自由编码的存储器使用,而忽略了JAVA字符串只有一种编码格式。如果真的想自由编码,用byte[]或者char[]就完全了解决问题的了。
以上,除了是解决JAVA中文问题的基础知识外,也是多年前应该掌握的计算机基础知识。温故而知新,以期共勉。
JAVA是是如何处理字符的。的更多相关文章
- java io流(字符流) 文件打开、读取文件、关闭文件
java io流(字符流) 文件打开 读取文件 关闭文件 //打开文件 //读取文件内容 //关闭文件 import java.io.*; public class Index{ public sta ...
- java把html标签字符转普通字符(反转换成html标签)(摘抄)
下面是java把html标签字符转换,我用了spring 包中的 org.springframework.web.util.HtmlUtils 了解了源代码并且进步了使用,发现写得真不错...同时也可 ...
- 001. Java内存中的字符编码
Java内存中的字符编码 Unicode字符集及utf-8 .utf-16.utf-32 等字符编码方式 字符集:字符表示的数字集合,元素称为码点或码位: 字符编码:字符实际的储存表示: 码点:一个码 ...
- Java字符串中常用字符占用字节数
java中一个char型的数据(也就是一个字符)占两个字节.而Java中常用的字符包括数字.英文字母.英文符号.中文汉字.中文符号等,若在字符串中包含里面的多种字符,它们是否都占两个字符呢?答案是否定 ...
- Java基础-二进制以及字符编码简介
Java基础-二进制以及字符编码简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 想必计算机毕业的小伙伴或是从事IT的技术人员都知道数据存储都是以二进制的数字存储到硬盘的.从事开 ...
- AsciiPic Java视频转成字符画
AsciiPic Java视频转成字符画 github下载 https://github.com/dejavudwh/AsciiPic 运行截图 //没有做GUI 比较简陋 节省时间 main里的文件 ...
- Java IO 字节流与字符流 (三)
概述 IO流用来处理设备之间的数据传输 Java对数据的操作时通过流的方式 Java用于操作流的对象都在IO包中 流按操作的数据分为:字节流和字符流 流按流向不同分为:输入流和输出流 IO流常用基类 ...
- 缓冲字符流 java.io.BufferedWriter ,java.io.BufferedReader,缓冲字符输出流:PrintWriter
package seday07; import java.io.IOException;import java.io.PrintWriter; /*** @author xingsir * 缓冲字符流 ...
- Java IO---字节流和字符流
一.IO流简介 流 流是一个抽象概念,Java程序和外部设备(可以是硬盘上的文件,也可以是网络设备)之间的输入输出操作是基于流的. 流就好比水管中的水流,具有流入和流出,类比数据的输入和输出. Jav ...
随机推荐
- part1:11-linux在线安装工具yum
第三方的免费软件仓库安装包 1.Linux安装软件: rpm方式:rpm(Red Hat Package Manager)现在是Linux standard Base(LSB)中采用的包管理系统. 优 ...
- Find the squareroot
https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Moc ...
- 用winsw让任何Windows程序都能运行为服务
用winsw让任何Windows程序都能运行为服务 winsw介绍 有时候我们需要在Windows下开机运行某些程序,这对于有图形界面的程序来说一般不是什么事,在选项中选中开机启动,然后它们就可以自动 ...
- 2018.09.24 codeforces 1053C. Putting Boxes Together(线段树)
传送门 就是让你维护动态的区间带权中位数. 然而昨晚比赛时并没有调出来. 想找到带权中位数的中点可以二分(也可以直接在线段树上找). 也就是二分出第一个断点,使得断点左边的和恰好大于或等于断点右边的和 ...
- 2018.08.22 NOIP模拟 shop(lower_bound+前缀和预处理)
Shop 有 n 种物品,第 i 种物品的价格为 vi,每天最多购买 xi 个. 有 m 天,第 i 天你有 wi 的钱,你会不停购买能买得起的最贵的物品.你需要求出你每天会购买多少个物品. [输入格 ...
- 2018.07.09 洛谷P2365 任务安排(线性dp)
P2365 任务安排 题目描述 N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间 ...
- a标签点击后,保证后来的样式
在个人中心中,左侧的菜单(a标签),点击之后,不能够应用新的样式 而在静态界面html 中表现正常,在修改成动态的就不行了 可能是a标签链接经过了后台,当前页面的this对象发生了变化,所以就不能够像 ...
- java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: Java he
tomcat内存溢出的解决方法(java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError:) 最简单的解决办法: 在ecl ...
- 201521123014《Java程序设计》第1周学习总结
201521123014 java第一周总结 1.本周学习总结 刚认识这一门新语言,我就充满了好奇心,想看看Java和学过C语言,C++有什么区别.在这一周的学习中,我认识到,对于初学者而言,Java ...
- linux上安装maven
解压安装: tar -zxvf apache-maven-3.3.9-bin.tar.gz 配置环境变量 cd /etc/ vi profile 在最后面加上M2_HOME=/usr/local/my ...