最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JAVA NIO按行讀寫大文件出現(xiàn)中文亂碼問題的解決

 更新時間:2025年02月18日 08:58:19   作者:程序員囧輝  
這篇文章主要為大家詳細(xì)介紹了JAVA在使用NIO進(jìn)行按行讀寫大文件時出現(xiàn)中文亂碼問題是如何解決的,文中的示例代碼簡潔易懂,有需要的小伙伴可以參考一下

前言

最近在開發(fā)的時候,接到了一個開發(fā)任務(wù),要將百萬行級別的txt數(shù)據(jù)插入到數(shù)據(jù)庫中,由于內(nèi)存方面的原因,因此不可能一次讀取所有內(nèi)容,后來在網(wǎng)上找到了解決方法,可以使用NIO技術(shù)來處理,后來在試驗過程中發(fā)現(xiàn)了一點(diǎn)小bug,由于是按字節(jié)讀取,漢字又是2個字節(jié),因此會出現(xiàn)漢字讀取“一半”導(dǎo)致亂碼的情況,于是花了幾天時間將這個問題解決了。

例子

假設(shè)我們一次讀取的字節(jié)是從下圖的start到end,因為結(jié)尾是漢字,所以有幾率出現(xiàn)上述的情況。

解決方法如下:將第9行這半行(第9行陰影的部分)跟上一次讀取留下來的半行(第9行沒陰影的部分)按順序存放在字節(jié)數(shù)組,然后轉(zhuǎn)成字符串;中間第10行到第17行正常轉(zhuǎn)換成字符串;第18行這半行(第18行陰影的部分)留著跟下一次讀取的第1行(第18行沒陰影的部分)連接成一行,因為是先拼接成字節(jié)數(shù)組再轉(zhuǎn)字符串,因此不會出現(xiàn)亂碼的情況。

代碼

package com.joonwhee.imp;
 
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 
/**
 * @author joonwhee
 * @date 2019/3/22
 */
public class NIOTest {
    
    public static void main(String args[]) throws Exception {
 
        int bufSize = 1000000;//一次讀取的字節(jié)長度
        File fin = new File("D:\\test\\20160622_627975.txt");//讀取的文件
        File fout = new File("D:\\test\\20160622_627975_1.txt");//寫出的文件
        Date startDate = new Date();
        FileChannel fcin = new RandomAccessFile(fin, "r").getChannel();
        ByteBuffer rBuffer = ByteBuffer.allocate(bufSize);
 
        FileChannel fcout = new RandomAccessFile(fout, "rws").getChannel();
        ByteBuffer wBuffer = ByteBuffer.allocateDirect(bufSize);
 
        readFileByLine(bufSize, fcin, rBuffer, fcout, wBuffer);
        Date endDate = new Date();
 
        System.out.print(startDate + "|" + endDate);//測試執(zhí)行時間
        if (fcin.isOpen()) {
            fcin.close();
        }
        if (fcout.isOpen()) {
            fcout.close();
        }
    }
 
