基本思路:

文件分割:将一个文件分割成若干个独立的文件。

       设置分割后小文件文件的字节数,然后读取被分割文件,

     将对应的字节数写入分割后的小文件中。

        使用seek定位下一次读取位置。

     

文件合并:将分割后的若干的文件合并成一个完整的文件。

     按照原有分割顺序逐个读取分割后的小文件,

     然后以追加的方式写入合并的文件中。

读取被分割文件将指定字节数写入分割后小文件时,下一次读取时要确保当前读取位置是上一次的写入的终点。

例如文件有5000K,设置分割后的文件大小1000K,那么第一次从0开始读取1000K写入小文件1,第二次就要从1000开始读取1000K写入小文件2.

这时就需要用到seek()不断设置文件读取位置。

seek是RandomAccessFile类中的函数

构造方法,mode为设置读写方法,“”r“为只读”w”为只写。

设置文件指针偏移量,下一次读或写时,从当前设置的位置开始。

read,write方法与输入输出流函数相同。

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.OutputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List; public class FileSplit {
private String filePath;//文件路径
private long blockSize;//每一块大小
private int blockNum;//块个个数
private List<String> blockName;//每一块名称
private String [] name;
public FileSplit(){
this.blockName = new ArrayList<String>();
} public FileSplit(String filePath){
this(filePath,1024);//未知的尺寸则默认1024
}
public FileSplit(String filePath, long blockSize){
this();
this.filePath = filePath;
this.blockSize = blockSize;
init();
} public String getFilePath() {
return filePath;
} public void setFilePath(String filePath) {
this.filePath = filePath;
} public long getBlockSize() {
return blockSize;
} public void setBlockSize(long blockSize) {
this.blockSize = blockSize;
} public int getBlockNum() {
return blockNum;
} public void setBlockNum(int blockNum) {
this.blockNum = blockNum;
} public List<String> getBlockName() {
return blockName;
} public void setBlockName(List<String> blockName) {
this.blockName = blockName;
} private void initBlockName(String destPath){
name = new File(filePath).getName().split("\\.");
for(int i = 0; i < blockNum; i++){
blockName.add(i,destPath + "\\" + name[0] + "_" + i + "." +name[1]);
}
} public void init(){
File src = new File(filePath);
//路径名不存在,或该路径表示的文件不存,或是文件夹在则结束。
if(filePath == null || !src.exists()||src.isDirectory()){
return;
}
if(blockSize >= src.length())
this.blockSize = src.length();
this.blockNum = (int)Math.ceil(src.length()*1.0/blockSize); }
//destPath分割文件存放目录
public void split(String destPath){//分割函数
initBlockName(destPath);//初始化分割后的文件名
long start = 0;
for(int i = 0; i < blockNum; i++){
if(i == blockNum - 1)//计算最后一块大小
blockSize = new File(filePath).length()%blockSize;
split_m(i,start,blockSize);//参数含义:第i块,读取位置,读取内容大小
start += blockSize;//更新起始位置
// System.out.println(start);
}
} //开始分割,每次分割一块
private void split_m(int blockNum,long start,long blockSize){
int len = 0;
byte[] flush = new byte[1024];
RandomAccessFile raf = null;//源文件
BufferedOutputStream bos = null;//分割后文件
try {
bos = new BufferedOutputStream(new FileOutputStream(new File(blockName.get(blockNum))));
raf = new RandomAccessFile(new File(filePath),"r");
try {
raf.seek(start);//确定读取位置
while(-1 != (len = raf.read(flush))){//当前块分割完成或文件已读取完跳出循环。
//System.out.printf("%d %d %d %s\n",start,blockSize,len,blockName.get(blockNum));
if((blockSize - len) >=0){//当前块大小-写入字节数,判断剩余字节
bos.write(flush,0,len);//如果块剩余大小大于读取字节数,则写入读取字节数
blockSize -= len;
}else{//如果小于,则写入当前块剩余字节数
bos.write(flush, 0, (int)blockSize);
break;//分块文件已写满,跳出当前循环
}
}
bos.flush();
bos.close();
raf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public void Merge(String mergePath){//合并文件夹路径
int len;
byte[] flush = new byte[1024];
InputStream is = null;
OutputStream bos = null;
for(int i = 0; i < blockNum; i++){
try {
//每次将一个分割后的文件写入合并文件中。
//写入方法为追加
bos = new BufferedOutputStream(new FileOutputStream(new File(mergePath,"merge." + name[1]),true));
is = new BufferedInputStream(new FileInputStream(new File(blockName.get(i))));
while(-1 != (len = is.read(flush))){//直到被分割的单个小文件读取完
is.read(flush);//将读取内容放入flush
bos.write(flush,0,len);//将读取内容写入文件。
}
bos.flush();
bos.close();
is.close();//释放当前资源,下次读取下一个小文件。
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
}
public class Main {
public static void main(String[] args){
FileSplit f = new FileSplit("F:\\依风\\Desktop\\temp.txt",500);//被分割文件,分割后的字节数
f.split("F:\\依风\\Desktop");//分割后小文件的存放位置
f.Merge("F:\\依风\\Desktop");//合并后大文件的存放位置
}
}

6.6(java学习笔记)文件分割(IO综合例子)的更多相关文章

  1. Java学习笔记31(IO:Properties类)

    Properties类,表示一个持久的j集,可以存在流中,或者从流中加载 是Hashtable的子类 map集合的方法都能用 用途之一:在开发项目中,我们最后交给客户的是一个编译过的class文件,客 ...

  2. Java学习笔记--文件IO

    简介 对于任何程序设计语言,输入和输出(Input\Output)都是系统非常核心的功能,程序运行需要数据,而数据的获取往往需要跟外部系统进行通信,外部系统可能是文件.数据库.其他程序.网络.IO设备 ...

  3. Java学习笔记7(IO)

    IO(输入输出) IO流按照操作数据的不同,分为字节流和字符流,按照数据传输方向分为输入流和输出流. 字节流 计算机中,所有文件都是以二进制(字节)形式存在,IO流中针对字节的输入输出提供了一系列的流 ...

  4. Java学习笔记33(IO:打印流,IO流工具类)

    打印流: 有两个类:PrintStream     PrintWriter类,两个类的方法一样,构造方法不一样 PrintStream构造方法:接收File类型,接收字符串文件名,接收字节输出流(Ou ...

  5. Java学习笔记32(IO:序列化流)

    对象中的数据 ,以流的形式,写入到文件中保存,过程称为写出对象,对象的序列化 ObjectOutputStream将对象写到序列中,实现序列化 在文件中,以流 的形式,将对象读取出来,过程称为读取对象 ...

  6. java学习笔记30(IO :缓冲流)

    缓冲流: 读取数据大量的文件时,读取的速度慢,java提供了一套缓冲流,提高IO流的效率: 缓冲流分为字节缓冲流和字符缓冲流: 字节输入缓冲流和字节输出缓冲流如下: package com.zs.De ...

  7. Java学习笔记29(IO字符流,转换流)

    字符流:只能操作文本文件,与字节流的区别是,字节流是按照字节来读取文件,而字符流是按照字符来读取,因此字符流的局限性为文本文件 字符输出流:Write类,使用时通过子类   每一次写入都要刷新 pac ...

  8. Java学习笔记28(IO字节流)

    IO定义: 写:Output操作:将内存上的数据持久化 到设备上,这个动作称为输出: 读:Input操作:把硬盘上的东西读取到内存,这个动作称为输入:              这两种操作称为IO流 ...

  9. Java学习笔记-文件读写和Json数组

    Java文件读写 Java中I/O流对文件的读写有很多种方法,百度后主要看了以下三种 第一种方式:使用FileWriter和FileReader,对文件内容按字符读取,代码如下 String dir ...

随机推荐

  1. bzoj 4004 [JLOI2015]装备购买 拟阵+线性基

    [JLOI2015]装备购买 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1820  Solved: 547[Submit][Status][Dis ...

  2. PRINT_TABLE 列以行形式显示

    在sqlplus,如果列比较多,往往会显示不够清晰,这时如果能把查询语句行转列就明了多了,在网上看到print_table存储过程:里面所设置的日期格式,可根据自己习惯修改 CREATE OR REP ...

  3. Step-By-Step: Setting up Active Directory in Windows Server 2016

    There are interesting new features now made available in Windows Server 2016 such as time based grou ...

  4. 51Nod 1421

    1421 最大MOD值 有一个a数组,里面有n个整数.现在要从中找到两个数字(可以是同一个) ai,aj ,使得 ai mod aj 最大并且 ai ≥ aj. Input 单组测试数据. 第一行包含 ...

  5. CCCC练习即感

    字符串进行初始化时不能通过char a[10]={'\0'}来简单进行,写循环或者memset,亲测有效,以及初始化分好情况,用空格还是'\0',别乱搞. 有一个有意思的题,连续因子,从2开始,依次向 ...

  6. 2017年上海金马五校程序设计竞赛:Problem E : Find Palindrome (字符串处理)

    Description Given a string S, which consists of lowercase characters, you need to find the longest p ...

  7. 小白科普之JavaScript的DOM模型

    微信公众号“前端大全”推送了一篇名为“通俗易懂的来讲讲DOM”的文章,把javascript原生DOM相关内容讲解的很详细.仔细读了一遍,觉得整理总结的不错,对自己也很使用,所以把内容整理过来,并根据 ...

  8. Selenium菜鸟手册

    转自: http://www.iselenium.com/read.php?tid=458 首先声明我还是一只很菜的菜鸟,学习Selenium一个来月而已,发这个帖子是想利用我这块板砖引出真正的玉来, ...

  9. linux驱动基础系列--linux rtc子系统

    前言 linux驱动子系统太多了,连时钟也搞了个子系统,这导致一般的时钟芯片的驱动也会涉及到至少2个子系统,一个是时钟芯片接口子系统(比如I2c接口的时钟芯片),一个是内核给所有时钟芯片提供的rtc子 ...

  10. 开源的zip_unzip库

    zip/unzip源码交叉编译 http://blog.chinaunix.net/uid-20288609-id-10016.html zlib 1.2.11 http://www.zlib.net ...