关于java乱码问题,字符串都是采用服务器默认编码的,有的服务器采用GBK;有的是UTF-8,那么如何避免字符串乱码问题呢?



字符串乱码具体原因

1)首先,明确一点,乱码是因为没有正确的指定编码格式,常见的编码格式有 utf-8(UTF8)、GBK、GB2312、ISO-8859-1.....

2)其次,Java的字符串编码统一采用Unicode编码,字符串中是用一个final char数组存储的,每个char拥有两byte,也就能存储汉字。

3)然后,Java中使用字符串存储已经有编码格式的内容时,字符串是不会有默认进行转码,也就是说传给字符串的是什么内容,那么字符串存储的就是什么内容,他不会自动进行转码!

4)最后,如果我们使用了

String.getBytes(charset);

那么,就会对字符串的内容进行转码,这句代码的意思就是把字符串原来的编码格式转为指定的charset编码格式,

如果采用

String.getBytes();

那么,就等价于 String.getBytes(System.getProperty("file.encoding")); 或者 String.getBytes(Charset.defaultCharset().name());采用系统编码进行转换,这个操作是非常危险的,因为不同的服务器系统编码不一样,所以经常出现这台服务器正常,而另外一台服务器则乱码!



字符串乱码解决:

1)不要使用 String.getBytes()方法,而要使用 String.getBytes(charset),这个charset必须是String内容的编码格式!

2)字符串转换是采用 new String(str1.getBytes(str1Charset),str2Charset);同样如果没有指定str2Charset也会采用默认的系统编码!但是这个要与 new String(str) 区别开来,他其实也是没有进行转码,源代码中可以看出!

3)在 HttpURLConnection Post 参数的时候会使用到字符串转码:

conn.setDoOutput(true);// 是否输入参数
  conn.getOutputStream().write(param.toString().getBytes());// 输入参数,
  conn.setDoOutput(true);// 是否输入参数
  conn.getOutputStream().write(param.toString().getBytes());// 输入参数,

    这里采用系统默认编码实际上是错误的,因为我们不知道param里面的内容具体是什么编码!

4)在文件读取和写入的时候会使用到字符串转码:

   // 读取文件内容

isr = new InputStreamReader(new FileInputStream(file),fileCharset);
   int length = -1 ;
   char[] buffer = new char[1024];
   StringBuffer sb = new StringBuffer();
   while((length = isr.read(buffer, 0, 1024) ) != -1){
    sb.append(buffer,0,length);
   }
   data = new String(sb);
   isr = new InputStreamReader(new FileInputStream(file),fileCharset);
   int length = -1 ;
   char[] buffer = new char[1024];
   StringBuffer sb = new StringBuffer();
   while((length = isr.read(buffer, 0, 1024) ) != -1){
    sb.append(buffer,0,length);
   }
   data = new String(sb);

    // 写人内容

osw = new OutputStreamWriter(new FileOutputStream(path),fileCharset);
    osw.write(new String(data.getBytes(charset1),charset2));
    osw.flush();
    osw = new OutputStreamWriter(new FileOutputStream(path),fileCharset);
    osw.write(new String(data.getBytes(charset1),charset2));
    osw.flush();

    读取文件内容时通过指定文件的编码格式进行读取,这个时候字符串会把读取的内容存储不会就像自动转码,因此字符串中存储的内容是按照文件的编码格式编码的。其实这里我们也可以通过采用字节流读取然后在采用字符串转码为指定编码格式;其次,写内容时,首先指定文件的编码格式,然后是设置字符串的编码格式,因为写一帮采用的是字节数组,字节是没有乱码一说的,所以我们要把字符串转为指定编码格式的的字节数组,这个时候如果采用data.getBytes(),那么采用系统编码则可能会出现乱码!!

5)在GBK系统中,假设内容是UTF-8编码,采用 new String(str.getBytes("utf-8"),"GBK"),然后 value.getByte(); 是不会乱码的原因就是先转为GBK,后面有默认从GBK(系统编码)转回来,最后还是UTF-8,所以不会乱码!

6)(Java字符串)转码指的是内容的字节不发生变化,只是根据编码格式的要求对字节进行不同长度的分割,比如ISO-8859-1是一个字节,然而是UTF-8则是可变的,所以把UTF-8转为ISO-8859-1 会发生乱码,但是又从ISO-8859-1 转为UTF-8则恢复正常。所以这里转码并不是我们使用的那种转码工具!