我的Java开发学习之旅------Base64的编码思想以及Java实现
Base64是一種用64個字符來表示任意二進制數據的方法。
用記事本打開exe、jpg、pdf這些文件時,我們都會看到一大堆亂碼,因為二進制文件包含很多無法顯示和打印的字符,所以,如果要讓記事本這樣的文本處理軟件能處理二進制數據,就需要一個二進制到字符串的轉換方法。Base64是一種最常見的二進制編碼方法。
一、編碼規則
所謂Base64,就是說選出64個字符----小寫字母a-z、大寫字母A-Z、數字0-9、符號"+"、"/"(再加上作為墊字的"=",實際上是65個字符)----作為一個基本字符集。然后,其他所有符號都轉換成這個字符集中的字符。
具體來說,轉換方式可以分為四步。
- 第一步,將每三個字節作為一組,一共是24個二進制位。
- 第二步,將這24個二進制位分為四組,每個組有6個二進制位。
- 第三步,在每組前面加兩個00,擴展成32個二進制位,即四個字節。
- 第四步,根據下表,得到擴展后的每個字節的對應符號,這就是Base64的編碼值。
注:BASE64字符表:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
| | Value Char | Value Char | Value Char|||||
| 0 | A | 16 | Q | 32 | g | 48 | w |
| 1 | B | 17 | R | 33 | h | 49 | x |
| 2 | C | 18 | S | 34 | i | 50 | y |
| 3 | D | 19 | T | 35 | j | 51 | z |
| 4 | E | 20 | U | 36 | k | 52 | 0 |
| 5 | F | 21 | V | 37 | l | 53 | 1 |
| 6 | G | 22 | W | 38 | m | 54 | 2 |
| 7 | H | 23 | X | 39 | n | 55 | 3 |
| 8 | I | 24 | Y | 40 | o | 56 | 4 |
| 9 | J | 25 | Z | 41 | p | 57 | 5 |
| 10 | K | 26 | a | 42 | q | 58 | 6 |
| 11 | L | 27 | b | 43 | r | 59 | 7 |
| 12 | M | 28 | c | 44 | s | 60 | 8 |
| 13 | N | 29 | d | 45 | t | 61 | 9 |
| 14 | O | 30 | e | 46 | u | 62 | + |
| 15 | P | 31 | f | 47 | v | 63 | / |
因為,Base64將三個字節轉化成四個字節,所以Base64編碼后的文本,會比原文本大出三分之一左右。
舉一個具體的實例,演示英語單詞Man如何轉成Base64編碼。
| M | a | n | |||||||||||||||||||||
| 77 | 97 | 110 | |||||||||||||||||||||
| 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 |
| 19 | 22 | 5 | 46 | ||||||||||||||||||||
| T | W | F | u | ||||||||||||||||||||
- 第一步,"M"、"a"、"n"的ASCII值分別是77、97、110,對應的二進制值是01001101、01100001、01101110,將它們連成一個24位的二進制字符串010011010110000101101110。
- 第二步,將這個24位的二進制字符串分成4組,每組6個二進制位:010011、010110、000101、101110。
- 第三步,在每組前面加兩個00,擴展成32個二進制位,即四個字節:00010011、00010110、00000101、00101110。它們的十進制值分別是19、22、5、46。
- 第四步,根據上表,得到每個值對應Base64編碼,即T、W、F、u。
因此,Man的Base64編碼就是TWFu。
我們看看另外不是剛好是3個字節的情況!?
| A | | | |||||||||||||||||||||
| 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | | | | | | | | | | | | | | | | |
| 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | | | | | | | | | | | | |
| Q | Q | = | = | ||||||||||||||||||||
| B | C | | |||||||||||||||||||||
| 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | | | x | x | x | x | x | x |
| 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | x | x | x | x | x | x |
| Q | k | M | ?= | ||||||||||||||||||||
因此,A的Base64編碼就是QQ==,BC的Base64編碼就是QkM=
?
二、解碼規則
??????解碼過程就是把4個字節再還原成3個字節再根據不同的數據形式把字節數組重新整理成數據。
三、Java實現Base64
public class Base64Utils {/*** 將一個字節數組轉換成base64的字符數組* * @param data* 字節數組* @return base64字符數組*/private static char[] encode(byte[] data) {char[] out = new char[((data.length + 2) / 3) * 4];for (int i = 0, index = 0; i < data.length; i += 3, index += 4) {boolean quad = false;boolean trip = false;int val = (0xFF & (int) data[i]);val <<= 8;if ((i + 1) < data.length) {val |= (0xFF & (int) data[i + 1]);trip = true;}val <<= 8;if ((i + 2) < data.length) {val |= (0xFF & (int) data[i + 2]);quad = true;}out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];val >>= 6;out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];val >>= 6;out[index + 1] = alphabet[val & 0x3F];val >>= 6;out[index + 0] = alphabet[val & 0x3F];}return out;}/*** 將一個base64字符數組解碼成一個字節數組* * @param data* base64字符數組* @return 返回解碼以后的字節數組*/private static byte[] decode(char[] data) {int len = ((data.length + 3) / 4) * 3;if (data.length > 0 && data[data.length - 1] == '=')--len;if (data.length > 1 && data[data.length - 2] == '=')--len;byte[] out = new byte[len];int shift = 0;int accum = 0;int index = 0;for (int ix = 0; ix < data.length; ix++) {int value = codes[data[ix] & 0xFF];if (value >= 0) {accum <<= 6;shift += 6;accum |= value;if (shift >= 8) {shift -= 8;out[index++] = (byte) ((accum >> shift) & 0xff);}}}if (index != out.length)throw new Error("miscalculated data length!");return out;}/*** base64字符集 0..63*/static private char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray();/*** 初始化base64字符集表*/static private byte[] codes = new byte[256];static {for (int i = 0; i < 256; i++)codes[i] = -1;for (int i = 'A'; i <= 'Z'; i++)codes[i] = (byte) (i - 'A');for (int i = 'a'; i <= 'z'; i++)codes[i] = (byte) (26 + i - 'a');for (int i = '0'; i <= '9'; i++)codes[i] = (byte) (52 + i - '0');codes['+'] = 62;codes['/'] = 63;}/*** 將字符串通過base64轉碼* @param str 要轉碼的字符串* @return 返回轉碼后的字符串*/public static String strToBase64Str(String str){return new String(encode(str.getBytes()));}/*** 將base64碼反轉成字符串* @param base64Str base64碼* @return 返回轉碼后的字符串*/public static String base64StrToStr(String base64Str){char[] dataArr = new char[base64Str.length()];base64Str.getChars(0, base64Str.length(), dataArr, 0);return new String(decode(dataArr));}/*** 將字節數組通過base64轉碼* @param byteArray 字節數組* @return 返回轉碼后的字符串*/public static String byteArrayToBase64Str(byte byteArray[]){return new String(encode(byteArray));}/*** 將base64碼轉換成字節數組* @param base64Str base64碼* @return 返回轉換后的字節數組*/public static byte[] base64StrToByteArray(String base64Str){char[] dataArr = new char[base64Str.length()];base64Str.getChars(0, base64Str.length(), dataArr, 0);return decode(dataArr);}/*** @param args* @throws UnsupportedEncodingException */public static void main(String[] args) throws Exception {String strSrc = "Man";String strOut = Base64Utils.strToBase64Str(strSrc);System.out.println("源字符串 "+strSrc+" 的Base64碼是:"+strOut);String strOut2 = Base64Utils.base64StrToStr(strOut);System.out.println("Base64碼 "+strOut+" 的對應源字符串為:"+strOut2); byte[] inByteArray={'a','b','c'};String base64Str=Base64Utils.byteArrayToBase64Str(inByteArray);StringBuilder sb=new StringBuilder();sb.append('[');for (int i = 0; i < inByteArray.length; i++) {sb.append(inByteArray[i]+" ");}sb.append(']');System.out.println("字節數組:"+sb+" 的Base64碼是:"+base64Str);byte[] outByteArray=Base64Utils.base64StrToByteArray(base64Str);StringBuilder sb2=new StringBuilder();sb2.append('[');for (int i = 0; i < outByteArray.length; i++) {sb2.append(outByteArray[i]+" ");}sb2.append(']');System.out.println("Base64碼為"+base64Str+" 的對應字節數組為:"+sb2);} }
運行效果如下:
源字符串 Man 的Base64碼是:TWFu Base64碼 TWFu 的對應源字符串為:Man 字節數組:[97 98 99 ] 的Base64碼是:YWJj Base64碼為YWJj 的對應字節數組為:[97 98 99 ]?
??????????????????????????? ====================================================================================
? 作者:歐陽鵬? 歡迎轉載,與人分享是進步的源泉!
? 轉載請保留原文地址:http://blog.csdn.net/ouyang_peng
====================================================================================
轉載于:https://www.cnblogs.com/ouyangpeng/p/8537980.html
總結
以上是生活随笔為你收集整理的我的Java开发学习之旅------Base64的编码思想以及Java实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STM8Lpwm
- 下一篇: 我的Java开发学习之旅------gt