我有一个文件,它由一行组成:
1 , 1 2 , 1 3 6 , 4 ,...
在此表示中,空格分隔整数和逗号。 这个字符串是如此巨大,我无法用RandomAccessFile.readLine()读取它(几乎需要4 Gb)。这样我就创建了一个缓冲区,它可以包含10个整数。我的任务是对字符串中的所有整数进行排序。
请你帮忙吗?
修改
@Oscar Reyes
我需要将一些整数序列写入文件然后从中读取。其实我不知道,怎么做。我是新手。所以我决定使用字符来编写整数,整数之间的分隔符是“,”,序列之间的分隔符是“\ n \ r”。所以我创造了一个读它的怪物:
public BinaryRow getFilledBuffer(String filePath, long offset) throws IOException{
mainFile = new RandomAccessFile(filePath, "r");
if (mainFile.length() == 0){
return new BinaryRow();
}
StringBuilder str = new StringBuilder();
mainFile.seek(mainFile.length()-4); //that is "\n" symbol
char chN = mainFile.readChar();
mainFile.seek(offset);
int i = 0;
char nextChar = mainFile.readChar();
while (i < 11 && nextChar != chN){
str.append(nextChar);
if (nextChar == ','){
i++;
if (i == 10){
break;
}
}
nextChar = mainFile.readChar();
}
if (nextChar == chN){
position = -1;
}else{
position = mainFile.getFilePointer();
}
BinaryRow br = new BinaryRow();
StringBuilder temp = new StringBuilder();
for (int j = 0; j < str.length(); j++){
if ((str.charAt(j) != ',')){
temp.append(str.charAt(j));
if (j == str.length() - 1){
br.add(Integer.parseInt(temp.toString()));
}
}else{
br.add(Integer.parseInt(temp.toString()));
temp.delete(0, temp.length());
}
}
mainFile.close();
return br;
}
如果你可以建议怎么做,请这样做=)
答案 0 :(得分:14)
这正是原点QuickSort,然后没有足够的RAM在内存中排序,所以他们的程序是将部分结果存储在磁盘中。
所以你可以做的是:
当零件足够小时(就像2直接交换它们足够在内存中分类)
通过这种方式,您可以对块进行排序并将部分结果存储在临时文件中,并且您将获得一个结果已排序的最终文件。
编辑我告诉你,快速排序是可能的。
毕竟,你似乎还需要额外的空间来存放临时文件。
这就是我的所作所为。
我创建了一个40 MB的文件,其中数字以逗号分隔。
我将其命名为input
:
input http://img200.imageshack.us/img200/5129/capturadepantalla201003t.png
输入为40mb
在排序期间,会创建桶大于“大于”,“低于”值的tmp文件,当排序完成时,这些值将被发送到一个名为(猜测是什么)的文件output
processing http://img200.imageshack.us/img200/1672/capturadepantalla201003y.png
使用部分结果
创建临时文件最后删除所有tmp文件,并将结果保存在文件“output”中,并使用正确的数字序列:
output http://img203.imageshack.us/img203/5950/capturadepantalla201003w.png
最后创建文件“output”,注意它也是40 mb
这是完整的计划。
import java.io.*;
import java.util.*;
public class FileQuickSort {
static final int MAX_SIZE = 1024*1024*16; // 16 megabytes in this sample, the more memory your program has, less disk writing will be used.
public static void main( String [] args ) throws IOException {
fileQuickSort( new File("input"), new File("output"));
System.out.println();
}
//
static void fileQuickSort( File inputFile, File outputFile ) throws IOException {
Scanner scanner = new Scanner( new BufferedInputStream( new FileInputStream( inputFile ), MAX_SIZE));
scanner.useDelimiter(",");
if( inputFile.length() > MAX_SIZE && scanner.hasNextInt()) {
System.out.print("-");
// put them in two buckets...
File lowerFile = File.createTempFile("quicksort-","-lower.tmp",new File("."));
File greaterFile = File.createTempFile("quicksort-","-greater.tmp", new File("."));
PrintStream lower = createPrintStream(lowerFile);
PrintStream greater = createPrintStream(greaterFile);
PrintStream target = null;
int pivot = scanner.nextInt();
// Read the file and put the values greater than in a file
// and the values lower than in other
while( scanner.hasNextInt() ){
int current = scanner.nextInt();
if( current < pivot ){
target = lower;
} else {
target = greater;
}
target.printf("%d,",current);
}
// avoid dropping the pivot
greater.printf("%d,",pivot);
// close the stream before reading them again
scanner.close();
lower.close();
greater.close();
// sort each part
fileQuickSort( lowerFile , outputFile );
lowerFile.delete();
fileQuickSort( greaterFile , outputFile);
greaterFile.delete();
// And you're done.
} else {
// Else , if you have enough RAM to process it
//
System.out.print(".");
List<Integer> smallFileIntegers = new ArrayList<Integer>();
// Read it
while( scanner.hasNextInt() ){
smallFileIntegers.add( scanner.nextInt() );
}
scanner.close();
// Sort them in memory
Collections.sort( smallFileIntegers );
PrintStream out = createPrintStream( outputFile);
for( int i : smallFileIntegers ) {
out.printf("%d,",i);
}
out.close();
// And your're done
}
}
private static PrintStream createPrintStream( File file ) throws IOException {
boolean append = true;
return new PrintStream( new BufferedOutputStream( new FileOutputStream( file, append )));
}
}
文件的格式为number,number,number,number
您当前的格式为:n u m b e r , n u m b , b e r
要解决这个问题,你只需要阅读全部内容并跳过空白即可。
为此添加另一个问题。
答案 1 :(得分:1)
以块(每个100 MB?)读取内存,一次一个块,对其进行排序并保存到磁盘。
然后打开所有有序的块,读取每个块的第一个元素,并将最低值附加到输出。然后阅读刚刚读取的块的下一个元素并重复。
合并时,您可以保留每个块中最后一个int读取的数组,然后迭代它以获得最低值。然后,将刚刚使用的值替换为取自它的块中的下一个元素。
example with chunks [1, 5, 16] [2, 9, 14] [3, 8, 10]
array [(1), 2, 3], lowest 1 --> to output
[5, (2), 3], lowest 2 --> to output
[5, 9, (3)], lowest 3 -->
[(5), 9, 8], 5
[16, 9, (8)], 8
[16, (9), 10], 9
...