日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java中String和byte[]间的转换浅析

發(fā)布時間:2025/3/19 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中String和byte[]间的转换浅析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Java語言中字符串類型和字節(jié)數(shù)組類型相互之間的轉(zhuǎn)換經(jīng)常發(fā)生,網(wǎng)上的分析及代碼也比較多,本文將分析總結常規(guī)的byte[]和String間的轉(zhuǎn)換以及十六進制String和byte[]間相互轉(zhuǎn)換的原理及實現(xiàn)。

1. String轉(zhuǎn)byte[]首先我們來分析一下常規(guī)的String轉(zhuǎn)byte[]的方法,代碼如下:public static byte[] strToByteArray(String str) {if (str == null) {return null;}byte[] byteArray = str.getBytes();return byteArray; }很簡單,就是調(diào)用String類的getBytes()方法。看JDK源碼可以發(fā)現(xiàn)該方法最終調(diào)用了String類如下的方法。/*** JDK source code*/ public byte[] getBytes(Charset charset) {String canonicalCharsetName = charset.name();if (canonicalCharsetName.equals("UTF-8")) {return Charsets.toUtf8Bytes(value, offset, count);} else if (canonicalCharsetName.equals("ISO-8859-1")) {return Charsets.toIsoLatin1Bytes(value, offset, count);} else if (canonicalCharsetName.equals("US-ASCII")) {return Charsets.toAsciiBytes(value, offset, count);} else if (canonicalCharsetName.equals("UTF-16BE")) {return Charsets.toBigEndianUtf16Bytes(value, offset, count);} else {CharBuffer chars = CharBuffer.wrap(this.value, this.offset, this.count);ByteBuffer buffer = charset.encode(chars.asReadOnlyBuffer());byte[] bytes = new byte[buffer.limit()];buffer.get(bytes);return bytes;} }上述代碼其實就是根據(jù)給定的編碼方式進行編碼。如果調(diào)用的是不帶參數(shù)的getBytes()方法,則使用默認的編碼方式,如下代碼所示:/*** JDK source code*/ private static Charset getDefaultCharset() {String encoding = System.getProperty("file.encoding", "UTF-8");try {return Charset.forName(encoding);} catch (UnsupportedCharsetException e) {return Charset.forName("UTF-8");} }關于默認的編碼方式,Java API是這樣說的:The default charset is determined during virtual-machine startup and typically depends upon the locale and charset of the underlying operating system.同樣,由上述代碼可以看出,默認編碼方式是由System類的"file.encoding"屬性決定的,經(jīng)過測試,在簡體中文Windows操作系統(tǒng)下,默認編碼方式為"GBK",在Android平臺上,默認編碼方式為"UTF-8"。 2. byte[]轉(zhuǎn)String接下來分析一下常規(guī)的byte[]轉(zhuǎn)為String的方法,代碼如下:public static String byteArrayToStr(byte[] byteArray) {if (byteArray == null) {return null;}String str = new String(byteArray);return str; }很簡單,就是String的構造方法之一。那我們分析Java中String的源碼,可以看出所有以byte[]為參數(shù)的構造方法最終都調(diào)用了如下代碼所示的構造方法。需要注意的是Java中String類的數(shù)據(jù)是Unicode類型的,因此上述的getBytes()方法是把Unicode類型轉(zhuǎn)化為指定編碼方式的byte數(shù)組;而這里的Charset為讀取該byte數(shù)組時所使用的編碼方式。/*** JDK source code*/ public String(byte[] data, int offset, int byteCount, Charset charset) {if ((offset | byteCount) < 0 || byteCount > data.length - offset) { throw failedBoundsCheck(data.length, offset, byteCount);}// We inline UTF-8, ISO-8859-1, and US-ASCII decoders for speed and because// 'count' and 'value' are final.String canonicalCharsetName = charset.name();if (canonicalCharsetName.equals("UTF-8")) {byte[] d = data;char[] v = new char[byteCount];int idx = offset;int last = offset + byteCount;int s = 0;outer:while (idx < last) {byte b0 = d[idx++];if ((b0 & 0x80) == 0) {// 0xxxxxxx// Range: U-00000000 - U-0000007Fint val = b0 & 0xff;v[s++] = (char) val;} else if (((b0 & 0xe0) == 0xc0) || ((b0 & 0xf0) == 0xe0) ||((b0 & 0xf8) == 0xf0) || ((b0 & 0xfc) == 0xf8) || ((b0 & 0xfe)== 0xfc)) {int utfCount = 1;if ((b0 & 0xf0) == 0xe0) utfCount = 2;else if ((b0 & 0xf8) == 0xf0) utfCount = 3;else if ((b0 & 0xfc) == 0xf8) utfCount = 4;else if ((b0 & 0xfe) == 0xfc) utfCount = 5;// 110xxxxx (10xxxxxx)+// Range: U-00000080 - U-000007FF (count == 1)// Range: U-00000800 - U-0000FFFF (count == 2)// Range: U-00010000 - U-001FFFFF (count == 3)// Range: U-00200000 - U-03FFFFFF (count == 4)// Range: U-04000000 - U-7FFFFFFF (count == 5)if (idx + utfCount > last) {v[s++] = REPLACEMENT_CHAR;continue;}// Extract usable bits from b0int val = b0 & (0x1f >> (utfCount - 1));for (int i = 0; i < utfCount; ++i) {byte b = d[idx++];if ((b & 0xc0) != 0x80) {v[s++] = REPLACEMENT_CHAR;idx--; // Put the input char backcontinue outer;}// Push new bits in from the right sideval <<= 6;val |= b & 0x3f;}// Note: Java allows overlong char// specifications To disallow, check that val// is greater than or equal to the minimum// value for each count://// count min value// ----- ----------// 1 0x80// 2 0x800// 3 0x10000// 4 0x200000// 5 0x4000000// Allow surrogate values (0xD800 - 0xDFFF) to// be specified using 3-byte UTF values onlyif ((utfCount != 2) && (val >= 0xD800) && (val <= 0xDFFF)) {v[s++] = REPLACEMENT_CHAR;continue;}// Reject chars greater than the Unicode maximum of U+10FFFF.if (val > 0x10FFFF) {v[s++] = REPLACEMENT_CHAR;continue;}// Encode chars from U+10000 up as surrogate pairsif (val < 0x10000) {v[s++] = (char) val;} else {int x = val & 0xffff;int u = (val >> 16) & 0x1f;int w = (u - 1) & 0xffff;int hi = 0xd800 | (w << 6) | (x >> 10);int lo = 0xdc00 | (x & 0x3ff);v[s++] = (char) hi;v[s++] = (char) lo;}} else {// Illegal values 0x8*, 0x9*, 0xa*, 0xb*, 0xfd-0xffv[s++] = REPLACEMENT_CHAR;}}if (s == byteCount) {// We guessed right, so we can use our temporary array as-is.this.offset = 0;this.value = v;this.count = s;} else {// Our temporary array was too big, so reallocate and copy.this.offset = 0;this.value = new char[s];this.count = s;System.arraycopy(v, 0, value, 0, s);}} else if (canonicalCharsetName.equals("ISO-8859-1")) {this.offset = 0;this.value = new char[byteCount];this.count = byteCount;Charsets.isoLatin1BytesToChars(data, offset, byteCount, value);} else if (canonicalCharsetName.equals("US-ASCII")) {this.offset = 0;this.value = new char[byteCount];this.count = byteCount;Charsets.asciiBytesToChars(data, offset, byteCount, value);} else {CharBuffer cb = charset.decode(ByteBuffer.wrap(data, offset, byteCount));this.offset = 0;this.count = cb.length();if (count > 0) {// We could use cb.array() directly, but that would mean we'd have to trust// the CharsetDecoder doesn't hang on to the CharBuffer and mutate it later,// which would break String's immutability guarantee. It would also tend to// mean that we'd be wasting memory because CharsetDecoder doesn't trim the// array. So we copy.this.value = new char[count];System.arraycopy(cb.array(), 0, value, 0, count);} else {this.value = EmptyArray.CHAR;}} }具體的轉(zhuǎn)換過程較為復雜,其實就是將byte數(shù)組的一個或多個元素按指定的Charset類型讀取并轉(zhuǎn)換為char類型(char本身就是以Unicode編碼方式存儲的),因為String類的核心是其內(nèi)部維護的char數(shù)組。因此有興趣的同學可以研究下各種編碼方式的編碼規(guī)則,然后才能看懂具體的轉(zhuǎn)換過程。 3. byte[]轉(zhuǎn)十六進制String所謂十六進制String,就是字符串里面的字符都是十六進制形式,因為一個byte是八位,可以用兩個十六進制位來表示,因此,byte數(shù)組中的每個元素可以轉(zhuǎn)換為兩個十六進制形式的char,所以最終的HexString的長度是byte數(shù)組長度的兩倍。閑話少說上代碼:public static String byteArrayToHexStr(byte[] byteArray) {if (byteArray == null){return null;}char[] hexArray = "0123456789ABCDEF".toCharArray();char[] hexChars = new char[byteArray.length * 2];for (int j = 0; j < byteArray.length; j++) {int v = byteArray[j] & 0xFF;hexChars[j * 2] = hexArray[v >>> 4];hexChars[j * 2 + 1] = hexArray[v & 0x0F];}return new String(hexChars); }上述代碼中,之所以要將byte數(shù)值和0xFF按位與,是因為我們?yōu)榱朔奖愫竺娴臒o符號移位操作(無符號右移運算符>>>只對32位和64位的值有意義),要將byte數(shù)據(jù)轉(zhuǎn)換為int類型,而如果直接轉(zhuǎn)換就會出現(xiàn)問題。因為java里面二進制是以補碼形式存在的,如果直接轉(zhuǎn)換,位擴展會產(chǎn)生問題,如值為-1的byte存儲的二進制形式為其補碼11111111,而轉(zhuǎn)換為int后為11111111111111111111111111111111,直接使用該值結果就不對了。而0xFF默認是int類型,即0x000000FF,一個byte值跟0xFF相與會先將那個byte值轉(zhuǎn)化成int類型運算,這樣,相與的結果中高的24個比特就總會被清0,后面的運算才會正確。 4. 十六進制String轉(zhuǎn)byte[]沒什么好說的了,就是byte[]轉(zhuǎn)十六進制String的逆過程,放代碼:public static byte[] hexStrToByteArray(String str) {if (str == null) {return null;}if (str.length() == 0) {return new byte[0];}byte[] byteArray = new byte[str.length() / 2];for (int i = 0; i < byteArray.length; i++){String subStr = str.substring(2 * i, 2 * i + 2);byteArray[i] = ((byte)Integer.parseInt(subStr, 16));}return byteArray; }文中所有代碼可以在個人github主頁查看和下載。

?


另,個人技術博客,同步更新,歡迎關注!轉(zhuǎn)載請注明出處!文中若有什么錯誤希望大家探討指正!

總結

以上是生活随笔為你收集整理的Java中String和byte[]间的转换浅析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲第一在线视频 | av手机网站| 午夜在线免费观看视频 | 国产在线精 | 国产成人精品亚洲 | 国产寡妇亲子伦一区二区三区四区 | 99re在线观看视频 | 欧美女人交配视频 | 中文字幕av专区 | 亚洲色图图片 | 91桃色视频在线观看 | 成人性生交大片免费 | 草女人视频| 人人av在线 | www.天堂在线 | 亚洲国产日韩一区二区 | 欧美在线三区 | 亚洲一区二区自偷自拍 | 性歌舞团一区二区三区视频 | 久久国产欧美日韩精品 | 邵氏电影《金莲外传2》免费观看 | 香蕉911| 麻豆911| 69性视频| 奇米成人影视 | 国产一级黄色电影 | 色av色| 性感美女一区二区三区 | 美女搞黄在线观看 | 麻豆免费观看视频 | 图书馆的女友动漫在线观看 | 韩国日本在线观看 | 日韩精品午夜 | 日本高清一区二区视频 | 国产91清纯白嫩初高中在线观看 | 亚洲黄色一区二区 | a天堂视频在线观看 | 国产ts三人妖大战直男 | 成人av地址| 精品国偷自产在线 | 欧美一级片在线 | 黄网在线免费观看 | 久久精品久久精品久久 | 99国产视频在线 | 狠狠干成人 | 九九热这里只有精品6 | 国产精品人人做人人爽 | a级片在线播放 | 青青草97| 二区在线视频 | 肥臀熟女一区二区三区 | 久久久免费高清视频 | 成人激情开心网 | 96久久精品 | 久久精品一区二区在线观看 | 狠狠躁18三区二区一区传媒剧情 | 少妇一级淫片免费视频 | 日韩网站在线播放 | 国产网站久久 | www.在线视频 | 亚洲欧美综合一区二区 | 神马午夜一区 | 国产理论片在线观看 | 久色综 | 国产亚洲精品久久久久久久 | 高h在线观看 | 视频一区在线观看 | 日本大乳美女 | aaa午夜| 无码人妻精品一区二区三区不卡 | 欧美精品四区 | 91精品啪 | 丰满岳跪趴高撅肥臀尤物在线观看 | 成人1区 | 精品免费一区 | 国产精品久久婷婷六月丁香 | 玖玖爱在线精品视频 | 免费色av| 国产精品久久久久久一区二区三区 | 欧美黄视频在线观看 | 国产免费看黄 | 激情999| 欧美精品色婷婷五月综合 | 国产女人叫床高潮大片免费 | 欧美亚洲成人网 | 国产大片中文字幕在线观看 | 国产成年妇视频 | av在线播放一区 | 窝窝午夜看片 | 欧美成人一区在线观看 | yellow免费在线观看 | 天堂91| 色噜| 3d动漫精品啪啪一区二区免费 | 久久在线视频 | 亚洲一区二区不卡在线观看 | 性生交大片免费看 | 亚洲一区欧美日韩 | 欧美日韩一级片在线观看 |