티스토리 뷰

Java

File Splitting 파일 자르기

나야 2009. 6. 21. 17:03
Personalized Web Search 와 관련해서 ODP(Open Directory Project) 를 참조하고 있습니다. 이 프로젝트에서는 구축된 웹페이지들의 계층구조를 RDF파일로 제공하고 있습니다. 문제는 이 파일이 너무 크다는 것입니다. 1.9GB와 700MB 정도 크기입니다.그래서 간단한 자바 프로그램을 작성하여 파일을 자르기로 했습니다. 싹둑. 검색해보면 '커다란 텍스트 파일을 편하게 잘라주는 프로그램, iHP TxT Split' 와 같은 글들을 찾을 수 있습니다. 어쨌든 연습 삼아 간단하게 자바로 코딩해보았습니다.

FileInputStream과 FileouputStream 을 사용해서 하나의 파일을 원하는 크기로(거의)  잘라주는 코드 입니다.
package kr.ac.uos.dmlab.odp.io.util;

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;

public class TextFileSplitter {
	public TextFileSplitter(File srcFile, String destDir) {
		this.srcFile= srcFile;		
		this.destDir= destDir;
	}
	
	private File srcFile;
	private String destDir;
	
	public void split(long preferedSize) {
		String fileName= srcFile.getName();
		
		long srcSize= srcFile.length();		
		long quotient= srcSize/preferedSize;
		int fileNoSpace= getFileNumberSpace(quotient+1);
		
		int fileNo= 0;		
					
		int buffSize= 9096;
		
		try {
			String firstFileName= destDir+formatFileName(fileName, fileNo, fileNoSpace); 
			FileOutputStream fos= new FileOutputStream(new File(firstFileName));
			System.out.println(firstFileName);
			OutputStream os= new BufferedOutputStream(fos);
									
			FileInputStream fis= new FileInputStream(srcFile);
			InputStream is= new BufferedInputStream(fis);
			
			byte buf[] = new byte[buffSize];
			int s = 0;
			long writtenSize= 0;
	
			while ( (s = is.read(buf, 0, buffSize)) > 0 ) {
				if (writtenSize > preferedSize) {
					writtenSize=0;
					fileNo++;					
					os.close();
					String outputFileName= destDir+formatFileName(fileName, fileNo, fileNoSpace);
					System.out.println(outputFileName);
					os= new BufferedOutputStream(new FileOutputStream(new File(outputFileName)));
					
				}
				os.write(buf, 0, s);
				writtenSize= writtenSize + s;
			}
			os.close();
			is.close();
			
			
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}  
	}
	
	private int getFileNumberSpace(long quotient) {
		if (quotient==0) {
			return 1;
		}
		
		int space= 0;
		while( quotient > 0) {
			quotient= quotient/10;
			space++;
		}
		return space;
	}
	
	private String formatFileName(String prefix, int fileNo, int fileNoSpace) {
		int space= fileNoSpace- getFileNumberSpace(fileNo);
		
		
		StringBuffer sb= new StringBuffer();
		
		sb.append(prefix+".part");
		for(int i=0; i< space; i++) {
			sb.append(0);
		}
		sb.append(fileNo);
		
		return sb.toString();
	}
	
		

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		TextFileSplitter splitter= new TextFileSplitter(new File("odp/structure.rdf.u8"), "odp/");
		splitter.split(20000000);
	}

}

split 메소드에서 소스 파일을 읽어와서 목적지 디렉터리에 파일을 씁니다. 
이 코드를 사용하면 대강 preferedSize와 비슷한 크기로 파일을 자를 수 있습니다. 
파일을 정확한 크기로 자르지 않는 이유는 그렇게 하려면 원하는 크기까지 쓰고 남은 부분을 따로 저장해놓았다가 다음 번에 쓰는 코드가 추가되어야 하는데, 정확한 크기로  잘라내야 할 이유는 없기 때문에 그냥 두었습니다. 귀차니즘....
클래스 명이 TextFileSplitter인데 그냥 FileSplitter가 맞겠네요.
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함