目的:把一个磁盘中的文件进行切割成若干份文件,然后合并这些文件。
详细请点击:点击打开链接
思想一:
使用IO技术读取文件,没读1M文件就重新new一个文件,然后把数据放入新的文件中。注意:1M=1024*104字节,因为java的IO只有两大家族,一个为字节流,一个为字符流,如果选择字符流,那么就只能读取纯文本文件,不然会把数据丢失。于是选择字节流,那么字节流就只能用字节数组读取数据。不要问我为什么不用int数组读的问题,因为java的字节流只提供了字节数组的方法,其他的可以自己造(可以查看API)。
简易代码如下:
package outIn2.fileCutAndMerge2;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.swing.JFileChooser;
public class FileSplit {
public static int splitNumber = 1024 * 1024;// 一次切割1M
public static void main(String[] args) {
JFileChooser jf = new JFileChooser();
int result = jf.showOpenDialog(null);
File srcFile = null;
File dirFile = null;
if (result == JFileChooser.APPROVE_OPTION) {
srcFile = jf.getSelectedFile();
dirFile = new File("d:/ex/a/splitFile");
splitFile(srcFile, dirFile);
}
}
/*
* splitFile-切割文件
* srcFile-源文件
* dirFile-目标放置文件夹
*/
public static void splitFile(File srcFile, File dirFile) {
FileInputStream fin = null;
FileOutputStream fout = null;
// 使用File开道
if (!dirFile.exists()) {
dirFile.mkdirs();
}
try {
fin = new FileInputStream(srcFile);
String name1 = dirFile.getAbsoluteFile() + "/";
int count = 1;
fout = new FileOutputStream(name1 + count + ".part");
byte[] bys = new byte[splitNumber];
int len = 0;
while ((len = fin.read(bys)) != -1) {
fout.write(bys, 0, len);
fout.close();
if (len == splitNumber) {
fout = new FileOutputStream(name1 + (++count) + ".part");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fout != null) {
try {
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fin != null) {
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
思想二:
使用配置文件,将分割文件的绝对路径保存在配置文件中,那么下次合并时就变得简单了。
Java代码:
package outIn2.fileCutAndMerge2;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;
import javax.swing.JFileChooser;
public class FileSplit {
public static int splitNumber = 1024 * 1024;// 一次切割1M
public static void main(String[] args) {
JFileChooser jf = new JFileChooser();
int result = jf.showOpenDialog(null);
File srcFile = null;
File dirFile = null;
if (result == JFileChooser.APPROVE_OPTION) {
// 切割文件
srcFile = jf.getSelectedFile();
dirFile = new File("d:/ex/a/splitFile");// 可以自定义
splitFile(srcFile, dirFile);
// 合并文件
mergeFiles(dirFile, new File("d:/ex/b/splitFile"),
srcFile.getName());
}
}
/*
* splitFile-切割文件
* srcFile-源文件,可以得到源文件路径
* dirFile-目标放置文件夹,可以得到目标放置文件夹路径
*/
public static void splitFile(File srcFile, File dirFile) {
BufferedInputStream bin = null;
BufferedOutputStream bout = null;
BufferedOutputStream pout = null;
Properties pro = new Properties();
// 使用File开道
if (!dirFile.exists()) {
dirFile.mkdirs();
}
try {
// new出切割文件的读写流
bin = new BufferedInputStream(new FileInputStream(srcFile));
int count = 1;
String name1 = dirFile.getAbsoluteFile() + "/";
String name2 = name1 + count + ".part";
bout = new BufferedOutputStream(new FileOutputStream(name2));
/*
* 配置文件的写流,
* 写流是单独开一个,
* 因为要生成多个文件,说以不能用fout。
*/
pout = new BufferedOutputStream(new FileOutputStream(name1
+ "mySplitPro.Properties"));
/*
* 使用读写流
*/
byte[] bys = new byte[splitNumber];
int len = 0;
while ((len = bin.read(bys)) != -1) {
bout.write(bys, 0, len);
bout.close();
pro.setProperty("" + count, name2);
name2 = name1 + (++count) + ".part";
if (len == splitNumber) {
bout = new BufferedOutputStream(new FileOutputStream(name2));
}
}
/*
* 数据读取完了,就应该保存配置文件
* comment-评论记录文件的个数,
* 下次访问时,如果个数不对,
* 那么就不给用户合并文件。
*/
pro.store(pout, "" + (count - 1));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (pout != null) {
try {
pout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bout != null) {
try {
bout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bin != null) {
try {
bin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
* mergeFiles-合并文件
* dirFile-目录文件夹,可以得到目录文件夹路径
* newFile-合成新文件,可以得到合成新文件的路径
*/
public static boolean mergeFiles(File dirFile, File parentPath,
String fileName) {
// File开道
if (!parentPath.exists()) {
parentPath.mkdirs();
}
parentPath = new File(parentPath.getAbsolutePath(), fileName);
Properties pro = new Properties();
BufferedReader br = null;
BufferedInputStream[] bins = null;
SequenceInputStream se = null;
BufferedOutputStream bout = null;
try {
/*
* 从配置文件中读取数据的准备
*/
br = new BufferedReader(new FileReader(dirFile.getAbsoluteFile()
+ "/mySplitPro.Properties"));
String num = "";
String str = br.readLine();
for (int i = 1; i < str.length(); i++) {
num += str.charAt(i);
}
int count = 0;
try {
count = Integer.parseInt(num);
} catch (Exception e) {
System.out.println("文件个数解析异常");
}
pro.load(br);
/*
* 构造序列流
*/
ArrayList<BufferedInputStream> al = new ArrayList<BufferedInputStream>();
bins = new BufferedInputStream[count];
for (int i = 1; i <= bins.length; i++) {
try {
bins[i - 1] = new BufferedInputStream(new FileInputStream(
pro.getProperty("" + i)));
} catch (Exception e) {
return false;
}
al.add(bins[i - 1]);
}
Enumeration<BufferedInputStream> en = Collections.enumeration(al);
se = new SequenceInputStream(en);
bout = new BufferedOutputStream(new FileOutputStream(parentPath));
/*
* 序列流读取数据,
* bout写数据。
*/
byte[] bys = new byte[splitNumber];
int len = 0;
while ((len = se.read(bys)) != -1) {
bout.write(bys, 0, len);
}
} catch (Exception e) {
} finally {
for (int i = 0; i < bins.length; i++) {
if (bins[i] != null) {
try {
bins[i].close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (se != null) {
try {
se.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bout != null) {
try {
bout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
}
}