成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java NIO下使用ByteBuffer讀取文本時解決UTF-8概率性中文亂碼的問題

SolomonXie / 3910人閱讀

摘要:場景讀取一個大文本文件,并輸出到控制臺。示例代碼如下至少為,因為最大為字節(jié),阻止讀取跨界數(shù)據(jù)恢復(fù)

場景:
讀取一個大文本文件,并輸出到控制臺。

在這里我們選擇使用nio進行讀取文本文件,在輸出的過程中,有些文件中英文都顯示正常,有些則偶爾出現(xiàn)中文亂碼,經(jīng)思考發(fā)現(xiàn),在 ByteBuffer.allocate 時分配空間,如果中英混合的文件中就會出現(xiàn)中文字符只讀取了一部分的問題,如果文本為等長編碼字符集的時候,可以根據(jù)編碼集 byte 長度進行 allocate ,例如 GBK 為2 byte ,所以我們 allocate 時未2的倍數(shù)即可,但像 UTF-8 這類變長的編碼字符集時則沒那么簡單了。

下面就是 UTF-8 的編碼方式

0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

對于 UTF-8 編碼中的任意字節(jié) B ,如果 B 的第一位為0,則 B 為 ASCII 碼,并且 B 獨立的表示一個字符;

如果 B 的第一位為1,第二位為0,則B為一個非 ASCII 字符(該字符由多個字節(jié)表示)中的一個字節(jié),并且不是字符的第一個字節(jié)編碼;

如果 B 的前兩位為1,第三位為0,則B為一個非 ASCII 字符(該字符由多個字節(jié)表示)中的第一個字節(jié),并且該字符由兩個字節(jié)表示;

如果 B 的前三位為1,第四位為0,則B為一個非 ASCII 字符(該字符由多個字節(jié)表示)中的第一個字節(jié),并且該字符由三個字節(jié)表示;

如果 B 的前四位為1,第五位為0,則B為一個非 ASCII 字符(該字符由多個字節(jié)表示)中的第一個字節(jié),并且該字符由四個字節(jié)表示;

通過分析我們發(fā)現(xiàn),在讀取中我們通過處理臨界值來解決 UTF-8 編碼字符讀取問題。

示例代碼如下:
RandomAccessFile rf = new RandomAccessFile("zh.txt", "rw");
FileChannel channel = rf.getChannel();

ByteBuffer buffer = ByteBuffer.allocate(4); // 至少為4,因為UTF-8最大為4字節(jié)

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);  // 阻止讀取跨界數(shù)據(jù)
    System.out.println(Charset.forName("UTF-8").decode(buffer).toString());

    buffer.limit(limit);  // 恢復(fù)limit
    buffer.compact();
}

channel.close();
rf.close();

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/76787.html

相關(guān)文章

  • 一文理解:Java NIO 核心組件

    摘要:的出現(xiàn)解決了這尷尬的問題,非阻塞模式下,通過,我們的線程只為已就緒的通道工作,不用盲目的重試了。注意要將注冊到,首先需要將設(shè)置為非阻塞模式,否則會拋異常。 showImg(https://segmentfault.com/img/remote/1460000017053374); 背景知識 同步、異步、阻塞、非阻塞 首先,這幾個概念非常容易搞混淆,但NIO中又有涉及,所以總結(jié)一下。 ...

    Coding01 評論0 收藏0
  • 一文讓你徹底理解 Java NIO 核心組件

    摘要:的出現(xiàn)解決了這尷尬的問題,非阻塞模式下,通過,我們的線程只為已就緒的通道工作,不用盲目的重試了。注意要將注冊到,首先需要將設(shè)置為非阻塞模式,否則會拋異常。 同步、異步、阻塞、非阻塞首先,這幾個概念非常容易搞混淆,但NIO中又有涉及,所以總結(jié)一下[1]。 同步:API調(diào)用返回時調(diào)用者就知道操作的結(jié)果如何了(實際讀取/寫入了多少字節(jié))。 異步:相對于同步,API調(diào)用返回時調(diào)用者不知道操作...

    guyan0319 評論0 收藏0
  • 深入分析 Java Web 中中文編碼問題

    摘要:文章首發(fā)地址深入分析中的中文編碼問題背景編碼問題一直困擾著程序開發(fā)人員,尤其是在中更加明顯,因為是跨平臺的語言,在不同平臺的編碼之間的切換較多。 文章首發(fā)地址:深入分析 Java Web 中的中文編碼問題 背景: 編碼問題一直困擾著程序開發(fā)人員,尤其是在 Java 中更加明顯,因為 Java 是跨平臺的語言,在不同平臺的編碼之間的切換較多。接下來將介紹 Java 編碼問題出現(xiàn)的根本原...

    jsyzchen 評論0 收藏0
  • 少啰嗦!一分鐘帶你讀懂JavaNIO和經(jīng)典IO區(qū)別

    摘要:的選擇器允許單個線程監(jiān)視多個輸入通道。一旦執(zhí)行的線程已經(jīng)超過讀取代碼中的某個數(shù)據(jù)片段,該線程就不會在數(shù)據(jù)中向后移動通常不會。 1、引言 很多初涉網(wǎng)絡(luò)編程的程序員,在研究Java NIO(即異步IO)和經(jīng)典IO(也就是常說的阻塞式IO)的API時,很快就會發(fā)現(xiàn)一個問題:我什么時候應(yīng)該使用經(jīng)典IO,什么時候應(yīng)該使用NIO? 在本文中,將嘗試用簡明扼要的文字,闡明Java NIO和經(jīng)典IO之...

    Meils 評論0 收藏0
  • 如何用Java與python代碼解釋IO模型

    摘要:緩沖區(qū)的限制不能為負(fù),并且不能大于其容量。如果指向的位置超過限制,則拋出異常。使用臨時緩沖區(qū)執(zhí)行低層次操作。臨時緩沖區(qū)對象離開作用域,并最終成為被回收的無用數(shù)據(jù)。 前天剛好看了點《UNIX網(wǎng)絡(luò)編程》,比較頭大。現(xiàn)在我來整理一下所學(xué)所得,并用于個人備忘。如果有不對,請批評。 想要解鎖更多新姿勢?請訪問https://blog.tengshe789.tech/ IO模型介紹 IO模型是什么...

    SnaiLiu 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<