当前位置: 技术问答>java相关
问个关于编码的问题,请高手进来讨论下
来源: 互联网 发布时间:2015-05-30
本文导语: 在用java/jsp/tomcat的时候总是遇到编码的问题,稍不注意就乱码? 一般解决办法就是用String(xxx.getBytes("encoding"), "encoding") 转来转去的, 可是,如果想让系统能够同时支持多种语言,比如,用户在页面上输入了中文 serv...
在用java/jsp/tomcat的时候总是遇到编码的问题,稍不注意就乱码?
一般解决办法就是用String(xxx.getBytes("encoding"), "encoding")
转来转去的,
可是,如果想让系统能够同时支持多种语言,比如,用户在页面上输入了中文
servlet保存,以后再调用现实就是中文;用户输入了日文,以后调用就显示出来
日文,(在html中不指定页面编码,用户只要自己选择对就可以)
怎么做呢?
在php中,不需要程序员作什么转化就可以实现,,
为什么java功能比php要强大很多(个人认为不是一个档次的)却不能实现?或者是实现起来很困难?
还有,顺便问个小问题
我用sevlet读输入参数,tomcat 4.01
没有做什么转换,直接输出,就能把中文显示出来,而不论做不作转换,写到文件里都是乱码,为什么?
一般解决办法就是用String(xxx.getBytes("encoding"), "encoding")
转来转去的,
可是,如果想让系统能够同时支持多种语言,比如,用户在页面上输入了中文
servlet保存,以后再调用现实就是中文;用户输入了日文,以后调用就显示出来
日文,(在html中不指定页面编码,用户只要自己选择对就可以)
怎么做呢?
在php中,不需要程序员作什么转化就可以实现,,
为什么java功能比php要强大很多(个人认为不是一个档次的)却不能实现?或者是实现起来很困难?
还有,顺便问个小问题
我用sevlet读输入参数,tomcat 4.01
没有做什么转换,直接输出,就能把中文显示出来,而不论做不作转换,写到文件里都是乱码,为什么?
|
那就帮着UP吧
好像只有jsp有编码的麻烦问题。ASP也没有
单编码只是其中很小的一部分,不能一叶障目吧
好像只有jsp有编码的麻烦问题。ASP也没有
单编码只是其中很小的一部分,不能一叶障目吧
|
你把他转成UTF8的一般能解决问题!我没试验过,不过我认为是可以的!CSDN就是这样的!你看看本叶面的编码!
|
不好意思,本人也是后进学者.............
|
java 中文问题的表层分析及处理
I. 取中文
用 JDBC 执行 SELECT 语句从服务器端读取数据(中文)后,将数据用
APPEND 方法加到 TTextArea(TA) ,不能正确显示。但加到 List 中时,
大部分汉字却可正确显示。
将数据按"ISO-8859-1" 编码方式转化为字节数组,再按系统缺省编码方式
(Default Charracter Encoding) 转化为 STRING ,即可在 TA 和 List
中正确显示。
程序段如下:
dbstr2 = results.getString(1);
//After reading the result from DB server,converting it to string.
0Adbbyte1 = dbstr2.getBytes("iso-8859-1");
dbstr1 = new String(dbbyte1);
在转换字符串时不采用系统默认编码方式,而直接采用" GBK" 或者
"GB2312" ,在 A 和 B 两种情况下,从数据库取数据都没有问题。
II. 写中文到数据库
处理方式与"取中文"相逆,先将 SQL 语句按系统缺省编码方式转化为字节数
组,再按"ISO--8859-1"编码方式转化为 STRING ,最后送去执行,则中文信
息可正确写入数据库。
程序段如下:
sqlstmt = tf_input.getText();
//Before sending statement to DB server,converting it to sql
statement.
dbbyte1 = sqlstmt.getBytes();
sqlstmt = newString(dbbyte1,"iso-8859-1");
_stmt = _con.createStatement();
0A_stmt.executeUpdate(sqlstmt);
……
问题:如果客户机上存在 CLASSPATH 指向 JDK 的 CLASSES.ZIP 时(称为 A 0D
情况),上述述程序代码可正确执行。但是如果客户机只有浏览器,而没有
JDK 和 CLASSPATH 时(称为 B 情况),则汉字无法正确转换。
我们的分析:
1.经过测试,在 A 情况下,程序运行时系统的缺省编码方式为 GBK 或者
GB2312 。在 B 乔 况下,程序启动时浏览器的 JAVA 控制台中出现如下错误
信息:
Can't find resource for sun.awt.windows.awtLocalization_zh_CN
然后系统的缺省编码方式为"8859-1"。
2.如果在转换字符串时不采用系统缺省编码方式,而是直接采用 "GBK" 或
"GB2312",则在 A 情况下程序仍然可正常运行,在 B 情况下,系统出现错
误:
UnsupportedEncodingException。
3.在客户机上,把 JDK 的 CLASSES.ZIP 解压后,放在另一个目录中,
CLASSPATH 只包含父 目录。然后一边逐步删除该目录中的 .CLASS 文件,另
一边运行测试程序,最后发现在一千多个 CLASS 文件中,只有一个是必不可
少的,该文件是:
sun.io.CharToByteDoubleByte.class。
将该文件拷到服务器端和其它的类放在一起,并在程序的开头 IMPORT 它,
在 B 情况下程行 仍然无法正常运行。
4.在 A 情况下,如果在 CLASSPTH 中去掉
sun.io.CharToByteDoubleByte.class ,则程序序运行时测得默认编码方式
为"8859-1",否则为 "GBK" 或 "GB2312" 。
如果 JDK 的版本为1.2以上的话,在 B 情况下遇到的问题得到了很好的解决
,测试的步骤屯希 兴趣的读者可以尝试一下。
[/b]Java 中文问题的根源分析及解决[/b]
在简体中文 MS Windows 98 + JDK 1.3 下,可以用
System.getProperties() 得到 Java 栽 行环境的一些基本属性,类
PoorChinese 可以帮助我们得到这些属性。
类 PoorChinese 的源代码:
public class PoorChinese {
public static void main(String[] args) {
System.getProperties().list(System.out);
}
}
执行 java PoorChinese 后,我们会得到:
系统变量 file.encoding 的值为 GBK ,user.language 的值为 zh ,
user.region 的值挝?CN ,这些系统变量的值决定了系统默认的编码方式是
GBK 。
在上述系统中,下面的代码将 GB2312 文件转换成 Big5 文件,它们能够帮
助我们理解 Javva 中汉字编码的转化:
import java.io.*;
import java.util.*;
public class gb2big5 {
static int iCharNum=0;
public static void main(String[] args) {
System.out.println("Input GB2312 file, output Big5 file.");
if (args.length!=2) {
System.err.println("Usage: jview gb2big5 gbfile big5file");
System.exit(1);
}
String inputString = readInput(args[0]);
writeOutput(inputString,args[1]);
System.out.println("Number of Characters in file: "+iCharNum+".");
}
static void writeOutput(String str, String strOutFile) {
try {
FileOutputStream fos = new FileOutputStream(strOutFile);
Writer out = new OutputStreamWriter(fos, "Big5");
out.write(str);
out.close();
}
catch (IOException e) {
e.printStackTrace();
e.printStackTrace();
}
}
static String readInput(String strInFile) {
StringBuffer buffer = new StringBuffer();
try {
FileInputStream fis = new FileInputStream(strInFile);
InputStreamReader isr = new InputStreamReader(fis, "GB2312");
Reader in = new BufferedReader(isr);
0A
int ch;
while ((ch = in.read()) > -1) {
iCharNum += 1;
buffer.append((char)ch);
0A
}
in.close();
return buffer.toString();
0A
}
catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
编码转化的过程如下:
ByteToCharGB2312 CharToByteBig5
GB2312------------------>Unicode------------->Big5
执行 java gb2big5 gb.txt big5.txt ,如果 gb.txt 的内容是"今天星期三
",则得到的文文件 big5.txt 中的字符能够正确显示;而如果 gb.txt 的内
容是"情人节快乐",则得到的文件 big5.txt 中对应于"节"和"乐"的字符都
是符号"?"(0x3F),?
见 sun.io.ByteToCharGB2312 和
附一个用于从数据库和网络中取出中文乱码的处理函数,入参是有问题的字
符串,出参是问问题已经解决了的字符串。
正如上例一样, Java 的基本类也可能存在问题。由于国际化的工作并不是
在国内完成的,,所以在这些基本类发布之前,没有经过严格的测试,所以
对中文字符的支持并不像 Java Soft 所声称的那样完美。前不久,我的一位
技术上的朋友发信给我说
他终于找到了 Java Servlet
中文问题的根源。两周以来,他一直为 Java Servlet
的中文问题所困扰,因为每面对一个含有中文字符的字符串都必须进行强制
转换才能够得到到正确的结果(这好象是大家公认的唯一的解决办法)。后
来,他确实不想如此继续安分下去了,因为这样的事情确实不应该是高级程
序员所要做的工作,他就?
出 Servlet
解码的源代码进行分析,因为他怀疑问题就出在解码这部分。经过四个小时
的奋斗,他终于于找到了问题的根源所在。原来他的怀疑是正确的,
Servlet 的解码部分完全没有考虑双字节,直接把 XX 当作一个字符。(原
来 Java Soft 也会犯这幺低级
错误!)
如果你对这个问题有兴趣或者遇到了同样的烦恼的话,你可以按照他的步骤
对 Servlet.jarr 进行修改:
找到源代码 HttpUtils 中的 static private String parseName ,在返回
前将 sb(StrinngBuffer) 复制成 byte bs[] ,然后 return new
String(bs,"GB2312")。作上述修改后就需要自己解码了:
HashTable form=HttpUtils
.parseQueryString(request.getQueryString())或者
form=HttpUtils.parsePostData(……)
千万别忘了编译后放到 Servlet.jar 里面。
五、 关于 Java 中文问题的总结
Java 编程语言成长于网络世界,这就要求 Java 对多国字符有很好的支持。
Java 编程语蜒允视α 计算的网络化的需求,为它能够在网络世界迅速成长
奠定?坚实的基础。 Java 的缔造者 (Java Soft) 已经考虑到 Java
附一个用于从数据库和网络中取出中文乱码的处理函数,入参是有问题的字
符串,出参是问问题已经解决了的字符串。
String parseChinese(String in)
{
String s = null;
byte temp [];
if (in == null)
{
System.out.println("Warn:Chinese null founded!");
return new String("");
}
try
{
temp=in.getBytes("iso-8859-1");
temp=in.getBytes("iso-8859-1");
s = new String(temp);
}
{
System.out.println("Warn:Chinese null founded!");
return new String("");
0A}
try
{
temp=in.getBytes("iso-8859-1"); 0D
s = new String(temp);
}
catch(UnsupportedEncodingException e)
{
I. 取中文
用 JDBC 执行 SELECT 语句从服务器端读取数据(中文)后,将数据用
APPEND 方法加到 TTextArea(TA) ,不能正确显示。但加到 List 中时,
大部分汉字却可正确显示。
将数据按"ISO-8859-1" 编码方式转化为字节数组,再按系统缺省编码方式
(Default Charracter Encoding) 转化为 STRING ,即可在 TA 和 List
中正确显示。
程序段如下:
dbstr2 = results.getString(1);
//After reading the result from DB server,converting it to string.
0Adbbyte1 = dbstr2.getBytes("iso-8859-1");
dbstr1 = new String(dbbyte1);
在转换字符串时不采用系统默认编码方式,而直接采用" GBK" 或者
"GB2312" ,在 A 和 B 两种情况下,从数据库取数据都没有问题。
II. 写中文到数据库
处理方式与"取中文"相逆,先将 SQL 语句按系统缺省编码方式转化为字节数
组,再按"ISO--8859-1"编码方式转化为 STRING ,最后送去执行,则中文信
息可正确写入数据库。
程序段如下:
sqlstmt = tf_input.getText();
//Before sending statement to DB server,converting it to sql
statement.
dbbyte1 = sqlstmt.getBytes();
sqlstmt = newString(dbbyte1,"iso-8859-1");
_stmt = _con.createStatement();
0A_stmt.executeUpdate(sqlstmt);
……
问题:如果客户机上存在 CLASSPATH 指向 JDK 的 CLASSES.ZIP 时(称为 A 0D
情况),上述述程序代码可正确执行。但是如果客户机只有浏览器,而没有
JDK 和 CLASSPATH 时(称为 B 情况),则汉字无法正确转换。
我们的分析:
1.经过测试,在 A 情况下,程序运行时系统的缺省编码方式为 GBK 或者
GB2312 。在 B 乔 况下,程序启动时浏览器的 JAVA 控制台中出现如下错误
信息:
Can't find resource for sun.awt.windows.awtLocalization_zh_CN
然后系统的缺省编码方式为"8859-1"。
2.如果在转换字符串时不采用系统缺省编码方式,而是直接采用 "GBK" 或
"GB2312",则在 A 情况下程序仍然可正常运行,在 B 情况下,系统出现错
误:
UnsupportedEncodingException。
3.在客户机上,把 JDK 的 CLASSES.ZIP 解压后,放在另一个目录中,
CLASSPATH 只包含父 目录。然后一边逐步删除该目录中的 .CLASS 文件,另
一边运行测试程序,最后发现在一千多个 CLASS 文件中,只有一个是必不可
少的,该文件是:
sun.io.CharToByteDoubleByte.class。
将该文件拷到服务器端和其它的类放在一起,并在程序的开头 IMPORT 它,
在 B 情况下程行 仍然无法正常运行。
4.在 A 情况下,如果在 CLASSPTH 中去掉
sun.io.CharToByteDoubleByte.class ,则程序序运行时测得默认编码方式
为"8859-1",否则为 "GBK" 或 "GB2312" 。
如果 JDK 的版本为1.2以上的话,在 B 情况下遇到的问题得到了很好的解决
,测试的步骤屯希 兴趣的读者可以尝试一下。
[/b]Java 中文问题的根源分析及解决[/b]
在简体中文 MS Windows 98 + JDK 1.3 下,可以用
System.getProperties() 得到 Java 栽 行环境的一些基本属性,类
PoorChinese 可以帮助我们得到这些属性。
类 PoorChinese 的源代码:
public class PoorChinese {
public static void main(String[] args) {
System.getProperties().list(System.out);
}
}
执行 java PoorChinese 后,我们会得到:
系统变量 file.encoding 的值为 GBK ,user.language 的值为 zh ,
user.region 的值挝?CN ,这些系统变量的值决定了系统默认的编码方式是
GBK 。
在上述系统中,下面的代码将 GB2312 文件转换成 Big5 文件,它们能够帮
助我们理解 Javva 中汉字编码的转化:
import java.io.*;
import java.util.*;
public class gb2big5 {
static int iCharNum=0;
public static void main(String[] args) {
System.out.println("Input GB2312 file, output Big5 file.");
if (args.length!=2) {
System.err.println("Usage: jview gb2big5 gbfile big5file");
System.exit(1);
}
String inputString = readInput(args[0]);
writeOutput(inputString,args[1]);
System.out.println("Number of Characters in file: "+iCharNum+".");
}
static void writeOutput(String str, String strOutFile) {
try {
FileOutputStream fos = new FileOutputStream(strOutFile);
Writer out = new OutputStreamWriter(fos, "Big5");
out.write(str);
out.close();
}
catch (IOException e) {
e.printStackTrace();
e.printStackTrace();
}
}
static String readInput(String strInFile) {
StringBuffer buffer = new StringBuffer();
try {
FileInputStream fis = new FileInputStream(strInFile);
InputStreamReader isr = new InputStreamReader(fis, "GB2312");
Reader in = new BufferedReader(isr);
0A
int ch;
while ((ch = in.read()) > -1) {
iCharNum += 1;
buffer.append((char)ch);
0A
}
in.close();
return buffer.toString();
0A
}
catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
编码转化的过程如下:
ByteToCharGB2312 CharToByteBig5
GB2312------------------>Unicode------------->Big5
执行 java gb2big5 gb.txt big5.txt ,如果 gb.txt 的内容是"今天星期三
",则得到的文文件 big5.txt 中的字符能够正确显示;而如果 gb.txt 的内
容是"情人节快乐",则得到的文件 big5.txt 中对应于"节"和"乐"的字符都
是符号"?"(0x3F),?
见 sun.io.ByteToCharGB2312 和
附一个用于从数据库和网络中取出中文乱码的处理函数,入参是有问题的字
符串,出参是问问题已经解决了的字符串。
正如上例一样, Java 的基本类也可能存在问题。由于国际化的工作并不是
在国内完成的,,所以在这些基本类发布之前,没有经过严格的测试,所以
对中文字符的支持并不像 Java Soft 所声称的那样完美。前不久,我的一位
技术上的朋友发信给我说
他终于找到了 Java Servlet
中文问题的根源。两周以来,他一直为 Java Servlet
的中文问题所困扰,因为每面对一个含有中文字符的字符串都必须进行强制
转换才能够得到到正确的结果(这好象是大家公认的唯一的解决办法)。后
来,他确实不想如此继续安分下去了,因为这样的事情确实不应该是高级程
序员所要做的工作,他就?
出 Servlet
解码的源代码进行分析,因为他怀疑问题就出在解码这部分。经过四个小时
的奋斗,他终于于找到了问题的根源所在。原来他的怀疑是正确的,
Servlet 的解码部分完全没有考虑双字节,直接把 XX 当作一个字符。(原
来 Java Soft 也会犯这幺低级
错误!)
如果你对这个问题有兴趣或者遇到了同样的烦恼的话,你可以按照他的步骤
对 Servlet.jarr 进行修改:
找到源代码 HttpUtils 中的 static private String parseName ,在返回
前将 sb(StrinngBuffer) 复制成 byte bs[] ,然后 return new
String(bs,"GB2312")。作上述修改后就需要自己解码了:
HashTable form=HttpUtils
.parseQueryString(request.getQueryString())或者
form=HttpUtils.parsePostData(……)
千万别忘了编译后放到 Servlet.jar 里面。
五、 关于 Java 中文问题的总结
Java 编程语言成长于网络世界,这就要求 Java 对多国字符有很好的支持。
Java 编程语蜒允视α 计算的网络化的需求,为它能够在网络世界迅速成长
奠定?坚实的基础。 Java 的缔造者 (Java Soft) 已经考虑到 Java
附一个用于从数据库和网络中取出中文乱码的处理函数,入参是有问题的字
符串,出参是问问题已经解决了的字符串。
String parseChinese(String in)
{
String s = null;
byte temp [];
if (in == null)
{
System.out.println("Warn:Chinese null founded!");
return new String("");
}
try
{
temp=in.getBytes("iso-8859-1");
temp=in.getBytes("iso-8859-1");
s = new String(temp);
}
{
System.out.println("Warn:Chinese null founded!");
return new String("");
0A}
try
{
temp=in.getBytes("iso-8859-1"); 0D
s = new String(temp);
}
catch(UnsupportedEncodingException e)
{