<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    byte[]轉(zhuǎn)16進(jìn)制bug總結(jié)

    (一)問題

             項(xiàng)目中需要對(duì)文件做md5sum,分兩步走:1、對(duì)文件流的每個(gè)字節(jié)用md5實(shí)例進(jìn)行update,然后進(jìn)行digest2digest返回長(zhǎng)度為16byte數(shù)組,一般我們需要把byte數(shù)組轉(zhuǎn)成16進(jìn)制字符串(很多開源的md5加密算法如此實(shí)現(xiàn),真正的原因還不是很理解,可能是便于查看和傳輸)。具體的實(shí)現(xiàn)代碼如下:

             /**

        * 對(duì)文件進(jìn)行md5 sum操作

        * @param checkFile 要進(jìn)行做md5 sum的文件

        * @return

        */

        public static String md5sum(File checkFile){

           String md5sumResult = "";

           if(checkFile == null || (!checkFile.exists())){

               return md5sumResult;

           }

           MessageDigest digest = MessageDigest.getInstance("MD5");

           InputStream is = new FileInputStream(checkFile);

           byte[] buffer = new byte[8192];

           int read = 0;

           try {

               while( (read = is.read(buffer)) > 0) {

                  digest.update(buffer, 0, read);

               }

               byte[] md5sum = digest.digest();

               BigInteger bigInt = new BigInteger(1, md5sum);

               md5sumResult = bigInt.toString(16);

           }

           catch(IOException e) {

               throw new RuntimeException("Unable to process file for MD5", e);

           }

           finally {

               try {

                  is.close();

               }

               catch(IOException e) {

                  throw new RuntimeException("Unable to close input stream for MD5 calculation", e);

               }

           }

          

           return md5sumResult;

        }

     

        其中黃色背景色的轉(zhuǎn)換方式是有問題的。為什么用bigint轉(zhuǎn)16進(jìn)制會(huì)有問題呢,原因是bigint進(jìn)行16進(jìn)制轉(zhuǎn)換的時(shí)候第一個(gè)0被自動(dòng)去掉了.

       

     

    (二)正確解決方式

    那正確的方式是怎么樣的呢?下面有兩種不同的轉(zhuǎn)換方式,但是原理其實(shí)是一致的。

        第一種正確的方式(由王建提供):

        /**

        * 將字節(jié)數(shù)組轉(zhuǎn)換為16進(jìn)制字符串

        *

        * @param buffer

        * @return

        */

       public static String toHex(byte[] buffer) {

          StringBuffer sb = new StringBuffer(buffer.length * 2);

          for (int i = 0; i < buffer.length; i++) {

           sb.append(Character.forDigit((buffer[i] & 240) >> 4, 16));

           sb.append(Character.forDigit(buffer[i] & 15, 16));

          }

     

          return sb.toString();

       }

     

        第二種正確的方式:

        public static String bytes2HexString(byte[] b) {

           String ret = "";

           for (int i = 0; i < b.length; i++) {

               String hex = Integer.toHexString(b[i] & 0xFF);

               if (hex.length() == 1) {

                  hex = '0' + hex;

               }

               ret += hex;

           }

           return ret;

        }

     

    (三)問題分析

        Md5算法對(duì)任何長(zhǎng)度的字符串進(jìn)行編碼最后輸出是128位長(zhǎng)整數(shù),也就是長(zhǎng)度為16byte數(shù)組。我們項(xiàng)目調(diào)用的是jdk實(shí)現(xiàn)的md5算法,所以一般是沒問題的。

        接下來我們要處理的事情,分別循環(huán)數(shù)組,把每個(gè)字節(jié)轉(zhuǎn)換成2個(gè)16進(jìn)制字符,也就是說每4位轉(zhuǎn)成一個(gè)16進(jìn)制字符。

       

        上面正確的兩種方式也就是做了這樣的事情。

        第一種方式:

           Character.forDigit((buffer[i] & 240) >> 4, 16)把字節(jié)的高4位取出右移4位換算成int,然后通過forDigit轉(zhuǎn)換成16進(jìn)制字符

           Character.forDigit(buffer[i] & 15, 16)把字節(jié)的低4位取出換算成int,然后通過forDigit轉(zhuǎn)換成16進(jìn)制字符

       

        第二種方式:

           Integer.toHexString(b[i] & 0xFF)把整個(gè)字節(jié)轉(zhuǎn)成int,然后toHexString也就是做高4位和低4位的運(yùn)算。但是這個(gè)方法如果高四位是0的話就不輸出任何東西,

    所以在輸出的字符前加0即可。

           b[i] & 0xFF就是把byte轉(zhuǎn)成int,為什么用與oxff做與運(yùn)算,是因?yàn)槿绻?/span>b[i]是負(fù)數(shù)的話,從8位變成32位會(huì)補(bǔ)1,所以需要與0xff做與運(yùn)算,可以把前面的24位全部清零,又可以表示成原來的字節(jié)了。

       

     

    附:

    盡量使用開源提供的工具包,比如:

    org.apache.commons.codec.digest.DigestUtils.md5Hex(InputStream data)來對(duì)文件流進(jìn)行md5即可,更加方便,可靠。

    posted on 2012-01-10 14:39 yangpingyu 閱讀(8069) 評(píng)論(2)  編輯  收藏 所屬分類: java基礎(chǔ)

    評(píng)論

    # re: byte[]轉(zhuǎn)16進(jìn)制bug總結(jié) 2013-06-04 11:20 緣分情空

    解釋的很有道理  回復(fù)  更多評(píng)論   

    # re: byte[]轉(zhuǎn)16進(jìn)制bug總結(jié)[未登錄] 2013-07-10 16:51 Rain

    謝謝,正好解決問題  回復(fù)  更多評(píng)論   

    <2013年7月>
    30123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿

    隨筆分類

    隨筆檔案

    收藏夾

    linux

    產(chǎn)品交互

    分析,設(shè)計(jì),架構(gòu)

    安全

    技術(shù)牛人

    數(shù)據(jù)庫(kù)

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 一级毛片不卡片免费观看| 一级白嫩美女毛片免费| 免费无码中文字幕A级毛片| 国产偷窥女洗浴在线观看亚洲| 黄页网址大全免费观看12网站| 内射无码专区久久亚洲| 一级一看免费完整版毛片| 久久亚洲中文字幕精品一区四| AAAAA级少妇高潮大片免费看| 亚洲欧洲精品无码AV| 久草视频在线免费看| 久久亚洲AV成人无码电影| 97视频免费在线| 亚洲一区二区三区免费观看| 午夜老司机免费视频| 激情小说亚洲色图| 国产亚洲精品AA片在线观看不加载 | 全免费A级毛片免费看网站| 久久人午夜亚洲精品无码区| 亚洲国产精品成人一区| 国产免费拔擦拔擦8X高清在线人| 亚洲AV电影院在线观看| 国产精彩免费视频| 国产成人 亚洲欧洲| 亚洲国产成人片在线观看| 97性无码区免费| 久久精品国产亚洲AV未满十八| 亚洲一级特黄大片无码毛片 | 亚洲色成人WWW永久网站| 日本免费一区二区三区四区五六区| 亚洲校园春色另类激情| 亚洲人成色77777在线观看大 | 精品亚洲福利一区二区| 亚洲欧洲成人精品香蕉网| 国产片AV片永久免费观看| 精品无码专区亚洲| 亚洲va在线va天堂va不卡下载| 成人免费无码大片a毛片软件| 中文字幕看片在线a免费| 亚洲欧洲日本在线观看| 在线观看午夜亚洲一区|