欢迎拍砖~
在数据二进制和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 10 private static final char PADDING_CHAR = '='; 11 static { 12 int index = 0; 13 for (int i = 0; i <= 25; i++) { 14 INDEX_MAP.put(index, (char) ((int) 'A' + i)); 15 index++; 16 } 17 18 for (int j = 0; j <= 25; j++) { 19 INDEX_MAP.put(index, (char) ((int) 'a' + j)); 20 index++; 21 } 22 23 for (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 33 public static 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); 41 return paddingEscapeString(escapeString); 42 } 43 44 private static String convertByteArray2BinaryString(byte[] bytes) { 45 46 StringBuilder binaryBuilder = new StringBuilder(); 47 for (byte b : bytes) { 48 binaryBuilder.append(convertByte2BinaryString(b)); 49 } 50 51 int paddingCount = binaryBuilder.length() % 6; 52 int totalCount = paddingCount > 0 ? binaryBuilder.length() / 6 + 1 53 : binaryBuilder.length() / 6; 54 int actualLength = 6 * totalCount; 55 56 //百分号后面的-号表示长度不够规定长度时,右填充。否则左填充。 57 return String.format("%-" + actualLength + "s", 58 binaryBuilder.toString()).replace(' ', '0'); 59 } 60 61 private static String escapeBinaryString(String binaryString) 62 throws Exception { 63 if (null == binaryString || binaryString.isEmpty() 64 || binaryString.length() % 6 != 0) { 65 System.out.println("error"); 66 throw new Exception("escape binary string error."); 67 } 68 69 StringBuilder escapeBuilder = new StringBuilder(); 70 for (int i = 0; i <= binaryString.length() - 1; i += 6) { 71 String escapeString = binaryString.substring(i, i + 6); 72 int index = Integer.parseInt(escapeString, 2); 73 escapeBuilder.append(INDEX_MAP.get(index)); 74 } 75 76 return escapeBuilder.toString(); 77 } 78 79 private static String paddingEscapeString(String escapeString) { 80 int paddingCount = escapeString.length() % 4; 81 int totalCount = paddingCount > 0 ? escapeString.length() / 4 + 1 82 : escapeString.length() / 4; 83 int actualCount = 4 * totalCount; 84 return String.format("%-" + actualCount + "s", escapeString).replace( 85 ' ', PADDING_CHAR); 86 } 87 88 private static String convertByte2BinaryString(byte b) { 89 90 /** 91 * 对于非负数,直接使用Integer.toBinaryString方法把它打印出来 92 */ 93 if (b >= 0) { 94 StringBuilder builder = new StringBuilder(); 95 builder.append(Integer.toBinaryString(b)); 96 return 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 */ 113 int value = b & 0xFF; 114 return Integer.toBinaryString(value); 115 } 116 } 117 118 }