다음과 같은 내용이 도움이 될 수 있습니다. 이 코드는 먼저 소스 파일을 BufferedReader
으로 열고 첫 번째 행을 읽고 \t
에 대해이를 나눕니다.
결과 배열의 길이는 대상 파일의 줄 수입니다. FileHolder
의 새로운 배열이 생성됩니다. FileHolder
에는 기본적으로 파일 설명자가 있고 ByteBuffer
은 캐시로 사용됩니다 (각 단어를 모두 쓰지 않도록). 모든 소유자가 생성되면 첫 번째 줄이 작성됩니다.
그런 다음 원본 파일을 다시 읽고 빈 줄에 추가 할 모든 파일 소유자가 추가 될 때까지 한 줄씩 다시 나누십시오.
완료되면 대상 파일이 만들어지고 (마지막) 모든 FileHolder 인스턴스가 배열 순서대로 순서대로 작성됩니다.
다음은 샘플 코드입니다 (LONG, here도 있음). 확실히 개선 될 수 있지만 (리소스는 실제로 올바른 장소 등에서 닫히지 않습니다) 작동합니다. 275MB 파일을 약 25 초 만에 옮겨 놓고 (쿼드 코어 Q6600, 4GB RAM, x86_64 Linux 3.1.2-rc5) 64MB의 Sun (64 비트) JDK를 "flimsy"기본값으로 실행합니다 :
package net.sf.jpam;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.regex.Pattern;
public final class Test
{
private static final Pattern TAB = Pattern.compile("\t");
private static class FileHolder
{
private static final byte TABCHAR[] = "\t".getBytes();
// Size of the buffer size
private static final int BUFSZ = 32768;
// Format string for a file
private static final String FORMAT = "/home/fge/t2.txt.%d";
// The ByteBuffer
private final ByteBuffer buf = ByteBuffer.allocate(BUFSZ);
// The File object
private final File fd;
// RandomAccessFile
private final RandomAccessFile file;
FileHolder(final int index)
throws FileNotFoundException
{
final String name = String.format(FORMAT, index);
fd = new File(name);
file = new RandomAccessFile(fd, "rw");
}
public void write(final String s)
throws IOException
{
final byte[] b = s.getBytes();
if (buf.remaining() < b.length + TABCHAR.length)
flush();
buf.put(b).put(TABCHAR);
}
private void flush()
throws IOException
{
file.write(buf.array(), 0, buf.position());
buf.position(0);
}
public void copyTo(final RandomAccessFile dst)
throws IOException
{
flush();
final FileChannel source = file.getChannel();
final FileChannel destination = dst.getChannel();
source.force(false);
final long len = source.size() - TABCHAR.length;
source.transferTo(0, len, destination);
dst.writeBytes("\n");
}
public void tearDown()
throws IOException
{
file.close();
if (!fd.delete())
System.err.println("Failed to remove file " + fd);
}
@Override
public String toString()
{
return fd.toString();
}
}
public static void main(final String... args)
throws IOException
{
long before, after;
before = System.currentTimeMillis();
final Reader r = new FileReader("/home/fge/t.txt");
final BufferedReader reader = new BufferedReader(r);
/*
* Read first line, count the number of elements. All elements are
* separated by a single tab.
*/
String line = reader.readLine();
String[] elements = TAB.split(line);
final int nrLines = elements.length;
final FileHolder[] files = new FileHolder[nrLines];
/*
* Initialize file descriptors
*/
for (int i = 0; i < nrLines; i++)
files[i] = new FileHolder(i);
/*
* Write first lines, then all others
*/
writeOneLine(elements, files);
while ((line = reader.readLine()) != null) {
elements = TAB.split(line);
writeOneLine(elements, files);
}
reader.close();
r.close();
after = System.currentTimeMillis();
System.out.println("Read time: " + (after - before));
before = System.currentTimeMillis();
final RandomAccessFile out = new RandomAccessFile("/home/fge/t2.txt",
"rw");
for (final FileHolder file: files) {
file.copyTo(out);
file.tearDown();
}
out.getChannel().force(false);
out.close();
after = System.currentTimeMillis();
System.out.println("Write time: " + (after - before));
System.exit(0);
}
private static void writeOneLine(final String[] elements,
final FileHolder[] fdArray)
throws IOException
{
final int len = elements.length;
String element;
FileHolder file;
for (int index = 0; index < len; index++) {
element = elements[index];
file = fdArray[index];
file.write(element);
}
}
}
출처
2011-12-16 17:17:02
fge
결과 파일이 같은 이름을 원한다고 가정합니까? – fge
아니, 실제로는 파일의 복사본을 미리 만들 수는 있지만 그 반대는 이상적인 경우입니다. – geoffjentry
피봇 팅 (pivoting)이란 무엇입니까? – Nayuki