摘要:場景讀取一個大文本文件,并輸出到控制臺。示例代碼如下至少為,因為最大為字節,阻止讀取跨界數據恢復
場景:
讀取一個大文本文件,并輸出到控制臺。
在這里我們選擇使用nio進行讀取文本文件,在輸出的過程中,有些文件中英文都顯示正常,有些則偶爾出現中文亂碼,經思考發現,在 ByteBuffer.allocate 時分配空間,如果中英混合的文件中就會出現中文字符只讀取了一部分的問題,如果文本為等長編碼字符集的時候,可以根據編碼集 byte 長度進行 allocate ,例如 GBK 為2 byte ,所以我們 allocate 時未2的倍數即可,但像 UTF-8 這類變長的編碼字符集時則沒那么簡單了。
下面就是 UTF-8 的編碼方式
0xxxxxxx 110xxxxx 10xxxxxx 1110xxxx 10xxxxxx 10xxxxxx 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
對于 UTF-8 編碼中的任意字節 B ,如果 B 的第一位為0,則 B 為 ASCII 碼,并且 B 獨立的表示一個字符;
如果 B 的第一位為1,第二位為0,則B為一個非 ASCII 字符(該字符由多個字節表示)中的一個字節,并且不是字符的第一個字節編碼;
如果 B 的前兩位為1,第三位為0,則B為一個非 ASCII 字符(該字符由多個字節表示)中的第一個字節,并且該字符由兩個字節表示;
如果 B 的前三位為1,第四位為0,則B為一個非 ASCII 字符(該字符由多個字節表示)中的第一個字節,并且該字符由三個字節表示;
如果 B 的前四位為1,第五位為0,則B為一個非 ASCII 字符(該字符由多個字節表示)中的第一個字節,并且該字符由四個字節表示;
通過分析我們發現,在讀取中我們通過處理臨界值來解決 UTF-8 編碼字符讀取問題。
示例代碼如下:
RandomAccessFile rf = new RandomAccessFile("zh.txt", "rw"); FileChannel channel = rf.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(4); // 至少為4,因為UTF-8最大為4字節 while (channel.read(buffer) != -1) { byte b; int idx; out : for (idx = buffer.position()-1; idx >= 0; idx--) { b = buffer.get(idx); if ((b & 0xff) >> 7 == 0) { // 0xxxxxxx break; } if ((b& 0xff & 0xc0) == 0xc0) { // 11xxxxxx,110xxxxx、1110xxxx、11110xxx idx -= 1; break; } if ((b & 0xff & 0x80) == 0x80) { for (int i = 1; i < 4; i++) { b = buffer.get(idx - i); if ((b & 0xff & 0xc0) == 0xc0) { if ((b & 0xff) >> (5 + 1 - i) == 0xf >> (3 - i)) { break out; } else { idx = idx - 1 - i; break out; } } } } } buffer.flip(); int limit = buffer.limit(); buffer.limit(idx+1); // 阻止讀取跨界數據 System.out.println(Charset.forName("UTF-8").decode(buffer).toString()); buffer.limit(limit); // 恢復limit buffer.compact(); } channel.close(); rf.close();
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76787.html
摘要:的出現解決了這尷尬的問題,非阻塞模式下,通過,我們的線程只為已就緒的通道工作,不用盲目的重試了。注意要將注冊到,首先需要將設置為非阻塞模式,否則會拋異常。 showImg(https://segmentfault.com/img/remote/1460000017053374); 背景知識 同步、異步、阻塞、非阻塞 首先,這幾個概念非常容易搞混淆,但NIO中又有涉及,所以總結一下。 ...
摘要:的出現解決了這尷尬的問題,非阻塞模式下,通過,我們的線程只為已就緒的通道工作,不用盲目的重試了。注意要將注冊到,首先需要將設置為非阻塞模式,否則會拋異常。 同步、異步、阻塞、非阻塞首先,這幾個概念非常容易搞混淆,但NIO中又有涉及,所以總結一下[1]。 同步:API調用返回時調用者就知道操作的結果如何了(實際讀取/寫入了多少字節)。 異步:相對于同步,API調用返回時調用者不知道操作...
摘要:文章首發地址深入分析中的中文編碼問題背景編碼問題一直困擾著程序開發人員,尤其是在中更加明顯,因為是跨平臺的語言,在不同平臺的編碼之間的切換較多。 文章首發地址:深入分析 Java Web 中的中文編碼問題 背景: 編碼問題一直困擾著程序開發人員,尤其是在 Java 中更加明顯,因為 Java 是跨平臺的語言,在不同平臺的編碼之間的切換較多。接下來將介紹 Java 編碼問題出現的根本原...
摘要:的選擇器允許單個線程監視多個輸入通道。一旦執行的線程已經超過讀取代碼中的某個數據片段,該線程就不會在數據中向后移動通常不會。 1、引言 很多初涉網絡編程的程序員,在研究Java NIO(即異步IO)和經典IO(也就是常說的阻塞式IO)的API時,很快就會發現一個問題:我什么時候應該使用經典IO,什么時候應該使用NIO? 在本文中,將嘗試用簡明扼要的文字,闡明Java NIO和經典IO之...
摘要:緩沖區的限制不能為負,并且不能大于其容量。如果指向的位置超過限制,則拋出異常。使用臨時緩沖區執行低層次操作。臨時緩沖區對象離開作用域,并最終成為被回收的無用數據。 前天剛好看了點《UNIX網絡編程》,比較頭大。現在我來整理一下所學所得,并用于個人備忘。如果有不對,請批評。 想要解鎖更多新姿勢?請訪問https://blog.tengshe789.tech/ IO模型介紹 IO模型是什么...
閱讀 1039·2021-11-18 13:23
閱讀 746·2021-11-08 13:16
閱讀 856·2021-10-11 10:58
閱讀 3511·2021-09-22 15:26
閱讀 1732·2021-09-08 10:42
閱讀 1807·2021-09-04 16:45
閱讀 1734·2019-08-30 15:54
閱讀 2565·2019-08-30 13:45