随机流——RandomAccessFile
支持读写随机访问文件,用字节流操作即可
重点方法:void seek(long pos)——设置文件指针偏移,从该文件的开头测量,发生下一次读取或写入
文件分割——直接打印
package com.io.cx3;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 随机读取和写入流 RandomAccessFile
*/
public class rand {
public static void main(String[] args) throws IOException {
//分多少块
File src = new File("src/com/io/cx3/rand.java");
//获取总长度
long len = src.length();
//每块大小
int blockSize =1024;
//有多少块
int size =(int) Math.ceil(len*1.0/blockSize);//向上取整
System.out.println(size);
//起始位置和实际大小
int beginPos = 0;
int actualSize = (int)(blockSize>len?len:blockSize);
for(int i=0;i<size;i++) {
beginPos = i*blockSize;
if(i==size-1) { //最后一块
actualSize = (int)len;
}else {
actualSize = blockSize;
len -=actualSize; //剩余量
}
System.out.println(i+"-->"+beginPos +"-->"+actualSize);
split(i,beginPos,actualSize);
}
}
/**
* 指定第i块的起始位置和实际长度
*/
public static void split(int i,int beginPos,int actualSize ) throws IOException {
RandomAccessFile raf =new RandomAccessFile(new File("src/com/io/cx3/rand.java"),"r");
//随机读取
raf.seek(beginPos);
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
if(actualSize>len) { //获取本次读取的所有内容
System.out.println(new String(flush,0,len));
actualSize -=len;
}else {
System.out.println(new String(flush,0,actualSize));
break;
}
}
raf.close();
}
//分开思想: 有起始和实际大小
public static void test2() throws IOException {
RandomAccessFile raf =new RandomAccessFile(new File("src/com/io/cx3/rand.java"),"r");
//起始位置
int beginPos =2;
//实际大小
int actualSize = 1026;
//随机读取
raf.seek(beginPos);
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
if(actualSize>len) { //获取本次读取的所有内容
System.out.println(new String(flush,0,len));
actualSize -=len;
}else {
System.out.println(new String(flush,0,actualSize));
break;
}
}
raf.close();
}
//指定起始位置,读取剩余所有内容
public static void test1() throws IOException {
RandomAccessFile raf =new RandomAccessFile(new File("src/com/io/cx3/rand.java"),"r");
//随机读取
raf.seek(2);//从第二个开始读取(0,1,2,3---)
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
System.out.println(new String(flush,0,len));
}
raf.close();
}
}
文件分割——大文件分割成多个小文件
package com.io.cx3;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 随机读取和写入流 RandomAccessFile
*/
public class rand2 {
public static void main(String[] args) throws IOException {
//分多少块
File src = new File("内存泄漏.JPG");
//总长度
long len = src.length();
//每块大小
int blockSize =1024*5;
//块数: 多少块
int size =(int) Math.ceil(len*1.0/blockSize);
System.out.println(size);
//起始位置和实际大小
int beginPos = 0;
int actualSize = (int)(blockSize>len?len:blockSize);
for(int i=0;i<size;i++) {
beginPos = i*blockSize;
if(i==size-1) { //最后一块
actualSize = (int)len;
}else {
actualSize = blockSize;
len -=actualSize; //剩余量
}
System.out.println(i+"-->"+beginPos +"-->"+actualSize);
split(i,beginPos,actualSize);
}
}
/**
* 指定第i块的起始位置 和实际长度
*/
public static void split(int i,int beginPos,int actualSize ) throws IOException {
RandomAccessFile raf =new RandomAccessFile(new File("内存泄漏.JPG"),"r");
RandomAccessFile raf2 =new RandomAccessFile(new File("text/"+i+"内存泄漏.JPG"),"rw");
//随机读取
raf.seek(beginPos);
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
if(actualSize>len) { //获取本次读取的所有内容
raf2.write(flush, 0, len);
actualSize -=len;
}else {
raf2.write(flush, 0, actualSize);
break;
}
}
raf2.close();
raf.close();
}
}
对上述代码进行封装(加入文件合并的代码):
package com.io.cx3;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
/**
* 面向对象思想封装 分割文件
*/
public class rand3 {
//源头
private File src;
//目的地(文件夹)
private String destDir;
//所有分割后的文件存储路径
private List<String> destPaths;
//每块大小
private int blockSize;
//块数: 多少块
private int size;
public rand3(String srcPath,String destDir) {
this(srcPath,destDir,1024);
}
public rand3(String srcPath,String destDir,int blockSize) {
this.src =new File(srcPath);
this.destDir =destDir;
this.blockSize =blockSize;
this.destPaths =new ArrayList<String>();
//初始化
init();
}
//初始化
private void init() {
//总长度
long len = this.src.length();
//块数: 多少块
this.size =(int) Math.ceil(len*1.0/blockSize);
//路径
for(int i=0;i<size;i++) {
this.destPaths.add(this.destDir +"/"+i+"-"+this.src.getName());
}
}
/**
* 分割
* 1、计算每一块的起始位置及大小
* 2、分割
*/
public void split() throws IOException {
//总长度
long len = src.length();
//起始位置和实际大小
int beginPos = 0;
int actualSize = (int)(blockSize>len?len:blockSize);
for(int i=0;i<size;i++) {
beginPos = i*blockSize;
if(i==size-1) { //最后一块
actualSize = (int)len;
}else {
actualSize = blockSize;
len -=actualSize; //剩余量
}
splitDetail(i,beginPos,actualSize);
}
}
/**
* 指定第i块的起始位置 和实际长度
*/
private void splitDetail(int i,int beginPos,int actualSize ) throws IOException {
RandomAccessFile raf =new RandomAccessFile(this.src,"r");
RandomAccessFile raf2 =new RandomAccessFile(this.destPaths.get(i),"rw");
//随机读取
raf.seek(beginPos);
//读取
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=raf.read(flush))!=-1) {
if(actualSize>len) { //获取本次读取的所有内容
raf2.write(flush, 0, len);
actualSize -=len;
}else {
raf2.write(flush, 0, actualSize);
break;
}
}
raf2.close();
raf.close();
}
/**
* 文件的合并
*/
public void merge(String destPath) throws IOException {
//输出流
OutputStream os =new BufferedOutputStream( new FileOutputStream(destPath,true));
Vector<InputStream> vi=new Vector<InputStream>();
SequenceInputStream sis =null;
//输入流
for(int i=0;i<destPaths.size();i++) {
vi.add(new BufferedInputStream(new FileInputStream(destPaths.get(i))));
}
sis =new SequenceInputStream(vi.elements());
//拷贝
//3、操作 (分段读取)
byte[] flush = new byte[1024]; //缓冲容器
int len = -1; //接收长度
while((len=sis.read(flush))!=-1) {
os.write(flush,0,len); //分段写出
}
os.flush();
sis.close();
os.close();
}
public static void main(String[] args) throws IOException {
rand3 sf = new rand3("src/com/io/cx3/rand.java","dest") ;
sf.split();
sf.merge("merge.java");
}
}
注:SequenceInputStream
表示其他输入流的逻辑级联。它从一个有序的输入流集合开始,从第一个读取到文件的结尾,然后从第二个文件读取,依此类推,直到最后一个输入流达到文件的结尾。
方法:SequenceInputStream(Enumeration<? extends InputStream> e)
初始化新创建 SequenceInputStream通过记住参数,它必须是一个 Enumeration产生对象,它们的运行时类型是 InputStream 。