    public static void readFileByLine(int bufSize, FileChannel fcin,
                                      ByteBuffer rBuffer, FileChannel fcout, ByteBuffer wBuffer) {
        String enter = "\n";
        List<String> dataList = new ArrayList<String>();//存儲讀取的每行數(shù)據(jù)
        byte[] lineByte = new byte[0];
 
        String encode = "GBK";
//		String encode = "UTF-8";
        try {
            //temp:由于是按固定字節(jié)讀取,在一次讀取中,第一行和最后一行經(jīng)常是不完整的行,因此定義此變量來存儲上次的最后一行和這次的第一行的內(nèi)容,
            //并將之連接成完成的一行,否則會出現(xiàn)漢字被拆分成2個字節(jié),并被提前轉(zhuǎn)換成字符串而亂碼的問題
            byte[] temp = new byte[0];
            while (fcin.read(rBuffer) != -1) {//fcin.read(rBuffer):從文件管道讀取內(nèi)容到緩沖區(qū)(rBuffer)
                int rSize = rBuffer.position();//讀取結(jié)束后的位置,相當(dāng)于讀取的長度
                byte[] bs = new byte[rSize];//用來存放讀取的內(nèi)容的數(shù)組
                rBuffer.rewind();//將position設(shè)回0,所以你可以重讀Buffer中的所有數(shù)據(jù),此處如果不設(shè)置,無法使用下面的get方法
                rBuffer.get(bs);//相當(dāng)于rBuffer.get(bs,0,bs.length()):從position初始位置開始相對讀,讀bs.length個byte,并寫入bs[0]到bs[bs.length-1]的區(qū)域
                rBuffer.clear();
 
                int startNum = 0;
                int LF = 10;//換行符
                int CR = 13;//回車符
                boolean hasLF = false;//是否有換行符
                for (int i = 0; i < rSize; i++) {
                    if (bs[i] == LF) {
                        hasLF = true;
                        int tempNum = temp.length;
                        int lineNum = i - startNum;
                        lineByte = new byte[tempNum + lineNum];//數(shù)組大小已經(jīng)去掉換行符
 
                        System.arraycopy(temp, 0, lineByte, 0, tempNum);//填充了lineByte[0]~lineByte[tempNum-1]
                        temp = new byte[0];
                        System.arraycopy(bs, startNum, lineByte, tempNum, lineNum);//填充lineByte[tempNum]~lineByte[tempNum+lineNum-1]
 
                        String line = new String(lineByte, 0, lineByte.length, encode);//一行完整的字符串(過濾了換行和回車)
                        dataList.add(line);
//						System.out.println(line);
                        writeFileByLine(fcout, wBuffer, line + enter);
 
                        //過濾回車符和換行符
                        if (i + 1 < rSize && bs[i + 1] == CR) {
                            startNum = i + 2;
                        } else {
                            startNum = i + 1;
                        }
 
                    }
                }
                if (hasLF) {
                    temp = new byte[bs.length - startNum];
                    System.arraycopy(bs, startNum, temp, 0, temp.length);
                } else {//兼容單次讀取的內(nèi)容不足一行的情況
                    byte[] toTemp = new byte[temp.length + bs.length];
                    System.arraycopy(temp, 0, toTemp, 0, temp.length);
                    System.arraycopy(bs, 0, toTemp, temp.length, bs.length);
                    temp = toTemp;
                }
            }
            if (temp != null && temp.length > 0) {//兼容文件最后一行沒有換行的情況
                String line = new String(temp, 0, temp.length, encode);
                dataList.add(line);
//				System.out.println(line);
                writeFileByLine(fcout, wBuffer, line + enter);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    /**
     * 寫到文件上
     *
     * @param fcout
     * @param wBuffer
     * @param line
     */
    @SuppressWarnings("static-access")
    public static void writeFileByLine(FileChannel fcout, ByteBuffer wBuffer,
                                       String line) {
        try {
            fcout.write(wBuffer.wrap(line.getBytes("UTF-8")), fcout.size());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

到此這篇關(guān)于JAVA NIO按行讀寫大文件出現(xiàn)中文亂碼問題的解決的文章就介紹到這了,更多相關(guān)JAVA NIO按行讀寫大文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java字符串轉(zhuǎn)成二進(jìn)制碼的方法

    Java字符串轉(zhuǎn)成二進(jìn)制碼的方法

    這篇文章主要為大家詳細(xì)介紹了Java字符串轉(zhuǎn)成二進(jìn)制碼的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一
    2017-05-05
  • @RequestParam 接收參數(shù)的值為null的處理方式

    @RequestParam 接收參數(shù)的值為null的處理方式

    這篇文章主要介紹了@RequestParam 接收參數(shù)的值為null的處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java元素排序Comparable與Comparator的區(qū)別

    Java元素排序Comparable與Comparator的區(qū)別

    這篇文章主要介紹了Java元素排序Comparable與Comparator的區(qū)別,二者都是頂級的接口,但擁有的方法和用法是不同的,下面我們分別來看看具體是怎樣的區(qū)別吧
    2022-05-05
  • java項目依賴包選擇具體實(shí)現(xiàn)類示例介紹

    java項目依賴包選擇具體實(shí)現(xiàn)類示例介紹

    這篇文章主要為大家介紹了java項目依賴包選擇具體實(shí)現(xiàn)類示例介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 淺談java IO流——四大抽象類

    淺談java IO流——四大抽象類

    這篇文章主要介紹了java IO流——四大抽象類,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 下一代Eclipse 步入云端

    下一代Eclipse 步入云端

    代號Che的下一代Eclipse IDE將運(yùn)行在云端,可以在任何機(jī)器上打開瀏覽器寫代碼。項目的建立、編輯、debug、部署可以都在一個倉庫中進(jìn)行,需要的朋友可以參考下
    2015-12-12
  • Java前后端任意參數(shù)類型轉(zhuǎn)換方式(Date、LocalDateTime、BigDecimal)

    Java前后端任意參數(shù)類型轉(zhuǎn)換方式(Date、LocalDateTime、BigDecimal)

    這篇文章主要介紹了Java前后端任意參數(shù)類型轉(zhuǎn)換方式(Date、LocalDateTime、BigDecimal),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • java解析xml常用的幾種方式總結(jié)

    java解析xml常用的幾種方式總結(jié)

    這篇文章主要介紹了java解析xml常用的幾種方式總結(jié),有需要的朋友可以參考一下
    2013-11-11
  • Java線程中的Timer和TimerTask原理詳解

    Java線程中的Timer和TimerTask原理詳解

    這篇文章主要介紹了Java線程中的Timer和TimerTask原理詳解,Timer和TimerTask成對出現(xiàn),Timer是定時器,TimerTask是定時任務(wù),換句話說,定時任務(wù)TimerTask是給定時器Timer執(zhí)行的具體任務(wù),需要的朋友可以參考下
    2023-10-10
  • spring boot整合redis實(shí)現(xiàn)shiro的分布式session共享的方法

    spring boot整合redis實(shí)現(xiàn)shiro的分布式session共享的方法

    本篇文章主要介紹了spring boot整合redis實(shí)現(xiàn)shiro的分布式session共享的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01

最新評論

突泉县| 德惠市| 商洛市| 秭归县| 金昌市| 定日县| 高阳县| 新田县| 黄骅市| 仁寿县| 北京市| 长兴县| 鹤峰县| 莱芜市| 大宁县| 淮安市| 荣成市| 赤城县| 永清县| 抚顺县| 柘荣县| 太和县| 徐汇区| 东丰县| 克东县| 胶州市| 和林格尔县| 台山市| 青河县| 永仁县| 湘潭县| 潮州市| 吉林市| 黄平县| 敖汉旗| 色达县| 金山区| 东乌珠穆沁旗| 杭锦旗| 威远县| 金溪县|