Java实现文件的分割与合并

时间:2021-07-19 23:51:54

本文实例为大家分享了Java实现文件的分割与合并的具体代码,供大家参考,具体内容如下

一、文件分割实现思想

1、设置分割文件(块)的大小;
2、通过输入流获取源文件的大小;
3、根据1、2步的计算结果计算出分割后的文件个数(源文件的大小 / 设置分割文件的大小 ,如果设置的文件大小大于源文件的大小,接下来判断1、2步计算结果,如果余数为0,则文件个数为商值,如果余数大于0,则文件个数为商值加1。
如果设置分割文件的大小小于源文件的大小,那么文件个数为1。);
4、分割文件(边读边写)。

二、文件合并实现思想

1、文件合并与文件分割实现思想的第4步类似,就是边读边写。

方式一:调用API中的RandomAccessFile,此类的实例支持对随机存取文件的读取和写入。按块分割与合并,示例代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
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;
 //块数
 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();
 }
 
 /**
  * 初始化操作 计算 块数、确定文件名
  */
 public void init(){
  File src =null;
  //健壮性
  if(null==filePath ||!(((src=new File(filePath)).exists()))){
   return;
  }
  if(src.isDirectory()){
   return ;
  }
  //文件名
  this.fileName =src.getName();
  
  //计算块数 实际大小 与每块大小
  this.length = src.length();
  //修正 每块大小
  if(this.blockSize>length){
   this.blockSize =length;
  }
  //确定块数 
  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、实际大小
  * @param destPath 分割文件存放目录
  */
 public void split(){
  long beginPos =0//起始点
  long actualBlockSize =blockSize; //实际大小 
  //计算所有块的大小、位置、索引
  for(int i=0;i<size;i++){
   if(i==size-1){ //最后一块
    actualBlockSize =this.length-beginPos;
   }  
   spiltDetail(i,beginPos,actualBlockSize);
   beginPos+=actualBlockSize; //本次的终点,下一次的起点
  }
  
 }
 /**
  * 文件的分割 输入 输出
  * 文件拷贝
  * @param idx 第几块
  * @param beginPos 起始点
  * @param actualBlockSize 实际大小
  */
 private void spiltDetail(int idx,long beginPos,long actualBlockSize){
  //1、创建源
  File src = new File(this.filePath);  //源文件
  File dest = new File(this.blockPath.get(idx)); //目标文件
  //2、选择流
  RandomAccessFile raf = null//输入流
  BufferedOutputStream bos=null; //输出流
  try {
   raf=new RandomAccessFile(src,"r");
   bos =new BufferedOutputStream(new FileOutputStream(dest));
   //读取文件
   raf.seek(beginPos);
   //缓冲区
   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){
  //创建源
  File dest =new File(destPath);
  //选择流
  BufferedOutputStream bos=null; //输出流
  SequenceInputStream sis =null ;//输入流
  //创建一个容器
  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());  
   //缓冲区
   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");
  
 }
 
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.cn.filesplite1;
import java.io.Closeable;
public class FileUtil {
 /**
  * 工具类关闭流
  * 可变参数: ...  只能形参最后一个位置,处理方式与数组一致
  */
 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) {
   }
  }
 }
 
}

方式二:用读写的方式实现文件的分割与合并,具体实现如下代码所示:

定义一个抽象类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.cn.filesplite2;
import java.io.File;
import java.io.IOException;
/**
 * 文件分割
 * @author Administrator
 *
 */
public abstract class SplitFile {
 /**
  * 设置单个文件的大小
  * 根据自己需求设置大小,字节进率为1024,本例中设置的最大分割文件大小是2Gb。
  */
 public static long MAX_BYTE = 1024 * 1024 * 1024 * 2L;  //2G
 
 /**
  * 获取可以分割的文件数
  * @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;
 
}

实现类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
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){
    //计算文件大小
    fileSize += line.length();
    line = br.readLine();
   }
  } catch (IOException e) {
   e.printStackTrace();
  }finally{
   //关闭输入流
   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;
  }
 }
}

测试类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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("个数" + 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);
  
 }
}

以上内容如有任何问题或错误,恳请大家能给予意见,我会及时更正,谢谢大家。

本文的全部内容介绍完了,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/manzongpeng/article/details/77937683