http://elf8848.iteye.com/blog/271742

问题:

当用JAVA字符流向硬盘写一个a.txt文件时,默认情况下a.txt 会使用什么字符集编码?

分析:

"字符流"是用JVM中所设置的字符集编码, 可我也没设置,那默认是什么字符集呢?

JVM是从系统变量file.encoding中读取操作系统的默认编码的字符集,来设置JVM的字符集编码

要查看系统的file.encoding参数,可以用以下代码:

Java代码  
  1. public static void main(final String[] args)
  2. {
  3. final String encoding = System.getProperty("file.encoding");
  4. System.out.println(encoding);
  5. }
public static void main(final String[] args)
{
final String encoding = System.getProperty("file.encoding");
System.out.println(encoding);
}

结果与操作系统(我用MS Windows)的区域语言有关系,如下表

标准和格式JVM默认字符集

中文(中国) GBK
中文(新加坡) GBK
中文(香港特别行政区) MS950
中文(澳门特别行政区) MS950
中文(台湾) MS950

我用的简体中文XP ,  所以 答案是 GBK

默认情况下a.txt 会使用GBK字符集编码

我们要想让a.txt 用UTF-8字符集编码保存, 就要做如下工作, new OutputStreamWriter() ,指定字符集编码,如下:

Java代码  
  1. final File file = new File("d:\\a.txt");
  2. if (!file.exists())
  3. {
  4. new File(file.getParent()).mkdirs();
  5. file.createNewFile(); //文件不存在,建立
  6. }
  7. final Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
  8. out.write("大量文字内容,比如HTML代码");
  9. out.flush();
  10. out.close();
final File file = new File("d:\\a.txt");
if (!file.exists())
{
new File(file.getParent()).mkdirs();
file.createNewFile(); //文件不存在,建立
}
final Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
out.write("大量文字内容,比如HTML代码");
out.flush();
out.close();

//------------------------------------ 转两篇文件 以供参考----------------------------------------------------

JVM的默认编码问题对JSTL标签的影响

Posted on 2006-03-02 11:17 么么茶 阅读(384) 评论(1)  编辑  收藏 所属分类: JAVA-WEB <!---->

今日无意中发现在中文系统使用良好的中文页面在移植到英文系统后出现了乱码,多方查找发现,出现乱码的页面是使用的jstl标签的c:url和c:param标签生成的URL通过c:import嵌入网页的,所以怀疑可能是c:param在进行Base64编码是使用的编码有问题。通过查找JSTL的源码发现在org.apache.taglibs.standard.tag.common.core.ParamSupport类即c:param的实现类中有这样一行代码:

   parent.addParameter(URLEncoder.encode(name), URLEncoder.encode(value))

其中URLEncoder.encode是问题所在。在JDK的API文档中已经标明URLEncoder.encode(String)这个方法已经deprecated了,而应该在编码时指定编码字符集。找到这里之后,再来看看URLEncoder.encode(String)的实现:

   public static String encode(String s){
      String str = null;

try {
         str = encode(s, dfltEncName);
      } catch (UnsupportedEncodingException e) {
      }

return str;
   }

可以看到默认使用了dfltEncName的字符集,那么这个dfltEncName又是如何得到的呢?从源码中找到如下:

dfltEncName = (String) AccessController.doProivileged(new GetPropertyAction("file.encoding"))

看到这里就一目了然了,JVM是从系统变量file.encoding中读取了默认编码的字符集。
之后,写了一个简单的测试程序,分别从中英文系统中取了一次默认的字符集,中文没问题是GBK,但是英文的就很奇怪,居然是Cp1252(好像是Latin I,按说应该是ISO8859-1才是)。看了一下英文系统的区域设置,Location选的是Englist(United States),改成PRC就完事大吉了。
为了防止这种问题的发生,最后还是决定采用最保险的办法,在Tomcat的启动参数中加入-Dfile.encoding=GBK,强制将缺省的字符集设为GBK,这样就一劳永逸了。

