Java 및 JavaScript Base64 인코딩
Java 웹 응용 프로그램을 개발할 때 Java를 사용하여 서버 측에서 Base64 인코딩을 수행하고 클라이언트 측의 JavaScript로 해독 할 수 있습니다. 이를 위해서는 양쪽의 Base64 인코딩 메커니즘이 일관성이 있어야합니다.
Base64 인코딩을 사용하면 다양한 이상한 상황이 발생할 수 있으며 인코딩에 버그가 있다고 의심했습니다. 그러나 사실, 이것은 사실이 아닙니다. Base64가 이론적으로 작동하는 객체는 문자열이 아니라 바이트 어레이입니다. 그것의 원칙은 64로 표현 될 ASCII 코드의 255자를 줄이는 것입니다. 특히 원래 3 바이트는 4 바이트로 표시되며 인코딩 후 길이는 일정 범위로 증가합니다.
1) 세그먼트 인코딩을 피하기 위해 한 번에 인코딩하는 것이 가장 좋습니다. 실제로 세그먼트 된 인코딩을 인코딩해야합니다. 각 세그먼트의 바이트 수는 3의 배수 여야합니다.
긴 바이트 스트림의 경우, 읽는 동안 인코딩하려면 각 세그먼트는 3의 배수 여야합니다. 그렇지 않으면 복원 중에 혼란이 발생할 수 있습니다. 대부분의 사람들은 2의 승수를 사용하여 바이트 [1024]와 같은 배열을 정의하는 것을 좋아합니다. 3의 배수가 아니기 때문에 복원 중에 오류가 발생할 수 있습니다. 올바른 예는 다음과 같습니다.
바이트 [] BS = 새로운 바이트 [3*100] .... inputStream.read (bs) .. encode (bs) ...
문자열의 경우, 전체 인코딩은 일반적으로 분할 된 인코딩 오류를 피하기 위해 필요합니다.
물론, 세그먼트로 코딩하고 하나씩 복원하면 아무런 문제가 없습니다.
2) 문자열을 복원 할 때 원래 인코딩에 따라 문자열이 복원되는지 확인하십시오.
바이트 어레이에서 작동하기 때문에 Base64 인코딩 후 GBK 인코딩 된 중국어 및 UTF-8 코딩 된 중국어에 대해 결과가 다릅니다. 예를 들어, "우리"라는 단어가 gbk 코드 인 경우, base64로 변환 된 후 ztldxw ==가됩니다. UTF-8 코드 인 경우 Base64로 변환 된 후 5oir5lus가됩니다.
"우리"==》 getbytes ( "gbk") ==> base64입니다
따라서 인코딩이 Java를 변환하는 데 사용되는 요소와 인코딩이 JavaScript를 복원하는 데 사용되는 인코딩이 사용됩니다. Java와 JavaScript가 범용인지 확인하기 위해 유니 코드 인코딩을 사용합니다 (JavaScript를 UTF-8 및 GBK로 변환하는 것은 불편하므로 자체 유니 코드 인코딩을 사용합니다). 세부 사항은 다음과 같습니다.
서버 측 :
1) getBytes ( "유니 코드")를 사용하여 유니 코드 바이트 어레이로 변환하십시오.
2) Base64 문자열로 인코딩합니다
3) 고객에게 양도
고객:
1) Base64는 바이트 어레이로 디코딩됩니다
2) 유니 코드를 눌러 복원하십시오
코드는 다음과 같습니다 (관련 함수는 첨부 파일 참조) :
base64.encode (데이터, "유니 코드"); // Java End End Encoding
decode64 (데이터); // javaScript 디코딩
부착 1 : Base64 Java에서 인코딩
패키지 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) 'i', (byte) ', (byte)' ') 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) ', (byte)', (byte) ', (byte)', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte), (byte) ', (byte)', 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', (byte) ', (byte)', (byte) ', (byte)', (바이트) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) '+', (byte) '/'}; 개인 정적 최종 바이트 [] 디코딩 테이블; 정적 {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; 디코딩 테이블 [ '/'] = 63; } public static bd int realCount = data.length-offset; int modulus = realCount % 3; if (modulus == 0) {bytes = new Byte [(4 * realCount) / 3]; } else {bytes = 새로운 바이트 [4 * ((RealCount / 3) + 1)]; } int datalength = (data.length -modulus); int a1; int a2; int a3; for (int i = 오프셋, j = 0; i <datalength; i += 3, j += 4) {a1 = data [i] & 0xff; a2 = 데이터 [i + 1] & 0xff; a3 = 데이터 [i + 2] & 0xff; 바이트 [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; 스위치 (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 = 디코딩 테이블 [데이터 [i + 1]]; b3 = decodingtable [data [i + 2]]; B4 = 디코딩 테이블 [데이터 [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 (문자열 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 bd int bytescopied = 0; for (int i = 0; i <data.length; i ++) {if (isvalidbase64byte (data [i])) {temp [bytescopied ++] = data [i]; }} byte [] newdata = new Byte [bytescopied]; System.arrayCopy (Temp, 0, NewData, 0, 바이 테스 코피); NewData를 반환합니다. } private static string discardNonbase64chars (문자열 data) {StringBuffer sb = new StringBuffer (); int length = data.length (); for (int i = 0; i <length; i ++) {if (isvalidbase64byte ((byte)) (data.charat (i))) {sb.append (data.charat (i)); }} return sb.toString (); } private static boolean isvalidbase64byte (바이트 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 (문자열 데이터, 문자열 charset)는 예외 {// byte [] result = (data.getBytes ( "unicode")); if (data == null || data.length () == 0) 데이터를 반환합니다. int 오프셋 = 0; // getBytes ( "unicode")가 회전 한 후, 두 바이트 "Fe"가 전면 바이트에 추가됩니다 [] result = encode (data.getBytes (charset), 오프셋); StringBuffer sb = new StringBuffer (result.length); for (int i = 0; i <result.length; i ++) sb.append ((char) result [i]); 반환 sb.toString (); } public static string decode (문자열 데이터, 문자열 charset)는 예외를 던집니다. {if (data == null || data.length () == 0) 반환 데이터; 새 문자열을 반환합니다 (base64.decode (data), charset); } public static void main (String [] args)은 예외 {문자열 data = "우리"; 문자열 data1 = encode (data, "unicode"); 문자열 data2 = decode (data1, "unicode"); System.out.println (데이터); System.out.println (data1); System.out.println (data2); }} 부록 2 : base64 JavaScript의 인코딩
<html> <head> <title> Base64 인코딩/디코딩 </title> </head> <script type = "text/javaScript"> <! <! var keyst = "abcdefghijklmnop" + "qrstuvwxyzabcdef" + "ghijklmnopqrstuv" + "wxyz0123454689 "="; 함수 encode64 (입력) {input = unicodetobytes (입력); var output = ""; var chr1, chr2, chr3 = ""; var Enc1, Enc2, Enc3, Enc4 = ""; var i = 0; do {chr1 = 입력 [i ++]; chr2 = 입력 [i ++]; chr3 = 입력 [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 (입력) {var output = ""; var chr1, chr2, chr3 = ""; var Enc1, Enc2, Enc3, Enc4 = ""; var i = 0; // az, az, 0-9, +,/, 또는 = var base64test =/[^a-za-z0-9/ +/// =]/g; if (base64test.exec (input)) {alert ( "입력 텍스트에 유효하지 않은 Base64 문자가 있습니다 ./n" + "유효한 Base64 문자는 AZ, AZ, 0-9, ' +', '/'및 '='/n" + "디코딩에서 오류를 기대합니다."); } input = input.replace (/[^a-za-z0-9/+/// =]/g, ""); 출력 = 새로운 배열 (); do {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); } 함수 unicodetobytes (s) {var result = new array (); if (s == null || s == "") 반환 결과; result.push (255); // "fe"를 Head result.push (254)에 추가합니다. 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); } 반환 결과; } 함수 bytestounicode (bs) {var result = ""; var 오프셋 = 0; if (bs.length> = 2 && bs [0] == 255 && bs [1] == 254) 오프셋 = 2; // "fe"for (var i = 오프셋; i <bs.length; i+= 2) {var code = bs [i]+(bs [i+1] << 8); 결과+= String.FromCharCode (코드); } 반환 결과; } //-> </script> <body> <form name = "base64form"> base64에서 인코딩하려는 메시지를 입력하거나 텍스트 필드에 인코딩 된 텍스트를 텍스트 필드에 가져오고 인코딩 또는 디코딩, <br>를 선택하고 버튼을 클릭하고 <br> <textarea name = "thetext"cols = "40"rows = "6"> name = "encode"value = "encode to base64"onclick = "document.base64form.thetext.value = encode64 (document.base64form.thetext.value);"> <input type = "name ="decode "value ="decode " onclick = "document.base64form.thetext.value = decode64 (document.base64form.thetext.value);"> </form> </body> </html>읽어 주셔서 감사합니다. 도움이되기를 바랍니다. 이 사이트를 지원 해주셔서 감사합니다!