JavaおよびJavaScript Base64エンコーディング
Java Webアプリケーションを開発するときは、Javaを使用してサーバー側でベース64エンコードを実行し、クライアント側のJavaScriptでデコードできます。これには、一貫性があるために両側のBase64エンコーディングメカニズムが必要です。
Base64エンコーディングを使用すると、さまざまな奇妙な状況に遭遇する可能性があり、エンコードにバグがあると疑われる可能性があります。しかし、実際には、そうではありません。 Base64が理論的に動作するオブジェクトは、文字列ではなくバイト配列です。その原則は、ASCIIコードの255文字を64で表現することを減らすことです。具体的には、元の3バイトは4バイトで表され、エンコード後に長さはある程度増加します。
1)セグメント化されたエンコードを避けるために、一度にエンコードするのが最善です。セグメント化されたエンコードをエンコードする必要があります。各セグメントのバイト数は3の倍数でなければなりません。
長いバイトストリームの場合、読み取り中にエンコードしたい場合は、各セグメントは3の倍数でなければなりません。そうしないと、復元中に混乱を引き起こす可能性があります。ほとんどの人は、2の乗数を使用してバイト[1024]などの配列を定義するのが好きです。これは3の倍数ではないため、復元中にエラーが発生する可能性があります。正しい例は次のとおりです。
byte [] bs = new byte [3*100] .... inputstream.read(bs).. encode(bs)...
文字列の場合、セグメント化されたエンコードエラーを避けるために、エンコード全体が一般的に必要です。
もちろん、セグメントでコーディングして1つずつ復元する場合、問題はありません。
2)文字列を復元するときに元のエンコードに従って文字列が復元されることを確認します。
Base64エンコード後のGBKエンコードされた漢字とUTF-8エンコードされた漢字の結果は、バイトアレイで動作するため、結果は異なります。たとえば、「we」という単語がgbkコードの場合、base64に変換された後はztldxw ==になります。 UTF-8コードの場合、base64に変換されてから5oir5lusになります。
それは「私たち」==》 getBytes( "gbk")==> base64です
したがって、Javaの変換に使用されるエンコードと、JavaScriptの復元に使用されるエンコード。 JavaとJavaScriptが普遍的であることを確認するために、Unicodeエンコードを使用します(JavaScriptをUTF-8とGBKに変換するのは不便なので、独自のUnicodeエンコードを使用します)。詳細は次のとおりです。
サーバー側:
1)GetBytes( "Unicode")を使用して、Unicodeバイト配列に変換します。
2)base64文字列にエンコードします
3)クライアントに転送します
クライアント:
1)base64はバイト配列にデコードされます
2)Unicodeを押して復元します
コードは次のとおりです(関連する関数については添付ファイルを参照):
base64.encode(data、 "unicode"); // Java Endエンコーディング
decode64(data); // JavaScriptデコード
添付ファイル1:JavaでのBase64エンコード
パッケージwebsharp.util; public class base64 {private static final byte [] encodingtable = {(byte) 'a'、(byte) 'b'、(byte) 'c' '、(byte)' d '、(byte)' e '、(byte)' f '、(byte)' g '、(byte)' h '、(byte)' ' 'l'、(byte) 'm'、(byte) 'n'、(byte) 'o'、(byte) 'p'、(byte) 'q'、(byte) 'r'、(byte) 's'、(byte) 't'、(byte) 'u'、(byte) 'v'、(byte) '' '、(byte)' '、(byte)' ''、 (byte) 'a'、(byte) 'b'、(byte) 'c'、(byte) 'd'、(byte) 'e'、(byte) 'f'、(byte) 'g'、(byte) 'h'、(byte) 'i'、(byte) 'j'、(byte) 'n' '、(byte)' n 'o'、(byte) 'p'、(byte) 'q'、(byte) 'r'、(byte) 's'、(byte) 't'、(byte) 'u'、(byte) 'v'、(byte) 'w'、(byte) 'x'、(byte) 'y'、(byte) '' 1 '、(byte)' '1'、 (byte) '3'、(byte) '4'、(byte) '5'、(byte) '6'、(byte) '7'、(byte) '8'、(byte) '9'、(byte) '+'、(byte) '/'};プライベート静的最終バイト[]デコードテーブル。 static {decodingTable = new Byte [128]; for(int i = 0; i <128; i ++){decodingTable [i] =(byte)-1; } for(int i = 'a'; i <= 'z'; i ++){decodingTable [i] =(byte)(i- 'a'); } for(int i = 'a'; i <= 'z'; i ++){decodingTable [i] =(byte)(i- 'a'+26); } for(int i = '0'; i <= '9'; i ++){decodingTable [i] =(byte)(i -'0'+52); } decodingTable ['+'] = 62; decodingTable ['/'] = 63; } public static byte [] Encode(byte [] data、int offset){byte [] bytes; int realcount = data.length-offset; int modulus = realcount%3; if(modulus == 0){bytes = new byte [(4 * realcount) / 3]; } else {bytes = new byte [4 *((realcount / 3) + 1)]; } int dataLength =(data.length -modulus); int a1; int a2; int a3; for(int i = offset、j = 0; i <datalength; i += 3、j += 4){a1 = data [i]&0xff; a2 = data [i + 1]&0xff; a3 = data [i + 2]&0xff; BYTES [J] = ENCODINGTABLE [(a1 >>> 2)&0x3f];バイト[j + 1] = encodingTable [((a1 << 4)|(a2 >>> 4))&0x3f];バイト[j + 2] = encodingTable [((a2 << 2)|(a3 >>> 6))&0x3f];バイト[j + 3] = encodingTable [a3&0x3f]; } int b1; int b2; int b3; int d1; int d2; switch(modulus){case 0: / *何も残っていない * / break;ケース1:d1 = data [data.length -1]&0xff; b1 =(d1 >>> 2)&0x3f; b2 =(d1 << 4)&0x3f;バイト[bytes.length -4] = encodingTable [b1];バイト[bytes.length -3] = encodingTable [B2];バイト[bytes.length -2] =(byte) '=';バイト[bytes.length -1] =(byte) '=';壊す;ケース2:d1 = data [data.length -2]&0xff; d2 = data [data.length -1]&0xff; b1 =(d1 >>> 2)&0x3f; b2 =((d1 << 4)|(d2 >>> 4))&0x3f; b3 =(d2 << 2)&0x3f;バイト[bytes.length -4] = encodingTable [b1];バイト[bytes.length -3] = encodingTable [B2];バイト[bytes.length -2] = encodingTable [B3];バイト[bytes.length -1] =(byte) '=';壊す; }バイトを返します。 } public static byte [] decode(byte [] data){byte [] bytes;バイトB1;バイトB2;バイトB3;バイトB4; data = discardnonbase64bytes(data); if(data [data.length -2] == '='){bytes = new byte [(((data.length / 4)-1) * 3) + 1]; } else if(data [data.length -1] == '='){bytes = new byte [(((data.length / 4) - 1) * 3) + 2]; } else {bytes = new byte [(data.length / 4) * 3)]; } for(int i = 0、j = 0; i <(data.length -4); i += 4、j += 3){b1 = decodingtable [data [i]]; b2 = decodingtable [data [i + 1]]; b3 = decodingtable [data [i + 2]]; b4 = decodingtable [data [i + 3]];バイト[j] =(byte)((b1 << 2)|(b2 >> 4));バイト[j + 1] =(byte)((b2 << 4)|(b3 >> 2));バイト[j + 2] =(byte)((b3 << 6)| b4); } if(data [data.length -2] = '='){b1 = decodingTable [data [data.length -4]]; b2 = decodingtable [data [data.length -3]];バイト[bytes.length -1] =(byte)((b1 << 2)|(b2 >> 4)); } else if(data [data.length -1] == '='){b1 = decodingTable [data [data.length -4]]; b2 = decodingtable [data [data.length -3]]; b3 = decodingtable [data [data.length -2]];バイト[bytes.length -2] =(byte)((b1 << 2)|(b2 >> 4));バイト[bytes.length -1] =(byte)((b2 << 4)|(b3 >> 2)); } else {b1 = decodingtable [data [data.length -4]]; b2 = decodingtable [data [data.length -3]]; b3 = decodingtable [data [data.length -2]]; b4 = decodingtable [data [data.length -1]];バイト[bytes.length -3] =(byte)((b1 << 2)|(b2 >> 4));バイト[bytes.length -2] =(byte)((b2 << 4)|(b3 >> 2));バイト[bytes.length -1] =(byte)((b3 << 6)| b4); }バイトを返します。 } public static byte [] decode(string data){byte [] byte b1;バイトB2;バイトB3;バイトB4; data = discardnonbase64chars(data); if(data.charat(data.length() - 2)== '='){bytes = new byte [((data.length() / 4) - 1) * 3) + 1]; } else if(data.charat(data.length() - 1)== '='){bytes = new byte [((data.length() / 4)-1) * 3) + 2]; } else {bytes = new byte [(data.length()) / 4) * 3)]; } for(int i = 0、j = 0; i <(data.length() - 4); i += 4、j += 3){b1 = decodingTable [data.Charat(i)]; b2 = decodingtable [data.charat(i + 1)]; b3 = decodingtable [data.charat(i + 2)]; b4 = decodingtable [data.charat(i + 3)];バイト[j] =(byte)((b1 << 2)|(b2 >> 4));バイト[j + 1] =(byte)((b2 << 4)|(b3 >> 2));バイト[j + 2] =(byte)((b3 << 6)| b4); } if(data.charat(data.length() - 2)== '='){b1 = decodingTable [data.Charat(data.Length()-4)]; b2 = decodingtable [data.charat(data.length()-3)];バイト[bytes.length -1] =(byte)((b1 << 2)|(b2 >> 4)); } else if(data.charat(data.length() - 1)== '='){b1 = decodingTable [data.charat(data.length()-4)]; b2 = decodingtable [data.charat(data.length()-3)]; b3 = decodingtable [data.charat(data.length()-2)];バイト[bytes.length -2] =(byte)((b1 << 2)|(b2 >> 4));バイト[bytes.length -1] =(byte)((b2 << 4)|(b3 >> 2)); } else {b1 = decodingtable [data.charat(data.length()-4)]; b2 = decodingtable [data.charat(data.length()-3)]; b3 = decodingtable [data.charat(data.length()-2)]; b4 = decodingtable [data.charat(data.length()-1)];バイト[bytes.length -3] =(byte)((b1 << 2)|(b2 >> 4));バイト[bytes.length -2] =(byte)((b2 << 4)|(b3 >> 2));バイト[bytes.length -1] =(byte)((b3 << 6)| b4); } for(int i = 0; i <bytes.length; i ++)system.out.println( "、"+bytes [i]);バイトを返します。 } private static byte [] discardnonbase64bytes(byte [] data){byte [] temp = new byte [data.length]; int bytescopied = 0; for(int i = 0; i <data.length; i ++){if(asvalidbase64byte(data [i])){temp [bytescopied ++] = data [i]; }} byte [] newData = new byte [bytescopied]; System.ArrayCopy(Temp、0、NewData、0、Bytescopied); NewDataを返します。 } private static string docardnonbase64chars(string data){stringbuffer sb = new StringBuffer(); int length = data.length(); for(int i = 0; i <length; i ++){if(asvalidbase64byte((byte)(data.charat(i)))){sb.append(data.charat(i)); }} return sb.toString(); } private static boolean isvalidbase64byte(byte b){if(b == '='){return true; } else if((b <0)||(b> = 128)){return false; } else if(decodingTable [b] == -1){return false; } trueを返します。 } public static string encode(string data、string charset)スロー例外{// byte [] result =(data.getBytes( "unicode")); if(data == null || data.length()== 0)データを返す; int offset = 0; //( "Unicode")を取得した後、2バイト「Fe」がフロントバイトに追加されます[] result = encode(data.getBytes(charset)、offset); stringbuffer sb = new StringBuffer(result.length); for(int i = 0; i <result.length; i ++)sb.append((char)result [i]); return sb.tostring(); } public static string decode(string data、string charset)スロー例外{if(data == null || data.length()== 0)return data;新しい文字列(base64.decode(data)、charset)を返します。 } public static void main(string [] args)スロー例外{string data = "we";文字列data1 = encode(data、 "unicode");文字列data2 = decode(data1、 "unicode"); System.out.println(data); System.out.println(data1); System.out.println(data2); }}付録2:JavaScriptでのBase64エンコーディング
<html> <head> <title> base64エンコード/デコード</title> </head> <script type = "text/javascript"> <! - var keystr = "abcdefghijklmnop" + " "="; function encode64(input){input = unicodetobytes(input); var output = ""; var chr1、chr2、chr3 = ""; var enc1、enc2、enc3、enc4 = ""; var i = 0; {chr1 = input [i ++]; chr2 = input [i ++]; chr3 = input [i ++]; enc1 = chr1 >> 2; enc2 =((chr1&3)<< 4)| (Chr2 >> 4); enc3 =((chr2&15)<< 2)| (Chr3 >> 6); enc4 = chr3&63; if(isnan(chr2)){enc3 = enc4 = 64; } else if(isnan(chr3)){enc4 = 64; } output = output + keystr.charat(enc1) + keystr.charat(enc2) + keystr.charat(enc3) + keystr.charat(enc4); chr1 = chr2 = chr3 = ""; enc1 = enc2 = enc3 = enc4 = ""; } while(i <input.length);返品出力; }関数decode64(input){var output = ""; var chr1、chr2、chr3 = ""; var enc1、enc2、enc3、enc4 = ""; var i = 0; // AZ、AZ、0-9、 +、/、OR = var base64Test =/[^a-za-z0-9/ +/// =]/gでないすべての文字を削除します。 if(base64test.exec(input)){alert( "入力テキストに無効なbase64文字がありました。/n" + "有効なbase64文字は、az、az、 ' +'、 '/'、および '='/n" + "デコードのエラーを期待しています。 } input = input.replace(/[^a-za-z0-9/+//// =]/g、 ""); output = new Array(); {enc1 = keystr.indexof(input.charat(i ++)); enc2 = keystr.indexof(input.charat(i ++)); enc3 = keystr.indexof(input.charat(i ++)); enc4 = keystr.indexof(input.charat(i ++)); chr1 =(enc1 << 2)| (enc2 >> 4); chr2 =((enc2&15)<< 4)| (enc3 >> 2); chr3 =((enc3&3)<< 6)| enc4; output.push(chr1); if(enc3!= 64){output.push(chr2); } if(enc4!= 64){output.push(chr3); } chr1 = chr2 = chr3 = ""; enc1 = enc2 = enc3 = enc4 = ""; } while(i <input.length); return bytestounicode(output); } function unicodetobytes {var result = new array(); if(s == null || s == "")return result; result.push(255); // result.push(254)に「fe」を追加します。 for(var i = 0; i <s.length; i ++){var c = s.charcodeat(i).toString(16); if(c.length == 1)i = "000"+c; else if(c.length == 2)c = "00"+c; else if(c.length == 3)c = "0"+c; var var1 = parseint(C.Substring(2)、16); var var2 = parseint(C.Substring(0,2)、16); result.push(var1); result.push(var2); } return result; } function bytestounicode(bs){var result = ""; var offset = 0; if(bs.length> = 2 && bs [0] == 255 && bs [1] == 254)offset = 2; //(var i = offset; i <bs.length; i+= 2){var code = bs [i]+(bs [i+1] << 8); result+= string.fromCharcode(code); } return result; } // - > </script> <body> <form name = "base64form"> base64でエンコードするメッセージを入力するか、<br> base64エンコードされたテキストをテキストフィールドにエンコードし、エンコードまたはデコードを選択し、ボタンを選択し、<br> <br> <br> <textarea name = "theText" cols = ""> < name = "encode" value = "base64" onclick = "document.base64form.thetext.value = encode64(document.base64form.thetext.value);"> <入力タイプ= "ボタン" name = "decode" value = "decode" decode "base64" onclick = "document.base64form.thetext.value = decode64(document.base64form.thetext.value);"> </form> </body> </html>読んでくれてありがとう、私はそれがあなたを助けることができることを願っています。このサイトへのご支援ありがとうございます!