//--------------------------------------------------------------------

JAVA编码转换的详细过程


我们常见的JAVA程序包括以下类别:
       *直接在console上运行的类(包括可视化界面的类)
       *JSP代码类(注:JSP是Servlets类的变型)
       *Servelets类
       *EJB类
       *其它不可以直接运行的支持类
这些类文件中,都有可能含有中文字符串,并且我们常用前三类JAVA程序和用户直接交互,用于输出和输入字符,如:我们在JSP和Servlet中得到客户端送来的字符,这些字符也包括中文字符。无论这些JAVA类的作用如何,这些JAVA程序的生命周期都是这样的:
*编程人员在一定的操作系统上选择一个合适的编辑软件来实现源程序代码并以.java扩展名保存在操作系统中,例如我们在中文win2k中用记事本编辑一个java源程序;
       *编程人员用JDK中的javac.exe来编译这些源代码,形成.class类(JSP文件是由容器调用JDK来编译的);
       *直接运行这些类或将这些类布署到WEB容器中去运行,并输出结果。
      那么,在这些过程中,JDK和JVM是如何将这些文件如何编码和解码并运行的呢?
      这里,我们以中文win2k操作系统为例说明JAVA类是如何来编码和被解码的。
第一步,我们在中文win2k中用编辑软件如记事本编写一个Java源程序文件(包括以上五类JAVA程序),程序文件在保存时默认采用了操作系统默认支持GBK编码格式(操作系统默认支持的格式为file.encoding格式)形成了一个.java文件,也即,java程序在被编译前,我们的JAVA源程序文件是采用操作系统默认支持的file.encoding编码格式保存的,java源程序中含有中文信息字符和英文程序代码;要查看系统的file.encoding参数,可以用以下代码:
public class ShowSystemDefaultEncoding {
public static void main(String[] args) {
String encoding = System.getProperty("file.encoding");
System.out.println(encoding);
}}
第二步,我们用JDK的javac.exe文件编译我们的Java源程序,由于JDK是国际版的,在编译的时候,如果我们没有用-encoding参数指定我们的JAVA源程序的编码格式,则javac.exe首先获得我们操作系统默认采用的编码格式,也即在编译java程序时,若我们不指定源程序文件的编码格式,JDK首先获得操作系统的file.encoding参数(它保存的就是操作系统默认的编码格式,如WIN2k,它的值为GBK),然后JDK就把我们的java源程序从file.encoding编码格式转化为JAVA内部默认的UNICODE格式放入内存中。然后,javac把转换后的unicode格式的文件进行编译成.class类文件,此时.class文件是UNICODE编码的,它暂放在内存中,紧接着,JDK将此以UNICODE编码的编译后的class文件保存到我们的操作系统中形成我们见到的.class文件。对我们来说,我们最终获得的.class文件是内容以UNICODE编码格式保存的类文件,它内部包含我们源程序中的中文字符串,只不过此时它己经由file.encoding格式转化为UNICODE格式了。这一步中,对于JSP源程序文件是不同的,对于JSP,这个过程是这样的:即WEB容器调用JSP编译器,JSP编译器先查看JSP文件中是否设置有文件编码格式,如果JSP文件中没有设置JSP文件的编码格式,则JSP编译器调用JDK先把JSP文件用JVM默认的字符编码格式(也即WEB容器所在的操作系统的默认的file.encoding)转化为临时的Servlet类,然后再把它编译成UNICODE格式的class类,并保存在临时文件夹中。如:在中文win2k上,WEB容器就把JSP文件从GBK编码格式转化为UNICODE格式,然后编译成临时保存的Servlet类,以响应用户的请求。
      第三步,运行第二步编译出来的类,分为三种情况:
      A、 直接在console上运行的类
      B、 EJB类和不可以直接运行的支持类(如JavaBean类)
      C、 JSP代码和Servlet类
      D、 JAVA程序和数据库之间
