首页 / JAVA / Base64的Java代码实现
Base64的Java代码实现
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Base64的Java代码实现,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含8386字,纯文字阅读大概需要12分钟。
内容图文
欢迎拍砖~
在数据二进制和byte互相转换的地方方法写得有点挫,不知道有没有更好的方法~
顺便复习了java的一些基础东西,如位操作,原码反码补码
可以在这篇blog里学习到详细的知识点:http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html
直接上代码吧,知识点在注释上
编码器:
1 package jdbc.pro.lin; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 public class MyBase64Encoder { 7 8 private static final Map<Integer, Character> INDEX_MAP = new HashMap<Integer, Character>(); 9 10privatestaticfinalchar PADDING_CHAR = ‘=‘; 11static { 12int index = 0; 13for (int i = 0; i <= 25; i++) { 14 INDEX_MAP.put(index, (char) ((int) ‘A‘ + i)); 15 index++; 16 } 17 18for (int j = 0; j <= 25; j++) { 19 INDEX_MAP.put(index, (char) ((int) ‘a‘ + j)); 20 index++; 21 } 22 23for (int k = 0; k <= 9; k++) { 24 INDEX_MAP.put(index, (char) ((int) ‘0‘ + k)); 25 index++; 26 } 27 28 INDEX_MAP.put(index, ‘+‘); 29 index++; 30 INDEX_MAP.put(index, ‘/‘); 31 } 32 33publicstatic String encode(byte[] bytes) throws Exception { 34/** 35 * 1.转成二进制的字符串(长度为6的倍数) 36 * 2.获取转义后的字符串 37 * 3.不是4的位数,填充=号 38*/ 39 String binaryString = convertByteArray2BinaryString(bytes); 40 String escapeString = escapeBinaryString(binaryString); 41return paddingEscapeString(escapeString); 42 } 43 44privatestatic String convertByteArray2BinaryString(byte[] bytes) { 45 46 StringBuilder binaryBuilder = new StringBuilder(); 47for (byte b : bytes) { 48 binaryBuilder.append(convertByte2BinaryString(b)); 49 } 50 51int paddingCount = binaryBuilder.length() % 6; 52int totalCount = paddingCount > 0 ? binaryBuilder.length() / 6 + 1 53 : binaryBuilder.length() / 6; 54int actualLength = 6 * totalCount; 55 56//百分号后面的-号表示长度不够规定长度时,右填充。否则左填充。 57return String.format("%-" + actualLength + "s", 58 binaryBuilder.toString()).replace(‘ ‘, ‘0‘); 59 } 60 61privatestatic String escapeBinaryString(String binaryString) 62throws Exception { 63if (null == binaryString || binaryString.isEmpty() 64 || binaryString.length() % 6 != 0) { 65 System.out.println("error"); 66thrownew Exception("escape binary string error."); 67 } 68 69 StringBuilder escapeBuilder = new StringBuilder(); 70for (int i = 0; i <= binaryString.length() - 1; i += 6) { 71 String escapeString = binaryString.substring(i, i + 6); 72int index = Integer.parseInt(escapeString, 2); 73 escapeBuilder.append(INDEX_MAP.get(index)); 74 } 75 76return escapeBuilder.toString(); 77 } 78 79privatestatic String paddingEscapeString(String escapeString) { 80int paddingCount = escapeString.length() % 4; 81int totalCount = paddingCount > 0 ? escapeString.length() / 4 + 1 82 : escapeString.length() / 4; 83int actualCount = 4 * totalCount; 84return String.format("%-" + actualCount + "s", escapeString).replace( 85 ‘ ‘, PADDING_CHAR); 86 } 87 88privatestatic String convertByte2BinaryString(byte b) { 89 90/** 91 * 对于非负数,直接使用Integer.toBinaryString方法把它打印出来 92*/ 93if (b >= 0) { 94 StringBuilder builder = new StringBuilder(); 95 builder.append(Integer.toBinaryString(b)); 96return String.format("%08d", Integer.parseInt(builder.toString())); 97 } else { 98/** 99 * 对于负数,要记住内存保存的是补码。 100 * 不能直接使用Byte.parseByte()方法。 101 * 因为这个方法最终调的是Integer.parseInt()方法,也就是说,负数如:10000001 102 * 对Integer.parseInt()来说并不会认为是负数,符号位1被当作数值位,是129 103 * 同时Byte.parseByte()方法里还对数值范围做了校验,符号位1,已超出范围,这样 104 * 会抛出异常。而Byte又没有提供toBinaryString的方法 105 * 为了保存byte的二进制值,可利用按位与的方法 106 * 例如有一个负数1000 1111,要把它以字符串保留出来,利用它与1111 1111的与操作, 107 * 再转成int类型。1000 1111 & 1111 1111 108 * 在内存中保存的就是 00000000 10001111,这时保存的是一个正整数。但我们不关心整数的正负, 109 * 因为我们的目的是要把这串字符串截取出来 110 * 再利用Integer.toBinaryString()打印出来。 111 * Integer.toBinaryString()对于正数,会将前面的零去掉,如上将打印出1000 1111,这就是我们要的结果。 112*/113int value = b & 0xFF; 114return Integer.toBinaryString(value); 115 } 116 } 117118 }
解码器:
1 package jdbc.pro.lin; 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 import java.util.Collections; 6 import java.util.HashMap; 7 import java.util.List; 8 import java.util.Map; 9 10 public class MyBase64Decoder { 11 private static final char PADDING_CHAR = ‘=‘; 12 13privatestaticfinal Map<Character, Integer> VALUE_MAP = new HashMap<Character, Integer>(); 14static { 15int index = 0; 16for (char i = ‘A‘; i <= ‘Z‘; i++, index++) { 17 VALUE_MAP.put(i, index); 18 } 19 20for (char j = ‘a‘; j <= ‘z‘; j++, index++) { 21 VALUE_MAP.put(j, index); 22 } 23 24for (char k = ‘0‘; k <= ‘9‘; k++, index++) { 25 VALUE_MAP.put(k, index); 26 } 27 28 VALUE_MAP.put(‘+‘, index); 29 index++; 30 VALUE_MAP.put(‘/‘, index); 31 } 32 33publicstaticbyte[] decode(String base64String) { 34 35if (null == base64String || base64String.isEmpty()) { 36returnnull; 37 } 38/** 39 * 1.去掉末尾拼凑的=符号 2.转成二进制 3.去掉末尾拼凑的0 4.截取每8位取数 40*/ 41 base64String = removePaddingChar(base64String); 42 String binaryString = getBinaryString(base64String); 43 binaryString = removePaddingNumber(binaryString); 44 45return convertBinaryString2Bytes(binaryString); 46 47 } 48 49/** 50 * 删除末尾拼凑的=符号 51 * 52 * @param base64String 53 * @return 54*/ 55privatestatic String removePaddingChar(String base64String) { 56int firstPaddingIndex = base64String.indexOf(PADDING_CHAR); 57return firstPaddingIndex >= 0 ? base64String.substring(0, 58 firstPaddingIndex) : base64String; 59 } 60 61/** 62 * 将base64字符串转成二进制字符串 63 * 64 * @param base64String 65 * @return 66*/ 67privatestatic String getBinaryString(String base64String) { 68 StringBuilder binaryBuilder = new StringBuilder(); 69for (char c : base64String.toCharArray()) { 70int value = VALUE_MAP.get(c); 71 binaryBuilder.append(String.format("%6s", 72 Integer.toBinaryString(value)).replace(" ", "0")); 73 } 74 75return binaryBuilder.toString(); 76 } 77 78/** 79 * 二进制字符串中的末尾有一些0是因为不足6的倍数而填充的,需要删除 80 * 81 * @param binaryString 82 * @return 83*/ 84privatestatic String removePaddingNumber(String binaryString) { 85int remainder = binaryString.length() % 8; 86 87 binaryString = binaryString.substring(0, binaryString.length() 88 - remainder); 89 90return binaryString; 91 } 92 93privatestaticbyte[] convertBinaryString2Bytes(String binaryString) { 94if (null == binaryString || binaryString.length() % 8 != 0) { 95 System.out.println("binary string not well formatted."); 96returnnull; 97 } 98int size = binaryString.length() / 8; 99byte[] bytes = newbyte[size]; 100int arrayIndex = 0; 101for (int i = 0; i <= binaryString.length() - 1; i += 8, arrayIndex++) { 102 String byteString = binaryString.substring(i, i + 8); 103/**104 * 非负数,直接使用Byte.parseByte()方法 105*/106if (byteString.startsWith("0")) { 107 bytes[arrayIndex] = Byte.parseByte(byteString, 2); 108 } else { 109/**110 * 10000000为-128是规定而来的。 -128并没有原码和反码表示。对-128的补码表示[10000000]补 111 * 算出来的原码是[0000 0000]原, 这是不正确的) 112*/113if (byteString.equals("1000000")) { 114 bytes[arrayIndex] = (byte) -128; 115continue; 116 } 117/**118 * 其他的负数,就要按照补码的规则来计算 即,原码取反+1=补码 那么,补码-1取反=原码 119 * 注意这都是真值部分的计算,符号位不能变 120*/121// 补码122 String twosComplement = byteString.substring(1); 123byte twoComplementValue = Byte.parseByte(twosComplement, 2); 124125// 反码126byte oneComplementValue = (byte) (twoComplementValue - 1); 127128/**129 * 这里用到的是0x7F而不是0xFF。因为oneComplementValue是0开头 130 * 若与1开头的异或,结果为1,而在int中该位不是符号位,会当成数值计算,造成数值错误。 131 * 因此,必须结果是0,即,两个0的异或。 132*/133// 真值 8位的计算134int trueValue = oneComplementValue ^ 0x7F; 135136 bytes[arrayIndex] = (byte) (trueValue * (-1)); 137138 } 139 } 140141return bytes; 142 } 143 }
测试代码:
1 package jdbc.pro.lin; 2 3 import oracle.net.aso.i; 4 5 import org.apache.commons.codec.binary.Base64; 6 7 public class TestMain { 8 public static void main(String[] args) throws Exception { 9byte[] binaryData = { 0, -2, -128, 127, 1, -1, 3, 4, 89, 45, 0 }; 10 String thirdPartyBase64String = Base64.encodeBase64String(binaryData); 11 String myBase64String = MyBase64Encoder.encode(binaryData); 12 System.out.println("ThirdParty encode: " + thirdPartyBase64String); 13 System.out.println("MyBase64 encode: " + myBase64String); 1415 System.out.print("ThirdParty decode: "); 16 printBytes(Base64.decodeBase64(thirdPartyBase64String.getBytes())); 1718 System.out.print("MyBase64 decode: "); 19 printBytes(MyBase64Decoder.decode(thirdPartyBase64String)); 2021 } 2223privatestaticvoid printBytes(byte[] bytes) { 24for (byte b : bytes) { 25 System.out.print(b); 26 System.out.print(" "); 27 } 28 System.out.println(""); 29 } 30 }
测试结果:
附Byte.parseByte()的反编译源码,确实是调用了Integer.parseInt()方法,导致符号位失效,对于10001111这样的数值认为是正数
原文:http://www.cnblogs.com/SirSmith/p/5011718.html
内容总结
以上是互联网集市为您收集整理的Base64的Java代码实现全部内容,希望文章能够帮你解决Base64的Java代码实现所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。