(Java)文件分割器

这是一道面试题,题意如图所示:






参考文献地址是http://www.cnblogs.com/yjmyzz/p/how-to-split-a-large-file-into-small-files-fastly.html


以上这篇参考文献对我帮助很大。文件分割部分基本是按照他的方法来改的,不过它是采用的多线程,我没有采用多线程。

既然不能利用文件名,那么就需要把顺序信息存到文件中去,分割后每个文件前五个字节表示顺序,其中第一个文件后面还有五个字节表示总共有多少个文件,再后面还有50个字节表示原文件名。我后来想如果在每个文件里都加上总共有多少个文件也许更好,处理起来会更简单,因为我这里还要单独处理万一少了第一个文件的情况。


分割就是将文件按照前五个字节排序之后,去除后加入的信息,再写入就可以了。我之前有个错误就是将第一个文件的读到的byte[]转换为String处理后加入的信息,再转回回byte[]进行写入,会产生错误,直接用读到的byte[]写就解决了~that's all ~不是很难,就是比较麻烦,而且不熟练。


package lzz;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Map;
import java.util.TreeMap;

public class FileUtilNew {

	/**
     * 当前目录路径
     */
	public static String currentWorkDir = System.getProperty("user.dir") + "\\";
	
    /**
     * 存放分割后文件目录
     */
    public static String splitDir = "F:\\files\\";
    
    
    
    /**
     * 拆分文件
     * 
     * @param fileName
     *            待拆分的完整文件名
     * @param partNumber
     *            拆分成多少部分
     * @throws IOException
     */
    public void splitByNum(String fileName, int partNumber)throws IOException {
        File file = new File(fileName);
        long totalLen = file.length();
        int averLen = (int)(totalLen / partNumber);
        int lastLen = (int)(totalLen - averLen * (partNumber - 1));
        System.out.println(averLen + " " + lastLen);

        String filePre = "00001" + leftFill(String.valueOf(partNumber)) + leftFillFileName(file.getName());
        executeSplit(averLen, 0, filePre, file);
        for (int i = 2; i < partNumber; i++) {
            filePre  = leftFill(String.valueOf(i));
            executeSplit(averLen, (i - 1) * averLen, filePre, file);
        }
        filePre = leftFill(String.valueOf(partNumber));
        executeSplit(lastLen, (partNumber - 1) * averLen, filePre, file);
    }
    
    /**
     * 合并文件
     * 
     * @param dirPath
     *            拆分文件所在目录名
     * @throws FileNotFoundException 
     * @throws IOException
     */
    public void mergePartFiles(String dirPath) throws IOException{
    	File path = new File(dirPath);
        File[] files = path.listFiles();
        int fileNumber = files.length;
        Map<Integer,File> map = new TreeMap<Integer,File>();
        for(int i = 0; i < fileNumber; i++){
        	FileInputStream fs = new FileInputStream(files[i]);
            byte[] b = new byte[5];
            fs.read(b);
            fs.close();
            int index = Integer.parseInt(new String(b));
            map.put(index, files[i]);
        }
        File fileFir = map.get(1);
        FileInputStream fis = new FileInputStream(fileFir);
        byte[] b = new byte[(int)fileFir.length()];
        fis.read(b);
        fis.close();
        int splitNum = Integer.parseInt(new String(b,5, 5));
        if(splitNum != fileNumber){
        	System.out.println("File Lose!");
        	return;
        }
        String fileName = "";
        for(int i = 10; i < 60; i++){
        	if(b[i] != '.'){
        		fileName = new String(b,i,60-i);
        		break;
        	}
        }
        FileOutputStream fos = new FileOutputStream(dirPath + fileName);
        fos.write(b, 60, b.length-60);
        map.remove(1);
        
        int len = 0;
        byte[] con = null;
        for(Map.Entry<Integer, File> entry : map.entrySet()){
        	FileInputStream fs = new FileInputStream(entry.getValue());
        	len = (int)entry.getValue().length();
            con = new byte[len];
            fs.read(con);
            fs.close();
            fos.write(con, 5, len-5);
        }
        fos.close();
        
    }
    

	private void executeSplit(int byteSize, int startPos, String partFileIndex,File originFile){
    	RandomAccessFile rFile;
        OutputStream os;
        try {
            rFile = new RandomAccessFile(originFile, "r");
            byte[] b = new byte[byteSize];
            rFile.seek(startPos);// 移动指针到每“段”开头
            int s = rFile.read(b);
            os = new FileOutputStream(splitDir + partFileIndex.substring(0,5));
            os.write(partFileIndex.getBytes());
            os.write(b, 0, s);
            os.flush();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    private String leftFill(String index){
    	int zeroNum = 5 - index.length();
    	StringBuilder sb = new StringBuilder("");
    	for(int i = 0; i < zeroNum; i++){
    		sb.append("0");
    	}
    	sb.append(index);
    	return sb.toString();
    }
    private String leftFillFileName(String name) {
    	// TODO Auto-generated method stub
    	int dotNum = 50 - name.length();
    	StringBuilder sb = new StringBuilder("");
    	for(int i = 0; i < dotNum; i++){
    		sb.append(".");
    	}
    	sb.append(name);
    	return sb.toString();
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值