Java實(shí)現(xiàn)文件的分割與合并
本文實(shí)例為大家分享了Java實(shí)現(xiàn)文件的分割與合并的具體代碼,供大家參考,具體內(nèi)容如下
一、文件分割實(shí)現(xiàn)思想
1、設(shè)置分割文件(塊)的大??;
2、通過輸入流獲取源文件的大?。?br />
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中建立0-10m的消息(字符串)實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猨ava中建立0-10m的消息(字符串)實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
Java Fluent Mybatis 項(xiàng)目工程化與常規(guī)操作詳解流程篇 下
Java中常用的ORM框架主要是mybatis, hibernate, JPA等框架。國內(nèi)又以Mybatis用的多,基于mybatis上的增強(qiáng)框架,又有mybatis plus和TK mybatis等。今天我們介紹一個(gè)新的mybatis增強(qiáng)框架 fluent mybatis關(guān)于項(xiàng)目工程化與常規(guī)操作流程2021-10-10
Maven安裝本地的jar包和創(chuàng)建帶模板的自定義項(xiàng)目的操作過程
這篇文章主要介紹了Maven安裝本地的jar包和創(chuàng)建帶模板的自定義項(xiàng)目,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-03-03
Java enum關(guān)鍵字不識(shí)別的快速解決辦法
這篇文章主要介紹了Java enum關(guān)鍵字不識(shí)別的快速解決辦法,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧2016-09-09
解決IDEA右鍵沒有創(chuàng)建新的package選項(xiàng)的情況
這篇文章主要介紹了解決IDEA右鍵沒有創(chuàng)建新的package選項(xiàng)的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02
java后端如何實(shí)現(xiàn)防止接口重復(fù)提交
這篇文章主要介紹了java后端如何實(shí)現(xiàn)防止接口重復(fù)提交問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
SpringBoot?SPI?機(jī)制和實(shí)現(xiàn)自定義?starter
這篇文章主要介紹了SpringBoot?SPI機(jī)制和實(shí)現(xiàn)自定義?starter,全稱是Service?Provider?Interface。簡單翻譯的話,就是服務(wù)提供者接口,是一種尋找服務(wù)實(shí)現(xiàn)的機(jī)制2022-08-08

