欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java實(shí)現(xiàn)大文本文件拆分

 更新時(shí)間:2020年05月19日 17:22:30   作者:lucky_白楊  
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)大文本文件拆分,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了java實(shí)現(xiàn)大文本文件拆分的具體代碼,供大家參考,具體內(nèi)容如下

生成大文件

public static void createBigFile() throws IOException {
 File file = new File("/Users/yangpeng/Documents/temp/big_file.csv");
 FileWriter fileWriter = new FileWriter(file);
 BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
 String str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1";
 for (int i = 0; i < 1000000; i++) {
  bufferedWriter.write(str);
  bufferedWriter.newLine();
 }
 bufferedWriter.flush();
 bufferedWriter.close();
}

文件拆分

此處沒有給出根據(jù)文件大小計(jì)算需要拆分的文件數(shù)量,所以這里是給定一個(gè)拆分文件數(shù)量

思路

思路:給定帶拆分?jǐn)?shù)量,計(jì)算出每個(gè)文件的平均字節(jié)數(shù),然后循環(huán)文件數(shù)進(jìn)行每個(gè)文件的拆分。拆分第一個(gè)文件時(shí),根據(jù)平均字節(jié)數(shù)往后取給定的大約行字節(jié)數(shù)的字節(jié),然后循環(huán)字節(jié)判斷是否為\r或者\(yùn)n,如果字節(jié)為\r或者\(yùn)n則代表到達(dá)行末尾,記錄行尾字節(jié)位置。知道了開頭字節(jié)位置與結(jié)束字節(jié)位置,就可以將此位置之間的數(shù)據(jù)生成子文件了。繼續(xù)循環(huán)拆分下個(gè)文件,基于上個(gè)文件記錄的結(jié)束字節(jié)位置繼續(xù)計(jì)算當(dāng)前文件的結(jié)束位置,直到到達(dá)拆分文件的數(shù)量或者大文件讀取完畢。

舉個(gè)栗子:

有一個(gè)3行記錄的文件,假設(shè)每行記錄行字節(jié)包含換行符的字節(jié)數(shù)為100,也就是說這個(gè)文件的總字節(jié)數(shù)為300。

我現(xiàn)在要將這個(gè)文件拆分成2個(gè)。按照上面的思路,首先我需要計(jì)算出文件的平均值300/2=150,這里計(jì)算出的平均值并不是拆分出來的子文件一定是150,因?yàn)檫@個(gè)數(shù)字位置的字節(jié)有可能在一行的中間,那么我要基于這個(gè)數(shù)字算出下個(gè)換行符出現(xiàn)的位置當(dāng)做我這個(gè)子文件的結(jié)束位。

所以我給定一個(gè)行字節(jié)數(shù)100+150=250,這個(gè)150到250之間的字節(jié)我認(rèn)為有換行符,所以我輪詢這100字節(jié),判斷是否為換行符,結(jié)果我輪到到50的位置發(fā)現(xiàn)了換行。

那么我這個(gè)第一個(gè)文件的結(jié)束位置是150+50=200,然后將0到200之間的字節(jié)生成第一個(gè)文件。然后基于這個(gè)200的位置繼續(xù)拆分下個(gè)文件,由于200+150已經(jīng)大于了源文件的大小,所以直接將200到300的數(shù)據(jù)生成一個(gè)子文件。所以最終的結(jié)果是一二行為一個(gè)子文件,三行為第二個(gè)子文件。

代碼

考慮到性能與內(nèi)存占用的問題,此處實(shí)現(xiàn)采用NIO

public static void splitFile(String filePath, int fileCount) throws IOException {
 FileInputStream fis = new FileInputStream(filePath);
 FileChannel inputChannel = fis.getChannel();
 final long fileSize = inputChannel.size();
 long average = fileSize / fileCount;//平均值
 long bufferSize = 200; //緩存塊大小,自行調(diào)整
 ByteBuffer byteBuffer = ByteBuffer.allocate(Integer.valueOf(bufferSize + "")); // 申請(qǐng)一個(gè)緩存區(qū)
 long startPosition = 0; //子文件開始位置
 long endPosition = average < bufferSize ? 0 : average - bufferSize;//子文件結(jié)束位置
 for (int i = 0; i < fileCount; i++) {
  if (i + 1 != fileCount) {
   int read = inputChannel.read(byteBuffer, endPosition);// 讀取數(shù)據(jù)
   readW:
   while (read != -1) {
    byteBuffer.flip();//切換讀模式
    byte[] array = byteBuffer.array();
    for (int j = 0; j < array.length; j++) {
     byte b = array[j];
     if (b == 10 || b == 13) { //判斷\n\r
      endPosition += j;
      break readW;
     }
    }
    endPosition += bufferSize;
    byteBuffer.clear(); //重置緩存塊指針
    read = inputChannel.read(byteBuffer, endPosition);
   }
  }else{
   endPosition = fileSize; //最后一個(gè)文件直接指向文件末尾
  }

  FileOutputStream fos = new FileOutputStream(filePath + (i + 1));
  FileChannel outputChannel = fos.getChannel();
  inputChannel.transferTo(startPosition, endPosition - startPosition, outputChannel);//通道傳輸文件數(shù)據(jù)
  outputChannel.close();
  fos.close();
  startPosition = endPosition + 1;
  endPosition += average;
 }
 inputChannel.close();
 fis.close();

}

