Java中文编码小结
Java中文编码小结
1. 只有 字符到字节 或者 字节到字符 的转换才存在编码转码;
2. Java String 采用 UTF-16 编码方式存储所有字符。unicode体系采用唯一的码点表示唯一的字符信息, 码点的存储方式有UFT-16、UTF-8 等等。: A String represents a string in the UTF-16 format in which supplementary characters are represented bysurrogate pairs (see the section Unicode Character Representations in the Character class for more information). Index values refer to char code units, so a supplementary character uses two positions in a String. The String class provides methods for dealing with Unicode code points (i.e., characters), in addition to those for dealing with Unicode code units (i.e., char values).
3. String只有一种格式,可认为String是独立于编码系统的,通过 getBytes(String charsetName) 可实现编码转换。
4. String对象是内存数据,string之间不存在编码变换问题。
5. 编码转换场景主要在 I/O , I/O 包括磁盘 I/O 和网络 I/O:文件输入输出、屏幕、数据库、浏览器、服务器。
6. 在内存中倒腾String数据是编码无关的,比如压缩编码。
7. 编码误区: new String(str.getBytes("ISO-8859-1"), "GB18030") 这种用法是无意义的,甚至是错误的。这种用法是用GB18030编码将ISO-8859-1编码格式的字节数据强制转换成unicode码点,不乱码是运气!
9. 数据库JDBC能够处理 数据库数据 <=> String 的正确互换。
9. OutputStreamWriter 和 InputStreamWriter 应该指定编码格式,避免程序依赖操作系统默认编码。
10. 用户从浏览器端发起一个 HTTP 请求,需要存在编码的地方是 URL、Cookie、Parameter。服务器端接受到 HTTP 请求后要解析 HTTP 协议,其中 URI、Cookie 和 POST 表单参数需要解码,服务器端可能还需要读取数据库中的数据,本地或网络中其它地方的文本文件,这些数据都可能存在编码问题,当 Servlet 处理完所有请求的数据后,需要将这些数据再编码通过 Socket 发送到用户请求的浏览器里,再经过浏览器解码成为文本。
11. tomcat: URL 的 URI 部分进行解码的字符集是在 connector 的 <Connector URIEncoding=”UTF-8”/>
12. QueryString(GET 查询参数) 的解码字符集要么是 Header 中 ContentType 中定义的 Charset 要么就是默认的 ISO-8859-1,要使用 ContentType 中定义的编码就要设置 connector 的 <Connector URIEncoding=”UTF-8” useBodyEncodingForURI=”true”/> 中的 useBodyEncodingForURI 设置为 true。
13. 不要在 Header 中传递非 ASCII 字符,如果一定要传递的话,我们可以先将这些字符用 org.apache.catalina.util.URLEncoder 编码然后再添加到 Header 中,这样在浏览器到服务器的传递过程中就不会丢失信息了,如果我们要访问这些项时再按照相应的字符集解码就好了。
14. POST 表单的编解码: 通过 HTTP 的 BODY 传递到服务端的。当我们在页面上点击 submit 按钮时浏览器首先将根据 ContentType 的 Charset 编码格式对表单填的参数进行编码然后提交到服务器端,在服务器端同样也是用 ContentType 中字符集进行解码。所以通过 POST 表单提交的参数一般不会出现问题,而且这个字符集编码是我们自己设置的,可以通过 request.setCharacterEncoding(charset) 来设置。
15. HTTP BODY 的编解码: 当用户请求的资源已经成功获取后,这些内容将通过 Response 返回给客户端浏览器,这个过程先要经过编码再到浏览器进行解码。这个过程的编解码字符集可以通过 response.setCharacterEncoding 来设置,它将会覆盖 request.getCharacterEncoding 的值,并且通过 Header 的 Content-Type 返回客户端,浏览器接受到返回的 socket 流时将通过 Content-Type 的 charset 来解码,如果返回的 HTTP Header 中 Content-Type 没有设置 charset,那么浏览器将根据 Html 的 <meta HTTP-equiv="Content-Type" content="text/html; charset=GBK" /> 中的 charset 来解码。如果也没有定义的话,那么浏览器将使用默认的编码来解码。<%@ page contentType="text/html; charset= GBK" %>。该设置和response.setCharacterEncoding("GBK")等效。
示例代码
/**
* @author zhenjing
*
* @date 2013-9-7
*/
public class cnCodeTest { public static void toHex(char[] b) {
for (int i = 0; i < b.length; i++) {
System.out.printf("%x " , (int)b[i]);
}
System.out.println();
} public static void toHex(byte[] b) {
for (int i = 0; i < b.length; i++) {
System.out.printf("%x " , b[i]);
}
System.out.println();
} public static void encode() {
String name = "I am 中文编码";
toHex(name.toCharArray());
try {
byte[] iso8859 = name.getBytes("ISO-8859-1");
toHex(iso8859);
byte[] gb2312 = name.getBytes("GB2312");
toHex(gb2312);
byte[] gbk = name.getBytes("GBK");
toHex(gbk);
byte[] utf16 = name.getBytes("UTF-16");
toHex(utf16);
byte[] utf8 = name.getBytes("UTF-8");
toHex(utf8);
} catch (Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) {
String cn = "中文编码"; // 这里存在编码转换: 将文件存储字节转成unicode存入String对象内存. 采用文件编码 char[] charArray = cn.toCharArray();
byte[] data = cn.getBytes(); System.out.println("print char array : " + cn);
toHex(cn.toCharArray()); cn = "���ı���"; // 这里存在编码转换: 将文件存储字节转成unicode存入String对象内存. 采用文件编码。
// 显示乱码是由于文件采用的编码无法解码文件存储字节数据。故存到String的unicode也是乱码的
charArray = cn.toCharArray();
System.out.println("print char array: " + cn);
toHex(cn.toCharArray()); encode();
}
}
参考文章
Java中文编码小结的更多相关文章
- Java序列化小结
title: Java序列化小结 date: 2017-05-06 20:07:59 tags: 序列化 categories: Java基础 --- Java序列化就是将一个对象转化成一串二进制表示 ...
- Java 基础--小结
Java 基础--小结 java基础 Java源程序(.java文件)——>java字节码文件(.class文件)——>由解释执行器(java.exe)将字节码文件加载到java虚拟机( ...
- debian/ubuntu部署java应用小结
近期改的Java应用即将部署,为了强强联合,需要把Java应用部署到linux,我们选择了debian系列.小结一下部署的大致过程,如下: Ubuntu已经默认安装了OpenJDK,但还是比较倾向官方 ...
- 面试贴:java异常小结
java的异常处理在面试中通常是个敏感的话题,这里我从整体框架方面稍微作一下我的小结. java的异常都继承Throwable这个类,也就是都可以抛出来的异常,在这个祖先类下,又分为如下子类: 1.E ...
- Java—字符串小结
最近工作中用到了大量有关字符串截取的知识,在此做出总结,希望需要的朋友带来帮助: 可以复制粘贴代码直接在java中测试1.将字符串中的指定字符":","-"删 ...
- Thrift-java学习小结
➠更多技术干货请戳:听云博客 Thrift是什么?什么情况下使用thrift Thrift源于大名鼎鼎的facebook之手,在2007年facebook提交Apache基金会将Thrift作为一个开 ...
- java Servlet小结
1:什么是Servlet? ① Servlet就是JAVA 类② Servlet是一个继承HttpServlet类的类③ 这个在服务器端运行,用以处理客户端的请求 2:Servlet 生命周期 Ser ...
- java线程小结3
1. 多线程概述 要实现多线程可以通过继承Thread和实现Runnable接口.不过这两者之间存在一些区别.其中最重要的区别就是,如果一个类继承Thread类,则不适合于多个线程共享资源,而实现了R ...
- java线程小结2
本文我们来总结一下可以改变线程状态的若干方法. 一. Thread类中的方法 1.sleep sleep方法属于Thread类,它相当于让线程睡眠,交出CPU,让CPU去执行其他的任务. 但是slee ...
随机推荐
- [Shell] swoole_timer_tick 与 crontab 实现定时任务和监控
手动完成 "任务" 和 "监控" 主要有下面三步: 1. mission_cron.php(定时自动任务脚本): <?php /** * 自动任务 定时器 ...
- [09]APUE:进程关系
[a] getpgid / setpgid #include <unistd.h> pid_t getpgid(pid_t pid) //成功返回进程组 ID,出错返回 -1 int se ...
- Spark中常用工具类Utils的简明介绍
<深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...
- Ado.net中简单的DBHelper类(增删改查)
private static string connString = "server=.;database=hotel;uid=aa;pwd=123";//最好从配置文件中取出 p ...
- 浅论ViewController的加载 -- 解决 viewDidLoad 被提前加载的问题(pushViewController 前执行)
一个ViewController,一般通过init或initWithNibName来加载.二者没有什么不同,init最终还是要调用initWithNibName方法(除非这个ViewControlle ...
- 纯css实现模块阴影变色效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- RocksDB笔记 - Compaction中的Iterator
Compaction中的Iterator 一般来说,Compaction的Input涉及两层数据的合并,对于涉及到的每一层数据: 如果是level-0,对level-0的每一个sstable文件建立一 ...
- RedHat Enterprise Linux 7关闭防火墙方法
systemctl命令是系统服务管理器指令,它实际上将 service 和 chkconfig 这两个命令组合到一起 在之前的版本中关闭防火墙等服务的命令是 service iptables stop ...
- 算法入门笔记------------Day3
主要是复习前面的基本内容,以及函数的概念 组合数 #include<stdio.h> int f(int n) { int m=1; for(int i=1;i<=n;i++) m* ...
- MongoDB学习笔记—02 MongoDB入门
Mongodb的基本概念 文档:是MongoDB中数据的基本单元,类似于关系型数据库中的行. 集合:多个文档组成一个集合,类似于关系型数据库中的表. 数据库:MongoDB的当个实例可以容纳多个独立的 ...