Java IO 流 -- 随机读取和写入流 RandomAccessFile (文件分割和合并)

RandomAccessFile 相对其它流多了一个seek() 方法指定指针的偏移量。

1、指定起始位置读取剩余内容

public static void test01() throws IOException {
		RandomAccessFile raf = new RandomAccessFile("src/com/xzlf/io/CopyFile.java", "r");
		// 随机读取
		raf.seek(2);
		byte[] flush = new byte[1024];
		int len = -1;
		while((len=raf.read(flush)) != -1) {
			System.out.println(new String(flush,0,len));
		}
		raf.close();
	}

2、指定起始位置和实际大小

public static void test02() throws IOException {
		RandomAccessFile raf = new RandomAccessFile("src/com/xzlf/io/CopyFile.java", "r");
		// 起始位置
		int beginPos = 2+1026;
		// 实际大小
		int actualSize = 1026;
		// 随机操作
		raf.seek(beginPos);
		// 缓冲容器
		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();
	}

3、封装

package com.xzlf.io;

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.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class SplitFile {
	// 源头
	private File src;
	// 目的地
	private String destDir;
	// 所有分割后文件存储路劲
	List<String> destPath;
	// 每块大小
	int blockSize;
	// 块数
	int size;
	public SplitFile(String srcPaht, String destDir) {
		this(srcPaht, destDir, 1024);
	}
	
	public SplitFile(String srcPath, String destDir, int blockSize) {
		this.src = new File(srcPath);
		this.destDir = destDir;
		this.blockSize = blockSize;
		this.destPath = 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.destPath.add(this.destDir + "/" + i + "-" + this.src.getName());
		}	
	}
	
	/**
	 * 分割
	 * 1、计算每一块的起始位置及大小
	 * 2、分割
	 * @throws IOException
	 */
	public void split() throws IOException {
		File src = this.src;
		// 总长度
		long len = src.length();
		// 起始位置和实际大小
		int beginPos = 0;
		int actualSize = 0;
		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);
			splitDetail(i, beginPos, actualSize);
		}
	}
	
	/**
	 * 指定第 i 块、起始位置、实际长度
	 * @param i
	 * @param beginPos
	 * @param actualSize
	 * @throws IOException
	 */
	private void splitDetail(int i, int beginPos, int actualSize) throws IOException {
		RandomAccessFile raf = new RandomAccessFile(src, "r");
		RandomAccessFile raf2 = new RandomAccessFile(destPath.get(i), "rw");
		raf.seek(beginPos);
		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;
			}
		}
		raf.close();
		raf2.close();
	}
	
	/**
	 * 文件的合并
	 * @param destPaht
	 * @throws IOException 
	 */
	public void merge(String destPath) throws IOException {
		// 输出流
		OutputStream os = new BufferedOutputStream(new FileOutputStream(destPath, true));
		Vector<InputStream> vi = new Vector<InputStream>();
		
		// 输入流
		for (int i = 0; i < this.destPath.size(); i++) {
			vi.add(new BufferedInputStream(new FileInputStream(this.destPath.get(i))));
		}
		SequenceInputStream sis = new SequenceInputStream(vi.elements());
		// 文件拷贝
		byte[] flush = new byte[1024];
		int len = -1;
		while((len = sis.read(flush)) != -1) {
			os.write(flush, 0, len);
		}
		
		// 释放资源
		os.flush();
		os.close();
		sis.close();
	}
}

4、添加测试代码测试:

	public static void main(String[] args) throws IOException {
//		SplitFile sf = new SplitFile("src/com/xzlf/io/CopyFile.java", "dest");
		SplitFile sf = new SplitFile("水电费.png", "dest");
		sf.split();
//		sf.merge("CopyFile.java");
		sf.merge("水电费-merge.png");
	}
重视基础,才能走的更远。
原文地址:https://www.cnblogs.com/xzlf/p/12681532.html