public static void main(String[] args) throws Exception {
 Scanner scanner = new Scanner(System.in);
 scanner.nextLine();
 long startTime = System.currentTimeMillis();
 splitFile("/Users/yangpeng/Documents/temp/big_file.csv",5);
 long endTime = System.currentTimeMillis();
 System.out.println("耗費(fèi)時(shí)間: " + (endTime - startTime) + " ms");
 scanner.nextLine();
}

使用NIO可以高效的實(shí)現(xiàn)文件拆分,我的文件為100W行大小為1.02G的文本文件,拆分成5個(gè)子文件總耗時(shí)1224ms

后如下是使用jvisualvm監(jiān)控的程序內(nèi)存:

可以看到拆分期間內(nèi)存浮動(dòng)基本在1M左右。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java并發(fā)之嵌套管程鎖死詳解

    Java并發(fā)之嵌套管程鎖死詳解

    這篇文章主要介紹了Java并發(fā)之嵌套管程鎖死詳解,涉及嵌套管程鎖死的發(fā)生,實(shí)例等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • Java中保證線程順序執(zhí)行的操作代碼

    Java中保證線程順序執(zhí)行的操作代碼

    本文給大家分享一篇教程關(guān)于java線程順序執(zhí)行問題,如何保證線程的順序執(zhí)行呢?今天通過實(shí)例代碼給大家詳細(xì)講解下,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • Java正則表達(dá)式——group方法的使用

    Java正則表達(dá)式——group方法的使用

    這篇文章主要介紹了Java正則表達(dá)式group方法的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Flyway詳解及Springboot集成Flyway的詳細(xì)教程

    Flyway詳解及Springboot集成Flyway的詳細(xì)教程

    Flayway是一款數(shù)據(jù)庫版本控制管理工具,,支持?jǐn)?shù)據(jù)庫版本自動(dòng)升級(jí),Migrations可以寫成sql腳本,也可以寫在java代碼里。這篇文章主要介紹了Flyway詳解及Springboot集成Flyway的詳細(xì)教程的相關(guān)資料,需要的朋友可以參考下
    2020-07-07
  • 使用Java實(shí)現(xiàn)希爾排序算法的簡(jiǎn)單示例

    使用Java實(shí)現(xiàn)希爾排序算法的簡(jiǎn)單示例

    這篇文章主要介紹了使用Java實(shí)現(xiàn)希爾排序算法的簡(jiǎn)單示例,希爾排序可以被看作是插入排序的一種更高效的改進(jìn)版本,需要的朋友可以參考下
    2016-05-05
  • 解決SpringBoot jar包中的文件讀取問題實(shí)現(xiàn)

    解決SpringBoot jar包中的文件讀取問題實(shí)現(xiàn)

    這篇文章主要介紹了解決SpringBoot jar包中的文件讀取問題實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 關(guān)于protected修飾符詳解-源于Cloneable接口

    關(guān)于protected修飾符詳解-源于Cloneable接口

    這篇文章主要介紹了protected修飾符詳解-源于Cloneable接口,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 詳解netty中常用的xml編碼解碼器

    詳解netty中常用的xml編碼解碼器

    這篇文章主要介紹了netty中常用的xml編碼解碼器,進(jìn)行frame拆分可以使用XmlFrameDecoder,進(jìn)行xml文件內(nèi)容的解析則可以使用XmlDecoder,接下來我們會(huì)詳細(xì)講解兩個(gè)decoder實(shí)現(xiàn)和使用,感興趣的朋友一起看看吧
    2022-05-05
  • Spring筆記-@Order注解和Ordered接口解析

    Spring筆記-@Order注解和Ordered接口解析

    這篇文章主要介紹了Spring筆記-@Order注解和Ordered接口,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Mybatis與微服務(wù)注冊(cè)的詳細(xì)過程

    Mybatis與微服務(wù)注冊(cè)的詳細(xì)過程

    這篇文章主要介紹了Mybatis與微服務(wù)注冊(cè),主要包括SpringBoot整合MybatisPlus,SpringBoot整合Freeamarker以及SpringBoot整合微服務(wù)&gateway&nginx的案例代碼,需要的朋友可以參考下
    2023-01-01

最新評(píng)論