| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.dubbo.common.io; |
| |
| import org.apache.dubbo.common.utils.IOUtils; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.security.MessageDigest; |
| import java.security.NoSuchAlgorithmException; |
| import java.util.Map; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.zip.DeflaterOutputStream; |
| import java.util.zip.InflaterInputStream; |
| |
| /** |
| * CodecUtils. |
| */ |
| |
| public class Bytes { |
| private static final String C64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; //default base64. |
| |
| private static final char[] BASE16 = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}, BASE64 = C64.toCharArray(); |
| |
| private static final int MASK4 = 0x0f, MASK6 = 0x3f, MASK8 = 0xff; |
| |
| private static final Map<Integer, byte[]> DECODE_TABLE_MAP = new ConcurrentHashMap<Integer, byte[]>(); |
| |
| private static ThreadLocal<MessageDigest> MD = new ThreadLocal<MessageDigest>(); |
| |
| private Bytes() { |
| } |
| |
| /** |
| * byte array copy. |
| * |
| * @param src src. |
| * @param length new length. |
| * @return new byte array. |
| */ |
| public static byte[] copyOf(byte[] src, int length) { |
| byte[] dest = new byte[length]; |
| System.arraycopy(src, 0, dest, 0, Math.min(src.length, length)); |
| return dest; |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @return byte[]. |
| */ |
| public static byte[] short2bytes(short v) { |
| byte[] ret = {0, 0}; |
| short2bytes(v, ret); |
| return ret; |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @param b byte array. |
| */ |
| public static void short2bytes(short v, byte[] b) { |
| short2bytes(v, b, 0); |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @param b byte array. |
| */ |
| public static void short2bytes(short v, byte[] b, int off) { |
| b[off + 1] = (byte) v; |
| b[off + 0] = (byte) (v >>> 8); |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @return byte[]. |
| */ |
| public static byte[] int2bytes(int v) { |
| byte[] ret = {0, 0, 0, 0}; |
| int2bytes(v, ret); |
| return ret; |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @param b byte array. |
| */ |
| public static void int2bytes(int v, byte[] b) { |
| int2bytes(v, b, 0); |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @param b byte array. |
| * @param off array offset. |
| */ |
| public static void int2bytes(int v, byte[] b, int off) { |
| b[off + 3] = (byte) v; |
| b[off + 2] = (byte) (v >>> 8); |
| b[off + 1] = (byte) (v >>> 16); |
| b[off + 0] = (byte) (v >>> 24); |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @return byte[]. |
| */ |
| public static byte[] float2bytes(float v) { |
| byte[] ret = {0, 0, 0, 0}; |
| float2bytes(v, ret); |
| return ret; |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @param b byte array. |
| */ |
| public static void float2bytes(float v, byte[] b) { |
| float2bytes(v, b, 0); |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @param b byte array. |
| * @param off array offset. |
| */ |
| public static void float2bytes(float v, byte[] b, int off) { |
| int i = Float.floatToIntBits(v); |
| b[off + 3] = (byte) i; |
| b[off + 2] = (byte) (i >>> 8); |
| b[off + 1] = (byte) (i >>> 16); |
| b[off + 0] = (byte) (i >>> 24); |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @return byte[]. |
| */ |
| public static byte[] long2bytes(long v) { |
| byte[] ret = {0, 0, 0, 0, 0, 0, 0, 0}; |
| long2bytes(v, ret); |
| return ret; |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @param b byte array. |
| */ |
| public static void long2bytes(long v, byte[] b) { |
| long2bytes(v, b, 0); |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @param b byte array. |
| * @param off array offset. |
| */ |
| public static void long2bytes(long v, byte[] b, int off) { |
| b[off + 7] = (byte) v; |
| b[off + 6] = (byte) (v >>> 8); |
| b[off + 5] = (byte) (v >>> 16); |
| b[off + 4] = (byte) (v >>> 24); |
| b[off + 3] = (byte) (v >>> 32); |
| b[off + 2] = (byte) (v >>> 40); |
| b[off + 1] = (byte) (v >>> 48); |
| b[off + 0] = (byte) (v >>> 56); |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @return byte[]. |
| */ |
| public static byte[] double2bytes(double v) { |
| byte[] ret = {0, 0, 0, 0, 0, 0, 0, 0}; |
| double2bytes(v, ret); |
| return ret; |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @param b byte array. |
| */ |
| public static void double2bytes(double v, byte[] b) { |
| double2bytes(v, b, 0); |
| } |
| |
| /** |
| * to byte array. |
| * |
| * @param v value. |
| * @param b byte array. |
| * @param off array offset. |
| */ |
| public static void double2bytes(double v, byte[] b, int off) { |
| long j = Double.doubleToLongBits(v); |
| b[off + 7] = (byte) j; |
| b[off + 6] = (byte) (j >>> 8); |
| b[off + 5] = (byte) (j >>> 16); |
| b[off + 4] = (byte) (j >>> 24); |
| b[off + 3] = (byte) (j >>> 32); |
| b[off + 2] = (byte) (j >>> 40); |
| b[off + 1] = (byte) (j >>> 48); |
| b[off + 0] = (byte) (j >>> 56); |
| } |
| |
| /** |
| * to short. |
| * |
| * @param b byte array. |
| * @return short. |
| */ |
| public static short bytes2short(byte[] b) { |
| return bytes2short(b, 0); |
| } |
| |
| /** |
| * to short. |
| * |
| * @param b byte array. |
| * @param off offset. |
| * @return short. |
| */ |
| public static short bytes2short(byte[] b, int off) { |
| return (short) (((b[off + 1] & 0xFF) << 0) + |
| ((b[off + 0]) << 8)); |
| } |
| |
| /** |
| * to int. |
| * |
| * @param b byte array. |
| * @return int. |
| */ |
| public static int bytes2int(byte[] b) { |
| return bytes2int(b, 0); |
| } |
| |
| /** |
| * to int. |
| * |
| * @param b byte array. |
| * @param off offset. |
| * @return int. |
| */ |
| public static int bytes2int(byte[] b, int off) { |
| return ((b[off + 3] & 0xFF) << 0) + |
| ((b[off + 2] & 0xFF) << 8) + |
| ((b[off + 1] & 0xFF) << 16) + |
| ((b[off + 0]) << 24); |
| } |
| |
| /** |
| * to int. |
| * |
| * @param b byte array. |
| * @return int. |
| */ |
| public static float bytes2float(byte[] b) { |
| return bytes2float(b, 0); |
| } |
| |
| /** |
| * to int. |
| * |
| * @param b byte array. |
| * @param off offset. |
| * @return int. |
| */ |
| public static float bytes2float(byte[] b, int off) { |
| int i = ((b[off + 3] & 0xFF) << 0) + |
| ((b[off + 2] & 0xFF) << 8) + |
| ((b[off + 1] & 0xFF) << 16) + |
| ((b[off + 0]) << 24); |
| return Float.intBitsToFloat(i); |
| } |
| |
| /** |
| * to long. |
| * |
| * @param b byte array. |
| * @return long. |
| */ |
| public static long bytes2long(byte[] b) { |
| return bytes2long(b, 0); |
| } |
| |
| /** |
| * to long. |
| * |
| * @param b byte array. |
| * @param off offset. |
| * @return long. |
| */ |
| public static long bytes2long(byte[] b, int off) { |
| return ((b[off + 7] & 0xFFL) << 0) + |
| ((b[off + 6] & 0xFFL) << 8) + |
| ((b[off + 5] & 0xFFL) << 16) + |
| ((b[off + 4] & 0xFFL) << 24) + |
| ((b[off + 3] & 0xFFL) << 32) + |
| ((b[off + 2] & 0xFFL) << 40) + |
| ((b[off + 1] & 0xFFL) << 48) + |
| (((long) b[off + 0]) << 56); |
| } |
| |
| /** |
| * to long. |
| * |
| * @param b byte array. |
| * @return double. |
| */ |
| public static double bytes2double(byte[] b) { |
| return bytes2double(b, 0); |
| } |
| |
| /** |
| * to long. |
| * |
| * @param b byte array. |
| * @param off offset. |
| * @return double. |
| */ |
| public static double bytes2double(byte[] b, int off) { |
| long j = ((b[off + 7] & 0xFFL) << 0) + |
| ((b[off + 6] & 0xFFL) << 8) + |
| ((b[off + 5] & 0xFFL) << 16) + |
| ((b[off + 4] & 0xFFL) << 24) + |
| ((b[off + 3] & 0xFFL) << 32) + |
| ((b[off + 2] & 0xFFL) << 40) + |
| ((b[off + 1] & 0xFFL) << 48) + |
| (((long) b[off + 0]) << 56); |
| return Double.longBitsToDouble(j); |
| } |
| |
| /** |
| * to hex string. |
| * |
| * @param bs byte array. |
| * @return hex string. |
| */ |
| public static String bytes2hex(byte[] bs) { |
| return bytes2hex(bs, 0, bs.length); |
| } |
| |
| /** |
| * to hex string. |
| * |
| * @param bs byte array. |
| * @param off offset. |
| * @param len length. |
| * @return hex string. |
| */ |
| public static String bytes2hex(byte[] bs, int off, int len) { |
| if (off < 0) { |
| throw new IndexOutOfBoundsException("bytes2hex: offset < 0, offset is " + off); |
| } |
| if (len < 0) { |
| throw new IndexOutOfBoundsException("bytes2hex: length < 0, length is " + len); |
| } |
| if (off + len > bs.length) { |
| throw new IndexOutOfBoundsException("bytes2hex: offset + length > array length."); |
| } |
| |
| byte b; |
| int r = off, w = 0; |
| char[] cs = new char[len * 2]; |
| for (int i = 0; i < len; i++) { |
| b = bs[r++]; |
| cs[w++] = BASE16[b >> 4 & MASK4]; |
| cs[w++] = BASE16[b & MASK4]; |
| } |
| return new String(cs); |
| } |
| |
| /** |
| * from hex string. |
| * |
| * @param str hex string. |
| * @return byte array. |
| */ |
| public static byte[] hex2bytes(String str) { |
| return hex2bytes(str, 0, str.length()); |
| } |
| |
| /** |
| * from hex string. |
| * |
| * @param str hex string. |
| * @param off offset. |
| * @param len length. |
| * @return byte array. |
| */ |
| public static byte[] hex2bytes(final String str, final int off, int len) { |
| if ((len & 1) == 1) { |
| throw new IllegalArgumentException("hex2bytes: ( len & 1 ) == 1."); |
| } |
| |
| if (off < 0) { |
| throw new IndexOutOfBoundsException("hex2bytes: offset < 0, offset is " + off); |
| } |
| if (len < 0) { |
| throw new IndexOutOfBoundsException("hex2bytes: length < 0, length is " + len); |
| } |
| if (off + len > str.length()) { |
| throw new IndexOutOfBoundsException("hex2bytes: offset + length > array length."); |
| } |
| |
| int num = len / 2, r = off, w = 0; |
| byte[] b = new byte[num]; |
| for (int i = 0; i < num; i++) { |
| b[w++] = (byte) (hex(str.charAt(r++)) << 4 | hex(str.charAt(r++))); |
| } |
| return b; |
| } |
| |
| /** |
| * to base64 string. |
| * |
| * @param b byte array. |
| * @return base64 string. |
| */ |
| public static String bytes2base64(byte[] b) { |
| return bytes2base64(b, 0, b.length, BASE64); |
| } |
| |
| /** |
| * to base64 string. |
| * |
| * @param b byte array. |
| * @return base64 string. |
| */ |
| public static String bytes2base64(byte[] b, int offset, int length) { |
| return bytes2base64(b, offset, length, BASE64); |
| } |
| |
| /** |
| * to base64 string. |
| * |
| * @param b byte array. |
| * @param code base64 code string(0-63 is base64 char,64 is pad char). |
| * @return base64 string. |
| */ |
| public static String bytes2base64(byte[] b, String code) { |
| return bytes2base64(b, 0, b.length, code); |
| } |
| |
| /** |
| * to base64 string. |
| * |
| * @param b byte array. |
| * @param code base64 code string(0-63 is base64 char,64 is pad char). |
| * @return base64 string. |
| */ |
| public static String bytes2base64(byte[] b, int offset, int length, String code) { |
| if (code.length() < 64) { |
| throw new IllegalArgumentException("Base64 code length < 64."); |
| } |
| |
| return bytes2base64(b, offset, length, code.toCharArray()); |
| } |
| |
| /** |
| * to base64 string. |
| * |
| * @param b byte array. |
| * @param code base64 code(0-63 is base64 char,64 is pad char). |
| * @return base64 string. |
| */ |
| public static String bytes2base64(byte[] b, char[] code) { |
| return bytes2base64(b, 0, b.length, code); |
| } |
| |
| /** |
| * to base64 string. |
| * |
| * @param bs byte array. |
| * @param off offset. |
| * @param len length. |
| * @param code base64 code(0-63 is base64 char,64 is pad char). |
| * @return base64 string. |
| */ |
| public static String bytes2base64(final byte[] bs, final int off, final int len, final char[] code) { |
| if (off < 0) { |
| throw new IndexOutOfBoundsException("bytes2base64: offset < 0, offset is " + off); |
| } |
| if (len < 0) { |
| throw new IndexOutOfBoundsException("bytes2base64: length < 0, length is " + len); |
| } |
| if (off + len > bs.length) { |
| throw new IndexOutOfBoundsException("bytes2base64: offset + length > array length."); |
| } |
| |
| if (code.length < 64) { |
| throw new IllegalArgumentException("Base64 code length < 64."); |
| } |
| |
| boolean pad = code.length > 64; // has pad char. |
| int num = len / 3, rem = len % 3, r = off, w = 0; |
| char[] cs = new char[num * 4 + (rem == 0 ? 0 : pad ? 4 : rem + 1)]; |
| |
| for (int i = 0; i < num; i++) { |
| int b1 = bs[r++] & MASK8, b2 = bs[r++] & MASK8, b3 = bs[r++] & MASK8; |
| |
| cs[w++] = code[b1 >> 2]; |
| cs[w++] = code[(b1 << 4) & MASK6 | (b2 >> 4)]; |
| cs[w++] = code[(b2 << 2) & MASK6 | (b3 >> 6)]; |
| cs[w++] = code[b3 & MASK6]; |
| } |
| |
| if (rem == 1) { |
| int b1 = bs[r++] & MASK8; |
| cs[w++] = code[b1 >> 2]; |
| cs[w++] = code[(b1 << 4) & MASK6]; |
| if (pad) { |
| cs[w++] = code[64]; |
| cs[w++] = code[64]; |
| } |
| } else if (rem == 2) { |
| int b1 = bs[r++] & MASK8, b2 = bs[r++] & MASK8; |
| cs[w++] = code[b1 >> 2]; |
| cs[w++] = code[(b1 << 4) & MASK6 | (b2 >> 4)]; |
| cs[w++] = code[(b2 << 2) & MASK6]; |
| if (pad) { |
| cs[w++] = code[64]; |
| } |
| } |
| return new String(cs); |
| } |
| |
| /** |
| * from base64 string. |
| * |
| * @param str base64 string. |
| * @return byte array. |
| */ |
| public static byte[] base642bytes(String str) { |
| return base642bytes(str, 0, str.length()); |
| } |
| |
| /** |
| * from base64 string. |
| * |
| * @param str base64 string. |
| * @param offset offset. |
| * @param length length. |
| * @return byte array. |
| */ |
| public static byte[] base642bytes(String str, int offset, int length) { |
| return base642bytes(str, offset, length, C64); |
| } |
| |
| /** |
| * from base64 string. |
| * |
| * @param str base64 string. |
| * @param code base64 code(0-63 is base64 char,64 is pad char). |
| * @return byte array. |
| */ |
| public static byte[] base642bytes(String str, String code) { |
| return base642bytes(str, 0, str.length(), code); |
| } |
| |
| /** |
| * from base64 string. |
| * |
| * @param str base64 string. |
| * @param off offset. |
| * @param len length. |
| * @param code base64 code(0-63 is base64 char,64 is pad char). |
| * @return byte array. |
| */ |
| public static byte[] base642bytes(final String str, final int off, final int len, final String code) { |
| if (off < 0) { |
| throw new IndexOutOfBoundsException("base642bytes: offset < 0, offset is " + off); |
| } |
| if (len < 0) { |
| throw new IndexOutOfBoundsException("base642bytes: length < 0, length is " + len); |
| } |
| if (len == 0) { |
| return new byte[0]; |
| } |
| if (off + len > str.length()) { |
| throw new IndexOutOfBoundsException("base642bytes: offset + length > string length."); |
| } |
| |
| if (code.length() < 64) { |
| throw new IllegalArgumentException("Base64 code length < 64."); |
| } |
| |
| int rem = len % 4; |
| if (rem == 1) { |
| throw new IllegalArgumentException("base642bytes: base64 string length % 4 == 1."); |
| } |
| |
| int num = len / 4, size = num * 3; |
| if (code.length() > 64) { |
| if (rem != 0) { |
| throw new IllegalArgumentException("base642bytes: base64 string length error."); |
| } |
| |
| char pc = code.charAt(64); |
| if (str.charAt(off + len - 2) == pc) { |
| size -= 2; |
| --num; |
| rem = 2; |
| } else if (str.charAt(off + len - 1) == pc) { |
| size--; |
| --num; |
| rem = 3; |
| } |
| } else { |
| if (rem == 2) { |
| size++; |
| } else if (rem == 3) { |
| size += 2; |
| } |
| } |
| |
| int r = off, w = 0; |
| byte[] b = new byte[size], t = decodeTable(code); |
| for (int i = 0; i < num; i++) { |
| int c1 = t[str.charAt(r++)], c2 = t[str.charAt(r++)]; |
| int c3 = t[str.charAt(r++)], c4 = t[str.charAt(r++)]; |
| |
| b[w++] = (byte) ((c1 << 2) | (c2 >> 4)); |
| b[w++] = (byte) ((c2 << 4) | (c3 >> 2)); |
| b[w++] = (byte) ((c3 << 6) | c4); |
| } |
| |
| if (rem == 2) { |
| int c1 = t[str.charAt(r++)], c2 = t[str.charAt(r++)]; |
| |
| b[w++] = (byte) ((c1 << 2) | (c2 >> 4)); |
| } else if (rem == 3) { |
| int c1 = t[str.charAt(r++)], c2 = t[str.charAt(r++)], c3 = t[str.charAt(r++)]; |
| |
| b[w++] = (byte) ((c1 << 2) | (c2 >> 4)); |
| b[w++] = (byte) ((c2 << 4) | (c3 >> 2)); |
| } |
| return b; |
| } |
| |
| /** |
| * from base64 string. |
| * |
| * @param str base64 string. |
| * @param code base64 code(0-63 is base64 char,64 is pad char). |
| * @return byte array. |
| */ |
| public static byte[] base642bytes(String str, char[] code) { |
| return base642bytes(str, 0, str.length(), code); |
| } |
| |
| /** |
| * from base64 string. |
| * |
| * @param str base64 string. |
| * @param off offset. |
| * @param len length. |
| * @param code base64 code(0-63 is base64 char,64 is pad char). |
| * @return byte array. |
| */ |
| public static byte[] base642bytes(final String str, final int off, final int len, final char[] code) { |
| if (off < 0) { |
| throw new IndexOutOfBoundsException("base642bytes: offset < 0, offset is " + off); |
| } |
| if (len < 0) { |
| throw new IndexOutOfBoundsException("base642bytes: length < 0, length is " + len); |
| } |
| if (len == 0) { |
| return new byte[0]; |
| } |
| if (off + len > str.length()) { |
| throw new IndexOutOfBoundsException("base642bytes: offset + length > string length."); |
| } |
| |
| if (code.length < 64) { |
| throw new IllegalArgumentException("Base64 code length < 64."); |
| } |
| |
| int rem = len % 4; |
| if (rem == 1) { |
| throw new IllegalArgumentException("base642bytes: base64 string length % 4 == 1."); |
| } |
| |
| int num = len / 4, size = num * 3; |
| if (code.length > 64) { |
| if (rem != 0) { |
| throw new IllegalArgumentException("base642bytes: base64 string length error."); |
| } |
| |
| char pc = code[64]; |
| if (str.charAt(off + len - 2) == pc) { |
| size -= 2; |
| --num; |
| rem = 2; |
| } else if (str.charAt(off + len - 1) == pc) { |
| size--; |
| --num; |
| rem = 3; |
| } |
| } else { |
| if (rem == 2) { |
| size++; |
| } else if (rem == 3) { |
| size += 2; |
| } |
| } |
| |
| int r = off, w = 0; |
| byte[] b = new byte[size]; |
| for (int i = 0; i < num; i++) { |
| int c1 = indexOf(code, str.charAt(r++)), c2 = indexOf(code, str.charAt(r++)); |
| int c3 = indexOf(code, str.charAt(r++)), c4 = indexOf(code, str.charAt(r++)); |
| |
| b[w++] = (byte) ((c1 << 2) | (c2 >> 4)); |
| b[w++] = (byte) ((c2 << 4) | (c3 >> 2)); |
| b[w++] = (byte) ((c3 << 6) | c4); |
| } |
| |
| if (rem == 2) { |
| int c1 = indexOf(code, str.charAt(r++)), c2 = indexOf(code, str.charAt(r++)); |
| |
| b[w++] = (byte) ((c1 << 2) | (c2 >> 4)); |
| } else if (rem == 3) { |
| int c1 = indexOf(code, str.charAt(r++)), c2 = indexOf(code, str.charAt(r++)), c3 = indexOf(code, str.charAt(r++)); |
| |
| b[w++] = (byte) ((c1 << 2) | (c2 >> 4)); |
| b[w++] = (byte) ((c2 << 4) | (c3 >> 2)); |
| } |
| return b; |
| } |
| |
| /** |
| * zip. |
| * |
| * @param bytes source. |
| * @return compressed byte array. |
| * @throws IOException |
| */ |
| public static byte[] zip(byte[] bytes) throws IOException { |
| UnsafeByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(); |
| OutputStream os = new DeflaterOutputStream(bos); |
| try { |
| os.write(bytes); |
| } finally { |
| os.close(); |
| bos.close(); |
| } |
| return bos.toByteArray(); |
| } |
| |
| /** |
| * unzip. |
| * |
| * @param bytes compressed byte array. |
| * @return byte uncompressed array. |
| * @throws IOException |
| */ |
| public static byte[] unzip(byte[] bytes) throws IOException { |
| UnsafeByteArrayInputStream bis = new UnsafeByteArrayInputStream(bytes); |
| UnsafeByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(); |
| InputStream is = new InflaterInputStream(bis); |
| try { |
| IOUtils.write(is, bos); |
| return bos.toByteArray(); |
| } finally { |
| is.close(); |
| bis.close(); |
| bos.close(); |
| } |
| } |
| |
| /** |
| * get md5. |
| * |
| * @param str input string. |
| * @return MD5 byte array. |
| */ |
| public static byte[] getMD5(String str) { |
| return getMD5(str.getBytes()); |
| } |
| |
| /** |
| * get md5. |
| * |
| * @param source byte array source. |
| * @return MD5 byte array. |
| */ |
| public static byte[] getMD5(byte[] source) { |
| MessageDigest md = getMessageDigest(); |
| return md.digest(source); |
| } |
| |
| /** |
| * get md5. |
| * |
| * @param file file source. |
| * @return MD5 byte array. |
| */ |
| public static byte[] getMD5(File file) throws IOException { |
| InputStream is = new FileInputStream(file); |
| try { |
| return getMD5(is); |
| } finally { |
| is.close(); |
| } |
| } |
| |
| /** |
| * get md5. |
| * |
| * @param is input stream. |
| * @return MD5 byte array. |
| */ |
| public static byte[] getMD5(InputStream is) throws IOException { |
| return getMD5(is, 1024 * 8); |
| } |
| |
| private static byte hex(char c) { |
| if (c <= '9') { |
| return (byte) (c - '0'); |
| } |
| if (c >= 'a' && c <= 'f') { |
| return (byte) (c - 'a' + 10); |
| } |
| if (c >= 'A' && c <= 'F') { |
| return (byte) (c - 'A' + 10); |
| } |
| throw new IllegalArgumentException("hex string format error [" + c + "]."); |
| } |
| |
| private static int indexOf(char[] cs, char c) { |
| for (int i = 0, len = cs.length; i < len; i++) { |
| if (cs[i] == c) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| private static byte[] decodeTable(String code) { |
| int hash = code.hashCode(); |
| byte[] ret = DECODE_TABLE_MAP.get(hash); |
| if (ret == null) { |
| if (code.length() < 64) { |
| throw new IllegalArgumentException("Base64 code length < 64."); |
| } |
| // create new decode table. |
| ret = new byte[128]; |
| for (int i = 0; i < 128; i++) // init table. |
| { |
| ret[i] = -1; |
| } |
| for (int i = 0; i < 64; i++) { |
| ret[code.charAt(i)] = (byte) i; |
| } |
| DECODE_TABLE_MAP.put(hash, ret); |
| } |
| return ret; |
| } |
| |
| private static byte[] getMD5(InputStream is, int bs) throws IOException { |
| MessageDigest md = getMessageDigest(); |
| byte[] buf = new byte[bs]; |
| while (is.available() > 0) { |
| int read, total = 0; |
| do { |
| if ((read = is.read(buf, total, bs - total)) <= 0) { |
| break; |
| } |
| total += read; |
| } |
| while (total < bs); |
| md.update(buf); |
| } |
| return md.digest(); |
| } |
| |
| private static MessageDigest getMessageDigest() { |
| MessageDigest ret = MD.get(); |
| if (ret == null) { |
| try { |
| ret = MessageDigest.getInstance("MD5"); |
| MD.set(ret); |
| } catch (NoSuchAlgorithmException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| return ret; |
| } |
| } |