在Java中,通过管道多次(基本上是2次)从stdin读取相同的数据

在Java中,通过管道多次(基本上是2次)从stdin读取相同的数据,java,pipe,Java,Pipe,我试图多次读取来自另一个命令输出的数据 我的命令是这样的:- cat input.txt | java -Xmx128m abcJavaFile | sort -k1,1 | java -Xmx128m xyzJavaFile inputTextFile > output.txt 现在,在xyzJavaFile中,我想将来自sort commmand的一些数据存储在一些变量中,然后再次访问管道输出,以对相同的数据进行处理 像这样:- BufferedReader consoleInput

我试图多次读取来自另一个命令输出的数据

我的命令是这样的:-

cat input.txt | java -Xmx128m abcJavaFile | sort -k1,1 | java -Xmx128m xyzJavaFile inputTextFile > output.txt
现在,在xyzJavaFile中,我想将来自sort commmand的一些数据存储在一些变量中,然后再次访问管道输出,以对相同的数据进行处理

像这样:-

BufferedReader consoleInput1 = new BufferedReader(new InputStreamReader(System.in));
String curDoc1 = null;
while((curDoc1 = consoleInput1.readLine()) != null) {
    //do something here
}

BufferedReader consoleInput2 = new BufferedReader(new InputStreamReader(System.in));
String curDoc2 = null;
while((curDoc2 = consoleInput2.readLine()) != null) {
    //again do something here
}

不可能,管道将数据流化。如果数据不太大,可以将其存储,或者在第一次读取数据时将其写入临时文件,然后在第二个处理步骤中使用该文件再次读取数据

BufferedReader consoleInput1 = new BufferedReader(new InputStreamReader(System.in));

String curDoc1 = null;
File temp = File.createTempFile("data", null);
try (BufferedWriter bw = Files.newBufferedWriter(temp.toPath())) {
    while((curDoc1 = consoleInput1.readLine()) != null) {
        doSomething(curDoc1);
        bw.write(curDoc1 + "\n");
    }
}

BufferedReader br = Files.newBufferedReader(temp.toPath());
String curDoc2 = null;
while((curDoc2 = br.readLine()) != null) {
    //again do something here
}

根据计算的性质,也可以将两个循环合并为一个循环。

如果您的输入不是超大的(相当小一点,小于128m),您可以将数据一次性读取到内存缓冲区中,然后根据需要从该缓冲区构建读卡器

// copy input into buffer
Reader reader = new InputStreamReader(System.in);
CharArrayWriter writer = new CharArrayWriter();
char[] transfer = new char[4096];
int count;
while ((count = reader.read(transfer)) != -1) {
    writer.write(transfer, 0, count);
}
char[] buffer = writer.toCharArray();

// use stream from buffer as often as you want
BufferedReader consoleInput1 = new BufferedReader(new CharArrayReader(buffer));
BufferedReader consoleInput2 = new BufferedReader(new CharArrayReader(buffer));
....
如果数据太大,您可以将数据存储在磁盘上:

File tempFile = File.createTempFile("data", ".tmp");
tempFile.deleteOnExit();

// copy input into buffer
Reader reader = new InputStreamReader(System.in);
try (Writer writer = new FileWriter(tempFile)) {
    char[] transfer = new char[4096];
    int count;
    while ((count = reader.read(transfer)) != -1) {
        writer.write(transfer, 0, count);
    }
}
// use stream from buffer as often as you want
BufferedReader consoleInput1 = new BufferedReader(new FileReader(tempFile));
BufferedReader consoleInput2 = new BufferedReader(new FileReader(tempFile));

你不能。第一次需要时保存它。我的input.txt文件大约是1.1gigs,xyzJavaFile的每行输入大约是100万字,即使我使用hashmap存储唯一的字,它也不适合128m限制。这就是为什么我要写入磁盘,所以没有存储在文件中的方法是不可能的。就像流媒体一样。是的,它还能是什么?如果它不完全在内存中,则必须进行流式处理。这完全取决于你在两个循环中做了什么,也许你可以简单地使用一个循环。那么,你可以在循环中详细说明代码,这样我们的答案就会有用吗?使用
BufferedWriter
?@Dici不是很有效。
transfer
缓冲区明确执行
Buffered???
在引擎盖下的操作。如果您使用一个,那么最终会将数据从一个缓冲区复制到另一个缓冲区。不过,将
transfer
的大小增加到64k可能会有好处。显然,默认的缓冲区大小是8k,因此您可以减少访问磁盘的次数,这将导致(我认为)更快的缓存loop@Dici是的,缓冲区越大越好。根据需要更改
transfer
s大小,并运行您自己的基准测试,以确定理想的大小。还有大量关于java实现这一点的不同方法的基准测试。喜欢或者,如果您知道需要将数据保存在文件中,让命令行代替java来执行,并在文件上运行java<代码>。|排序>foo.txt&&java。。foo.txt或so@Dici哎呀:)我没注意到