2015-10-08 64 views
1

我想通過30個字節,以限制使用UTF-8字符集大小的字符串,我發現的溶液this如何截斷字符串包含由字節大小表情符號

所以我創建此

public static String truncateTextByByteLimit(String message, int byteLimit) { 
    String result = ""; 
    try { 
     Charset utf8Charset = Charset.forName("UTF-8"); 
     CharsetDecoder cd = utf8Charset.newDecoder(); 
     byte[] utf8Bytes = message.getBytes(utf8Charset); 
     System.out.println("check message: " + message + " /length: " +message.length()+ " //byte length: " + utf8Bytes.length + "/limit: " + byteLimit + " /codePoint: " +message.codePointCount(0, message.length())); 
     ByteBuffer bb = ByteBuffer.wrap(utf8Bytes, 0, byteLimit); 
     CharBuffer cb = CharBuffer.allocate(byteLimit); 
     // Ignore an incomplete character 
     cd.onMalformedInput(CodingErrorAction.IGNORE); 
     cd.decode(bb, cb, true); 
     cd.flush(cb); 
     result = new String(cb.array(), 0, cb.position()); 
     if (result.length()<=0) { 
      return truncateTextByByteLimit(message, (byteLimit+1)); 
     } else { 
      return result; 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 

     return message; 
    } 
} 
的方法基

問題是雖然我測試字符串與表情符號等如下: System.out.println(truncateTextByByteLimit("let's \uD83D\uDE09", 30));

它顯示錯誤

java.lang.IndexOutOfBoundsException 
at java.nio.ByteBuffer.wrap(ByteBuffer.java:371) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:606) 
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) 

和我的調試消息顯示 check message: let's /length: 8 //byte length: 10/limit: 30 /codePoint: 7

當我用同樣的消息測試byteLimit小於或等於10,它的工作原理沒有錯誤...

所以我不明白爲什麼它顯示java.lang.IndexOutOfBoundsException

回答

1

ByteBuffer#wraphas a limitation什麼是允許的長度。

要使用的子陣列的長度;必須是非負數且不得大於array.length - offset。新緩衝區的限制將被設置爲offset + length

爲了彌補這一點,你需要採取的兩種長度的較小的 - 無論是這將是你絕對最大值byteLimit,或者這將是utf8Bytes數組的大小。

ByteBuffer.wrap(utf8Bytes, 0, Math.min(utf8Bytes.length, byteLimit));