下面我们分这四种情况来看。
A、直接在console上运行的类
这种情况,运行该类首先需要JVM支持,即操作系统中必须安装有JRE。运行过程是这样的:首先java启动JVM,此时JVM读出操作系统中保存的class文件并把内容读入内存中,此时内存中为UNICODE格式的class类,然后JVM运行它,如果此时此类需要接收用户输入,则类会默认用file.encoding编码格式对用户输入的串进行编码并转化为unicode保存入内存(用户可以设置输入流的编码格式)。程序运行后,产生的字符串(UNICODE编码的)再回交给JVM,最后JRE把此字符串再转化为file.encoding格式(用户可以设置输出流的编码格式)传递给操作系统显示接口并输出到界面上。以上每一步的转化都需要正确的编码格式转化,才能最终不出现乱码现象。
B、EJB类和不可以直接运行的支持类(如JavaBean类)
由于EJB类和不可以直接运行的支持类,它们一般不与用户直接交互输入和输出,它们常常与其它的类进行交互输入和输出,所以它们在第二步被编译后,就形成了内容是UNICODE编码的类保存在操作系统中了,以后只要它与其它的类之间的交互在参数传递过程中没有丢失,则它就会正确的运行。
C、JSP代码和Servlet类
经过第二步后,JSP文件也被转化为Servlets类文件,只不过它不像标准的Servlets一校存在于classes目录中,它存在于WEB容器的临时目录中,故这一步中我们也把它做为Servlets来看。
对于Servlets,客户端请求它时,WEB容器调用它的JVM来运行Servlet,首先,JVM把Servlet的class类从系统中读出并装入内存中,内存中是以UNICODE编码的Servlet类的代码,然后JVM在内存中运行该Servlet类,如果Servlet在运行的过程中,需要接受从客户端传来的字符如:表单输入的值和URL中传入的值,此时如果程序中没有设定接受参数时采用的编码格式,则WEB容器会默认采用ISO-8859-1编码格式来接受传入的值并在JVM中转化为UNICODE格式的保存在WEB容器的内存中。Servlet运行后生成输出,输出的字符串是UNICODE格式的,紧接着,容器将Servlet运行产生的UNICODE格式的串(如html语法,用户输出的串等)直接发送到客户端浏览器上并输出给用户,如果此时指定了发送时输出的编码格式,则按指定的编码格式输出到浏览器上,如果没有指定,则默认按ISO-8859-1编码发送到客户的浏览器上。
D、Java程序和数据库之间
对于几乎所有数据库的JDBC驱动程序,默认的在JAVA程序和数据库之间传递数据都是以ISO-8859-1为默认编码格式的,所以,我们的程序在向数据库内存储包含中文的数据时,JDBC首先是把程序内部的UNICODE编码格式的数据转化为ISO-8859-1的格式,然后传递到数据库中,在数据库保存数据时,它默认即以ISO-8859-1保存,所以,这是为什么我们常常在数据库中读出的中文数据是乱码。

