Java 给定InputStream替换字符并生成OutputStream
我有很多海量文件需要通过替换某些字符转换为CSV 我正在寻找可靠的方法,给定InputStream返回OutputStream并将所有字符Java 给定InputStream替换字符并生成OutputStream,java,inputstream,outputstream,Java,Inputstream,Outputstream,我有很多海量文件需要通过替换某些字符转换为CSV 我正在寻找可靠的方法,给定InputStream返回OutputStream并将所有字符c1替换为c2 这里的诀窍是并行读写,我无法将整个文件放入内存中 如果我想同时读写,是否需要在单独的线程中运行它 非常感谢你的建议 要将数据从输入流复制到输出流,您需要在每次读取一个字节(或字符)或一行数据时写入数据 FileWriter writer = new FileWriter("Report.csv");
c1
替换为c2
这里的诀窍是并行读写,我无法将整个文件放入内存中
如果我想同时读写,是否需要在单独的线程中运行它
非常感谢你的建议 要将数据从输入流复制到输出流,您需要在每次读取一个字节(或字符)或一行数据时写入数据
FileWriter writer = new FileWriter("Report.csv");
BufferedReader reader = new BufferedReader(new InputStreamReader(YOURSOURCE, Charsets.UTF_8));
String line;
while ((line = reader.readLine()) != null) {
line.replace('c1', 'c2');
writer.append(line);
writer.append('\n');
}
writer.flush();
writer.close();
下面是一个示例,该示例读取一个文件,将所有“x”字符转换为“y”
BufferedInputStream in = new BufferedInputStream(new FileInputStream("input.dat"));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("output.dat"));
int ch;
while((ch = in.read()) != -1) {
if (ch == 'x') ch = 'y';
out.write(ch);
}
out.close();
in.close();
或者,如果可以使用读卡器并一次处理一行,则可以使用以下方法:
BufferedReader reader = new BufferedReader(new FileReader("input.dat"));
PrintWriter writer = new PrintWriter(
new BufferedOutputStream(new FileOutputStream("output.dat")));
String str;
while ((str = reader.readLine()) != null) {
str = str.replace('x', 'y'); // replace character at a time
str = str.replace("abc", "ABC"); // replace string sequence
writer.println(str);
}
writer.close();
reader.close();
BufferedInputStream和BufferedReader提前读取,并在缓冲区中保留8K字符以提高性能。可以处理非常大的文件,同时一次只能在内存中保留8K个字符。您可以在此处找到相关答案:
FileWriter writer = new FileWriter("Report.csv");
BufferedReader reader = new BufferedReader(new InputStreamReader(YOURSOURCE, Charsets.UTF_8));
String line;
while ((line = reader.readLine()) != null) {
line.replace('c1', 'c2');
writer.append(line);
writer.append('\n');
}
writer.flush();
writer.close();
我在该线程中接受了@aioobe的答案,并用Java构建了替换输入流模块,您可以在我的GitHub要点中找到它:
将源代码也放在这里:
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
/**
* Created by simon on 8/29/17.
*/
public class ReplacingInputStream extends FilterInputStream {
private Queue<Integer> inQueue, outQueue;
private final byte[] search, replacement;
public ReplacingInputStream(InputStream in, String search, String replacement) {
super(in);
this.inQueue = new LinkedList<>();
this.outQueue = new LinkedList<>();
this.search = search.getBytes();
this.replacement = replacement.getBytes();
}
private boolean isMatchFound() {
Iterator<Integer> iterator = inQueue.iterator();
for (byte b : search) {
if (!iterator.hasNext() || b != iterator.next()) {
return false;
}
}
return true;
}
private void readAhead() throws IOException {
// Work up some look-ahead.
while (inQueue.size() < search.length) {
int next = super.read();
inQueue.offer(next);
if (next == -1) {
break;
}
}
}
@Override
public int read() throws IOException {
// Next byte already determined.
while (outQueue.isEmpty()) {
readAhead();
if (isMatchFound()) {
for (byte a : search) {
inQueue.remove();
}
for (byte b : replacement) {
outQueue.offer((int) b);
}
} else {
outQueue.add(inQueue.remove());
}
}
return outQueue.remove();
}
@Override
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
// copied straight from InputStream inplementation, just needed to to use `read()` from this class
@Override
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
}
导入java.io.FilterInputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.util.Iterator;
导入java.util.LinkedList;
导入java.util.Queue;
/**
*西蒙于2017年8月29日创作。
*/
公共类ReplacingInputStream扩展FilterInputStream{
专用队列inQueue、outQueue;
专用最终字节[]搜索、替换;
公共ReplacingInputStream(输入流输入、字符串搜索、字符串替换){
超级(in),;
this.inQueue=newLinkedList();
this.outQueue=新建LinkedList();
this.search=search.getBytes();
this.replacement=replacement.getBytes();
}
私有布尔值isMatchFound(){
迭代器迭代器=inQueue.Iterator();
for(字节b:搜索){
如果(!iterator.hasNext()| | b!=iterator.next()){
返回false;
}
}
返回true;
}
私有void readAhead()引发IOException{
//制定一些前瞻性的计划。
while(inQueue.size()b.长度-off){
抛出新的IndexOutOfBoundsException();
}else if(len==0){
返回0;
}
int c=read();
如果(c==-1){
返回-1;
}
b[关]=(字节)c;
int i=1;
试一试{
对于(;i
InputStream为您提供字节。如果您知道自己的编码,您可以使用读取器获取字符。然后,您可以在每个字符经过时查看它,并根据需要进行替换。是的。非常感谢。我在想,是否已经有任何预构建解决方案可用?也许。到目前为止你在找什么?好的,太好了,谢谢!但是我如何并行读写呢?我无法将整个文件放在内存中。如果一次处理一个字节或一行处理一个文件,Java就不会将整个文件放在内存中。上面的BufferedInputStream和BufferedReader在读取时会在内存中保留一个小缓存,因此在读取时只存储8K的文件。不需要并行化方法,除非文件大小为多个terrabytes,并且希望将文件分成块。您可以创建一个reader/writer作业类来处理特定文件,并创建n个线程,其中每个线程一次处理一个文件并重复,直到完成。