Java實(shí)現(xiàn)文件的分割與合并
本文實(shí)例為大家分享了Java實(shí)現(xiàn)文件的分割與合并的具體代碼,供大家參考,具體內(nèi)容如下
一、文件分割實(shí)現(xiàn)思想
1、設(shè)置分割文件(塊)的大??;
2、通過輸入流獲取源文件的大??;
3、根據(jù)1、2步的計(jì)算結(jié)果計(jì)算出分割后的文件個(gè)數(shù)(源文件的大小 / 設(shè)置分割文件的大小 ,如果設(shè)置的文件大小大于源文件的大小,接下來判斷1、2步計(jì)算結(jié)果,如果余數(shù)為0,則文件個(gè)數(shù)為商值,如果余數(shù)大于0,則文件個(gè)數(shù)為商值加1。
如果設(shè)置分割文件的大小小于源文件的大小,那么文件個(gè)數(shù)為1。);
4、分割文件(邊讀邊寫)。
二、文件合并實(shí)現(xiàn)思想
1、文件合并與文件分割實(shí)現(xiàn)思想的第4步類似,就是邊讀邊寫。
方式一:調(diào)用API中的RandomAccessFile,此類的實(shí)例支持對(duì)隨機(jī)存取文件的讀取和寫入。按塊分割與合并,示例代碼如下:
package com.cn.filesplite1; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.io.SequenceInputStream; import java.util.ArrayList; import java.util.List; import java.util.Vector; public class SplitFile { //文件的路徑 private String filePath; //文件名 private String fileName; //文件大小 private long length; //塊數(shù) private int size; //每塊的大小 private long blockSize; //分割后的存放目錄 private String destBlockPath; //每塊的名稱 private List<String> blockPath; public SplitFile(){ blockPath = new ArrayList<String>(); } public SplitFile(String filePath,String destBlockPath){ this(filePath,destBlockPath,1024); } public SplitFile(String filePath,String destBlockPath,long blockSize){ this(); this.filePath= filePath; this.destBlockPath =destBlockPath; this.blockSize=blockSize; init(); } /** * 初始化操作 計(jì)算 塊數(shù)、確定文件名 */ public void init(){ File src =null; //健壯性 if(null==filePath ||!(((src=new File(filePath)).exists()))){ return; } if(src.isDirectory()){ return ; } //文件名 this.fileName =src.getName(); //計(jì)算塊數(shù) 實(shí)際大小 與每塊大小 this.length = src.length(); //修正 每塊大小 if(this.blockSize>length){ this.blockSize =length; } //確定塊數(shù) size= (int)(Math.ceil(length*1.0/this.blockSize)); //確定文件的路徑 initPathName(); } private void initPathName(){ for(int i=0;i<size;i++){ this.blockPath.add(destBlockPath+"/"+this.fileName+".part"+i); } } /** * 文件的分割 * 0)、第幾塊 * 1、起始位置 * 2、實(shí)際大小 * @param destPath 分割文件存放目錄 */ public void split(){ long beginPos =0; //起始點(diǎn) long actualBlockSize =blockSize; //實(shí)際大小 //計(jì)算所有塊的大小、位置、索引 for(int i=0;i<size;i++){ if(i==size-1){ //最后一塊 actualBlockSize =this.length-beginPos; } spiltDetail(i,beginPos,actualBlockSize); beginPos+=actualBlockSize; //本次的終點(diǎn),下一次的起點(diǎn) } } /** * 文件的分割 輸入 輸出 * 文件拷貝 * @param idx 第幾塊 * @param beginPos 起始點(diǎn) * @param actualBlockSize 實(shí)際大小 */ private void spiltDetail(int idx,long beginPos,long actualBlockSize){ //1、創(chuàng)建源 File src = new File(this.filePath); //源文件 File dest = new File(this.blockPath.get(idx)); //目標(biāo)文件 //2、選擇流 RandomAccessFile raf = null; //輸入流 BufferedOutputStream bos=null; //輸出流 try { raf=new RandomAccessFile(src,"r"); bos =new BufferedOutputStream(new FileOutputStream(dest)); //讀取文件 raf.seek(beginPos); //緩沖區(qū) byte[] flush = new byte[1024]; //接收長度 int len =0; while(-1!=(len=raf.read(flush))){ if(actualBlockSize-len>=0){ //查看是否足夠 //寫出 bos.write(flush, 0, len); actualBlockSize-=len; //剩余量 }else{ //寫出最后一次的剩余量 bos.write(flush, 0, (int)actualBlockSize); break; } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ FileUtil.close(bos,raf); } } /** * 文件的合并 */ public void merge(String destPath){ //創(chuàng)建源 File dest =new File(destPath); //選擇流 BufferedOutputStream bos=null; //輸出流 SequenceInputStream sis =null ;//輸入流 //創(chuàng)建一個(gè)容器 Vector<InputStream> vi = new Vector<InputStream>(); try { for (int i = 0; i < this.blockPath.size(); i++) { vi.add(new BufferedInputStream(new FileInputStream(new File(this.blockPath.get(i))))); } bos =new BufferedOutputStream(new FileOutputStream(dest,true)); //追加 sis=new SequenceInputStream(vi.elements()); //緩沖區(qū) byte[] flush = new byte[1024]; //接收長度 int len =0; while(-1!=(len=sis.read(flush))){ bos.write(flush, 0, len); } bos.flush(); FileUtil.close(sis); } catch (Exception e) { }finally{ FileUtil.close(bos); } } /** * @param args */ public static void main(String[] args) { //1024 * 30 表示按照每塊30Kb大小分割 SplitFile split = new SplitFile("F:/123/1234/logFile.txt","F:/123/",1024 * 30); System.out.println(split.size); // split.split(); split.merge("F:/123/logFile.txt"); } }
package com.cn.filesplite1; import java.io.Closeable; public class FileUtil { /** * 工具類關(guān)閉流 * 可變參數(shù): ... 只能形參最后一個(gè)位置,處理方式與數(shù)組一致 */ public static void close(Closeable ... io){ for(Closeable temp:io){ try { if (null != temp) { temp.close(); } } catch (Exception e) { } } } /** * 使用泛型方法 */ public static <T extends Closeable> void closeAll(T ... io){ for(Closeable temp:io){ try { if (null != temp) { temp.close(); } } catch (Exception e) { } } } }
方式二:用讀寫的方式實(shí)現(xiàn)文件的分割與合并,具體實(shí)現(xiàn)如下代碼所示:
定義一個(gè)抽象類
package com.cn.filesplite2; import java.io.File; import java.io.IOException; /** * 文件分割 * @author Administrator * */ public abstract class SplitFile { /** * 設(shè)置單個(gè)文件的大小 * 根據(jù)自己需求設(shè)置大小,字節(jié)進(jìn)率為1024,本例中設(shè)置的最大分割文件大小是2Gb。 */ public static long MAX_BYTE = 1024 * 1024 * 1024 * 2L; //2G /** * 獲取可以分割的文件數(shù) * @param fileByte 文件大小 * @param fileParh 文件路徑 * @return */ public abstract int getSplitFileNum(long fileByte,String fileParh); /** * 獲取文件長度 * @param file * @return * @throws IOException */ public abstract long getFileLength(File file) ; /** * 分割文件 * @param srcFile * @param splitFileNum * @return * @throws IOException */ public abstract String[] splitFile (File srcFile,int splitFileNum) throws IOException; /** * 合并文件 * @param files * @param newFile * @throws IOException */ public abstract void mergeFile(String[] files,String newFile) throws IOException; }
實(shí)現(xiàn)類
package com.cn.filesplite2; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; /** * 文本文件分割 * @author Administrator * */ public class SplitTextFile extends SplitFile{ @Override public long getFileLength(File file) { FileReader fr = null; BufferedReader br = null; //文件大小 long fileSize = 0; try { fr = new FileReader(file); br = new BufferedReader(fr); String line = br.readLine(); //按行讀取文件 while(line != null){ //計(jì)算文件大小 fileSize += line.length(); line = br.readLine(); } } catch (IOException e) { e.printStackTrace(); }finally{ //關(guān)閉輸入流 try { if(br != null){ br.close(); } if(fr != null){ fr.close(); } } catch (IOException e) { e.printStackTrace(); } } //返回文件大小 return fileSize; } @Override public int getSplitFileNum(long fileByte,String fileParh){ fileByte = getFileLength(new File(fileParh)); if(MAX_BYTE < fileByte){ if(fileByte % MAX_BYTE == 0){ return (int) (fileByte/MAX_BYTE); }else{ return (int) (fileByte/MAX_BYTE) + 1; } } return 1; } @Override public String[] splitFile(File srcFile, int splitFileNum) throws IOException { splitFileNum = getSplitFileNum(getFileLength(srcFile), srcFile.toString()); if(splitFileNum <= 0){ return null; } FileReader fr = null; BufferedReader br = null; long readNum = 0; String[] splits = new String[splitFileNum]; try { fr = new FileReader(srcFile); br = new BufferedReader(fr); int i = 0; while(splitFileNum > i){ //分割后的文件名 String name = null; //文件后綴 String nameLast = null; if(srcFile.getName().indexOf(".") != -1){ name = srcFile.getName().substring(0, srcFile.getName().indexOf(".")); int last = srcFile.getName().lastIndexOf("."); // System.out.println(i); // String string = str.substring(i); nameLast = srcFile.getName().substring(last); }else{ name = srcFile.getName(); } splits[i] = srcFile.getParent() + "/" + name + "_" + i + nameLast; File wfile = new File(splits[i]); if(!wfile.exists()){ wfile.getParentFile().mkdirs(); wfile.createNewFile(); } FileWriter fw = new FileWriter(wfile,false); BufferedWriter bw = new BufferedWriter(fw); String line = br.readLine(); int flush = 0; while(line != null){ if(line.trim().length() == 0){ line = br.readLine(); continue; } readNum += line.length(); if(i + 1 == splitFileNum){ bw.write(line); bw.newLine(); }else{ if(readNum >= MAX_BYTE){ bw.write(line); bw.newLine(); break; }else{ bw.write(line); bw.newLine(); } } line = br.readLine(); if(flush % 100 == 0){ bw.flush(); } } bw.flush(); fw.flush(); bw.close(); fw.close(); readNum = 0; i++; } } catch (RuntimeException e) { e.printStackTrace(); } finally{ try { if(br != null) br.close(); if(fr != null) fr.close(); } catch (Exception e) { e.printStackTrace(); }finally{ br = null; fr = null; } } return splits; } @Override public void mergeFile(String[] files, String newFile) throws IOException { File wfile = new File(newFile); FileWriter writer = null; BufferedWriter bufferedWriter = null; try { writer = new FileWriter(wfile,false); bufferedWriter = new BufferedWriter(writer); for(int i = 0; i < files.length; i++){ File rFile = new File(files[i]); FileReader reader = new FileReader(rFile); BufferedReader bufferedReader = new BufferedReader(reader); String line = bufferedReader.readLine(); while(line != null){ if(line.trim().length() == 0){ line = bufferedReader.readLine(); continue; } bufferedWriter.write(line); bufferedWriter.newLine(); line = bufferedReader.readLine(); } } bufferedWriter.flush(); writer.flush(); } catch (Exception e) { e.printStackTrace(); }finally{ if(bufferedWriter != null) bufferedWriter.close(); bufferedWriter = null; if(writer != null) writer.close(); writer = null; } } }
測試類
package com.cn.filesplite2; import java.io.File; import java.io.IOException; import org.junit.Test; public class TestSplitFile { SplitTextFile splitTextFile = new SplitTextFile(); @Test public void funSplitFile() throws IOException{ String srcPath = "E:/splitfile/splitfile.txt"; File file = new File(srcPath); long fileLength = splitTextFile.getFileLength(file); System.out.println("文件大?。? + fileLength); int partitionFileNum = splitTextFile.getSplitFileNum(fileLength, srcPath); System.out.println("個(gè)數(shù)" + partitionFileNum); //文件分割 splitTextFile.splitFile(new File(srcPath), partitionFileNum); } @Test public void funMergeFile() throws IOException{ String[] files = {"E:/splitfile/splitfile0", "E:/splitfile/splitfile1", "E:/splitfile/splitfile2" // ...files/ }; String newFile = "E:/splitfile/newmergefile"; splitTextFile.mergeFile(files, newFile); } }
以上內(nèi)容如有任何問題或錯(cuò)誤,懇請(qǐng)大家能給予意見,我會(huì)及時(shí)更正,謝謝大家。
本文的全部內(nèi)容介紹完了,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java框架Quartz中API、Jobs和Trigger詳解
這篇文章主要介紹了Java框架Quartz中API、Jobs和Trigger詳解,JobDetail?對(duì)象是在將?job?加入?scheduler?時(shí),由客戶端程序(你的程序)創(chuàng)建的,它包含?job?的各種屬性設(shè)置,以及用于存儲(chǔ)?job?實(shí)例狀態(tài)信息的?JobDataMap,需要的朋友可以參考下2023-11-11java實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證(包含前端代碼)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12Spring Boot數(shù)據(jù)庫鏈接池配置方法
這篇文章主要介紹了Spring Boot數(shù)據(jù)庫鏈接池配置方法,需要的朋友可以參考下2017-04-04springboot應(yīng)用服務(wù)啟動(dòng)事件的監(jiān)聽實(shí)現(xiàn)
本文主要介紹了springboot應(yīng)用服務(wù)啟動(dòng)事件的監(jiān)聽實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04SpringBoot中使用Redisson的實(shí)現(xiàn)示例
Redission是一個(gè)強(qiáng)大的Java庫,用于構(gòu)建和管理分布式系統(tǒng)中的緩存和任務(wù)調(diào)度,本文主要介紹了SpringBoot中使用Redisson的實(shí)現(xiàn)示例,感興趣的可以了解一下2023-12-12