你可能也會(huì)掉進(jìn)這個(gè)簡(jiǎn)單的 String 的坑
/**
?*?@param?status
?*?@param?result,?the?size?should?less?than?1000?bytes
?*?@throws?Exception
?*/
public?XXResult(boolean?status,?String?result)?{
????if?(result?!=?null?&&?result.getBytes().length?>?1000)?{
????????throw?new?RuntimeException("result?size?more?than?1000?bytes!");
????}
??......
}
result?也不是什么關(guān)鍵性的東西,你有限制,我直接 trim 一下不就行了?
解決方案
trim?方法,支持傳不同參數(shù)按需 trim,代碼如下:/**
?*?將給定的字符串?trim?到指定大小
?*?@param?input
?*?@param?trimTo?需要?trim?的字節(jié)長(zhǎng)度
?*?@return?trim?后的?String
?*/
public?static?String?trimAsByte(String?input,?int?trimTo)?{
????if?(Objects.isNull(input))?{
????????return?null;
????}
????byte[]?bytes?=?input.getBytes();
????if?(bytes.length?>?trimTo)?{
????????byte?[]?subArray?=?Arrays.copyOfRange(bytes,?0,?trimTo);
????????return?new?String(subArray);
????}
????return?input;
}
trimAsByte?方法,一頓操作連忙上線,一切完美~
災(zāi)難現(xiàn)場(chǎng)


trimAsByte("WeChat:tangleithu",?8)
WeChat:tangleithu?太長(zhǎng)了,只 trim 到剩下 8 個(gè)字節(jié),對(duì)應(yīng)的字節(jié)數(shù)組是從?[87,101,67,104,97,116,58,116,97,110,103,108,101,105,116,104,117]?變?yōu)榱?[87,101,67,104,97,116,58,116],字符串變成了?WeChat:t?,結(jié)果正確。trimAsByte("程序猿石頭",?8)

程序猿石頭,3 個(gè)字節(jié)一個(gè)漢字,一共 15 個(gè)字節(jié)?[-25,-88,-117,-27,-70,-113,-25,-116,-65,-25,-97,-77,-27,-92,-76],trim 到 8 位,剩下前 8 位?[-25,-88,-117,-27,-70,-113,-25,-116]?也正確。再?new String,又變成3 個(gè) “中文” 了,雖然第 3 個(gè)“中文”,咱也不認(rèn)識(shí),咱也不敢問(wèn)到底讀啥,總之再轉(zhuǎn)換成字節(jié)數(shù)組,長(zhǎng)度多了 1 個(gè),變成 9 了。
?
不禁要問(wèn),為什么?
/**
?*?Constructs?a?new?{@code?String}?by?decoding?the?specified?array?of?bytes
?*?using?the?platform's?default?charset.??The?length?of?the?new?{@code
?*?String}?is?a?function?of?the?charset,?and?hence?may?not?be?equal?to?the
?*?length?of?the?byte?array.
?*
?*??The?behavior?of?this?constructor?when?the?given?bytes?are?not?valid
?*?in?the?default?charset?is?unspecified.??The?{@link
?*?java.nio.charset.CharsetDecoder}?class?should?be?used?when?more?control
?*?over?the?decoding?process?is?required.
?*
?*?@param??bytes
?*?????????The?bytes?to?be?decoded?into?characters
?*
?*?@since??JDK1.1
?*/
public?String(byte?bytes[])?{
????//this(bytes,?0,?bytes.length);
????checkBounds(bytes,?offset,?length);
????this.value?=?StringCoding.decode(bytes,?offset,?length);
}

[-25,-88,-117,-27,-70,-113,-25,-116,-65,-25,-97,-77,-27,-92,-76]?仍然用這串字節(jié)數(shù)組來(lái)實(shí)驗(yàn),這串字節(jié)數(shù)組,如果用 “UTF-8” 編碼去解釋,那么其想表達(dá)的語(yǔ)義就是中文“程序猿石頭”,從上文標(biāo)注的 1,2,3 中可以看出來(lái),沒(méi)有寫(xiě)即用了系統(tǒng)中的默認(rèn)編碼“UTF-8”。??是不是似曾相識(shí);??其實(shí)是 UNICODE 編碼方式中的一個(gè)特殊的字符,也就是 0xFFFD(65535),其實(shí)是一個(gè)占位符(REPLACEMENT CHARACTER),用來(lái)表達(dá)未知的、沒(méi)辦法表達(dá)的東東。上文中在進(jìn)行編碼轉(zhuǎn)換過(guò)程中,出現(xiàn)了這個(gè)玩意,其實(shí)也就是沒(méi)辦法準(zhǔn)確表達(dá)含義,會(huì)被替換成這個(gè)東西,因此信息也就丟失了。你可以試試前面的例子,比如把前 8 個(gè)字節(jié)中的最后一兩個(gè)字節(jié)隨便改改,都是一樣的。
?
總結(jié)
trim?方法,其實(shí)很容易寫(xiě)個(gè)單元測(cè)試就能盡早發(fā)現(xiàn)有問(wèn)題;有道無(wú)術(shù),術(shù)可成;有術(shù)無(wú)道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號(hào)
好文章,我在看??
評(píng)論
圖片
表情