JAVA字符流与字符集编码相关推荐

  1. Java18-day09【字节缓冲流、字符流、编码表、字符串与字符流中的编码解码问题、字符流读写数据的方式、字符缓冲流、IO流小结】

    视频+资料(工程源码.笔记)[链接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg   提取码:zjxs] Java基础--学习笔记(零起点打开java ...

  2. 黑马程序员——Java字符流、字节流IO流

    黑马程序员--Java字符流.字节流Io流 ---------------------- <a href="http://www.itheima.com"target=&qu ...

  3. java 字符流图片_java 字节流、字符流(复制图片、复制文本)

    1.File 1)构造方法 2)创建 3)判断.获取 4)删除 2.字节流 1)字节流写数据的3种方式 FileOutputStream fos = new FileOutputStream(&quo ...

  4. java字节流与字符流的区别编码缓冲

    部分摘自http://blog.csdn.net/cynhafa/article/details/6882061 所有的文件在存储和传输时都是以字节(byte)为单位进行的,包括图片等都是按字节的方式 ...

  5. JAVA Io 流 字符流 编码表 编码和解码的方法

    字节流,用中文可能会出现乱码 计算机中存储的信息都是二进制表示的 按照某种规则将字符编程二进制 再存储到计算机中,成为编码 按照同样规则,在计算机中二进制数解析出来,成为解码 编码和解码的方式必须一致 ...

  6. 1.7 Java字符流的使用:字符输入/输出流、字符文件和字符缓冲区的输入/输出流

    尽管 Java 中字节流的功能十分强大,几乎可以直接或间接地处理任何类型的输入/输出操作,但利用它却不能直接操作 16 位的 Unicode 字符.这就要用到字符流.本节将重点介绍字符流的操作. 字符 ...

  7. java字符流实际上也是字节,[Java教程]Java字节流与字符流的区别

    [Java教程]Java字节流与字符流的区别 0 2017-05-22 12:00:42 字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢? 实际上字节流在操作时本身 ...

  8. java字符流字节流场景_【120期】Java IO:字节流、字符流、缓冲流

    IO流是Java中的一个重要构成部分,也是我们经常打交道的.这篇关于Java IO的博文干货满满,堪称全网前三(请轻喷!) 下面几个问题(问题还会继续补充),如果你能对答如流,那么恭喜你,IO知识掌握 ...

  9. java字符流的父类_Java基于代码实战的字符流父类、字符转换流、缓冲字符流、过滤流...

    1. Java输入输出(I/O)流的知识回顾: 补充:因为这篇文章是基于上一篇的延续,因此将上一篇进行简单的回顾,以便理解本节内容. 1)输入输出(I/O)流分类:共分为字节型输入输出流和字符型输入输 ...

最新文章

  1. CentOS部署JAVA程序、安装Tomcat以及安装导入mysql文件的方法
  2. 高数第六章知识点框架
  3. awgn信道中的噪声功率谱密度_从OFC2020看高级算法在光通信中的应用
  4. 计算用户输入的数字的平均数,并输出大于平均数的数字输出
  5. Dubbo的优化 --- 开发时使用
  6. Burpsuite Web渗透-扫描工具(中间攻击,渗透大牛都用来修改包和监视包)
  7. 用apache commons-pool2建立thrift连接池
  8. extjs6入门:用sencha cmd搭建简单的extjs6项目
  9. 关于if else 和 switch 的区别 究竟哪个更快
  10. oracle中字母A或B是否包含在字符串中
  11. java.lang.UnsupportedOperationException: This parser does not support specification “null“ version “
  12. shiro放行_Shiro框架详解
  13. vs2015安装与配置
  14. 西安80转2000坐标系重新定义投影
  15. 三维实景拍摄虚拟现实!- Panorama
  16. Linux T恤设计大赛 “飞企鹅”获奖
  17. 2020.04 总结分享
  18. 给定两个字符串 s 和 t,它们只包含小写字母。
  19. ISA-95/B2MML教程 : 从用例到XML消息的整合实践
  20. 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇一:WPF常用知识以及本项目设计总结

热门文章

  1. Hi Azure. 从零开始打造一个语音机器人,跟你的电脑聊聊天。
  2. 华为有造车实力,却坚决不造整车,这背后有着怎样的无奈与思考?
  3. 11.1 JavaScript介绍
  4. Windows 下更换pip源为阿里源
  5. ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 程序目录
  6. 1019:浮点数向零舍入
  7. Java-OpenCV(一)准备工作
  8. 完美解决Ubuntu16.04虚拟机窗口自适应问题
  9. 【Qt】QModbusRtuSerialSlave类
  10. arm 架构_ARM发布A78增强版大核架构:性能怪兽