JAvaでの符号化問題

13791 ワード


コード問題で小損をしたので、特記します.
import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.util.zip.GZIPInputStream;

import java.util.zip.GZIPOutputStream;



/**

 * 

 *Module:          ZipUtil.java

 *Description:              

 *Company:       

 *Author:           vigar

 *Date:             May 6, 2012

 */

public class ZipStrUtil {

    public static void main(String[] args) throws IOException {

        //           

        String str = "00aa  a";

        System.out.println("
------->" + str); String ys = compress(str); System.out.println(" ----->" + ys); String jy = unCompress(ys);

     /* byte[] midArray=ys.getBytes();       String midStr=new String(midArray);
    unCompress(midStr);*/
        System.out.println("
--->" + jy); System.out.println(" --->"+jy.length()); outputFormat(jy); // if(str.equals(jy)){ System.out.println(" "); } } /** * * @param str * * @return * @throws IOException */ public static String compress(String str) throws IOException { if (null == str || str.length() <= 0) { return str; } // byte ByteArrayOutputStream out = new ByteArrayOutputStream(); // GZIPOutputStream gzip = new GZIPOutputStream(out); // b.length gzip.write(str.getBytes()); gzip.close(); // charsetName, return out.toString("ISO-8859-1"); } /** * * @param str * * @return * @throws IOException */ public static String unCompress(String str) throws IOException { if (null == str || str.length() <= 0) { return str; } // byte ByteArrayOutputStream out = new ByteArrayOutputStream(); // ByteArrayInputStream, buf ByteArrayInputStream in = new ByteArrayInputStream(str .getBytes("ISO-8859-1")); // GZIPInputStream gzip = new GZIPInputStream(in); byte[] buffer = new byte[256]; int n = 0; while ((n = gzip.read(buffer)) >= 0) {// // byte off len byte out.write(buffer, 0, n); } // charsetName, return out.toString("gbk"); } /** * mq , outputFormat byte[] * @param str * * @return * @throws IOException */ public static void outputFormat(String str) { byte[] origStr=str.getBytes(); for(int i =0;i<origStr.length;i++) { System.out.print(origStr[i]+" "); } System.out.println(" end"); } }

正常に動作
緑色の注釈部分を加えると、エラーが発生します.
Exception in thread "main" java.io.IOException: Not in GZIP format

at java.util.zip.GZIPInputStream.readHeader(Unknown Source)

at java.util.zip.GZIPInputStream.<init>(Unknown Source)

at java.util.zip.GZIPInputStream.<init>(Unknown Source)

at com.boco.fmhandler.wl.adapter.ZipStrUtil.unCompress(ZipStrUtil.java:82)

at com.boco.fmhandler.wl.adapter.ZipStrUtil.main(ZipStrUtil.java:29)

コードを次のように変更すると、正常に動作します.
   byte[] midArray=ys.getBytes("ISO-8859-1");

   String midStr=new String(midArray,"ISO-8859");

 
 深く探求する: 
StringのgetBytes()メソッドは,文字列のバイト配列を得ることで知られている.ただし、このメソッドは、オペレーティングシステムのデフォルトの符号化フォーマットのバイト配列を返すことに特に注意してください.この方法を使用するときにこれを考慮しないと、あるプラットフォームで良好なシステムを実行し、別のマシンに置くと予想外の問題が発生することがわかります.中国語オペレーティングシステムでは、getBytesメソッドは、1つのGBKまたはGB 2312の中国語符号化バイト配列を返し、そのうち中国語文字は、それぞれ2バイトを占めている.英語プラットフォームでは、一般的なデフォルトコードはISO-8859-1です.各文字には、ラテン文字でないかどうかにかかわらず、1バイトしか取られません.Javaは多国間符号化をサポートしており、Javaでは文字がUnicodeで格納されている点はclassファイルを逆コンパイルすればわかります.そこで、このような問題を回避するために、得られる符号化フォーマットを明確に示すために、String.getBytes(String charset)メソッドを符号化に使用することをお勧めします.次は小さな例を作って印象を深めてみましょう
public class TestCharset

{

    public static void main(String[] args)

    {

        new TestCharset().execute();

    }



    private void execute()

    {

        try

        {

            String s = "Hello!  !";

            byte[] bytes = s.getBytes();

            System.out.println("bytes lenght is:" + bytes.length);

        } catch (Exception e)

        {

            e.printStackTrace();

        }

    }

}

Windowsで実行
String: Hello!  !

bytes lenght is:12

linuxでは、次のように実行されます. その実行結果は環境変数LANGに関連していることがわかる
[sg@101/udp ~]$ javac -encoding GBK TestCharset.java 

[sg@101/udp ~]$ export LANG=C;

[sg@101/udp ~]$ java TestCharset

String: Hello!???

bytes lenght is:9

[sg@101/udp ~]$ export LANG=zh_CN;

[sg@101/udp ~]$ java TestCharset

String: Hello!  !

bytes lenght is:12

 getBytes()をbyte[]bytes=s.getBytes(「GBK」)に変更します.その後、
その結果、文字列の長さは環境変数の影響を受けません.すなわちbytes[]では、指定した符号化フォーマットで同じ内容が取り出されます.
[sg@101/udp ~]$ javac -encoding GBK TestCharset.java 

[sg@101/udp ~]$ export LANG=C;

[sg@101/udp ~]$ java TestCharset

String: Hello!???

bytes lenght is:12

[sg@101/udp ~]$ export LANG=zh_CN;

[sg@101/udp ~]$ java TestCharset

String: Hello!  !

bytes lenght is:12

 参考記事
http://www.360doc.com/content/08/1015/09/61497_1765862.shtml