| /*
|
| * Copyright 1999-2011 Alibaba Group.
|
| *
|
| * Licensed 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 com.alibaba.dubbo.common.io; |
| |
| 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; |
| |
| import com.alibaba.dubbo.common.utils.IOUtils; |
| |
| /** |
| * CodecUtils. |
| * |
| * @author qian.lei |
| */ |
| |
| 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>(); |
| |
| /** |
| * 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( 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( 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; |
| else if( str.charAt(off+len-1) == pc ) |
| size--; |
| } |
| 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; |
| } |
| |
| private Bytes(){} |
| } |