InputStream 或 Reader。具有相同逻辑的方法
InputStream or Reader. Method with same logic
我需要实现相同的逻辑:比较文件使用 InputStream
以二进制形式进行比较,使用 Reader
以 unicode 进行比较。
我能以某种方式制作一个采用 InputStream
或 Reader
的方法,并与采用参数的 read()
方法执行相同的逻辑吗?
找不到这种情况的通配符,因为据我所知,InputStream
和 Reader
没有交互层次结构。
我需要一个采用 BufferedInputStream
或 BufferedReader
的方法。
您可以使用重载创建两个方法,这意味着每个方法都采用您想要支持的输入之一。
定义一个具有您需要从这两个方法访问的功能的接口,然后编写实现该接口的包装器 类(这些可以是相应方法中的匿名内部 类)。
将包装的输入传递给在接口上工作的内部私有处理方法,而不关心它可能包装的是什么。
这可以扩展为支持任意数量的不同类型的传入对象(只要可以包装它们),只需为每个对象添加一个新方法和一个新包装器即可。
一些或多或少通用的方法,您可以根据需要进行扩展。这个想法是将原始流通过管道传输到另一个流,以便在当前线程中读取原始流时由另一个线程读取。所以这里的 TeeInputStream
用于包装原始流并将流中的数据副本发送到 PipeOutputStream
。反过来,PipeOutputStream
正在被 PipeInputStream
读取,即单独线程中的 运行。流的内容是 "hashed" 通过 MD5 进行比较,当两个流都被完全读取时,但是您可以使用任何您想要比较字节数据的方法(差异等)。
这有点冗长,但如果您需要将流提供给 XML reader 并同时计算流的 CRC 或 MD5 校验和,则效果很好无需从流中读取两次。
import org.apache.commons.io.input.TeeInputStream;
import java.io.*;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Test1 {
private static final ExecutorService executor = Executors.newFixedThreadPool(2);
public static boolean compareStreams(InputStream is1, InputStream is2) throws Exception {
// create pipe that will copy data from is1 to pipe accessible by pis1
final PipedOutputStream pos1 = new PipedOutputStream();
final PipedInputStream pis1 = new PipedInputStream(pos1, 1024);
final TeeInputStream tee1 = new TeeInputStream(is1, pos1, true);
// create pipe that will copy data from is2 to pipe accessible by pis2
final PipedOutputStream pos2 = new PipedOutputStream();
final PipedInputStream pis2 = new PipedInputStream(pos2, 1024);
final TeeInputStream tee2 = new TeeInputStream(is2, pos2, true);
class Comparator implements Runnable {
private final InputStream is;
final MessageDigest md = MessageDigest.getInstance("MD5");
public Comparator(InputStream is) throws Exception {
this.is = is;
}
@Override
public void run() {
byte[] arr = new byte[1024];
int read = 0;
try {
while ((read = is.read(arr)) >= 0) {
md.update(arr, 0, read);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Comparator comparatorIs1 = new Comparator(pis1);
Future<?> f1 = executor.submit(comparatorIs1);
Comparator comparatorIs2 = new Comparator(pis2);
Future<?> f2 = executor.submit(comparatorIs2);
Reader r1 = new InputStreamReader(is1);
Reader r2 = new InputStreamReader(is2);
char[] c1 = new char[1024];
char[] c2 = new char[1024];
int read1 = 0;
int read2 = 0;
boolean supposeEquals = true;
while (supposeEquals) {
read1 = r1.read(c1);
read2 = r2.read(c2);
if (read1 != read2 || (read1 < 0 && read2 < 0)) {
break;
}
for (int i = 0; i < read1; i++) {
if (c1[i] != c2[i]) {
supposeEquals = false;
break;
}
}
}
f1.cancel(true);
f2.cancel(true);
return read1 == read2 && supposeEquals && Arrays.equals(comparatorIs1.md.digest(), comparatorIs2.md.digest());
}
public static void main(String[] args) throws Exception {
System.out.println("Comparison result : " + compareStreams(new ByteArrayInputStream("test string here".getBytes()), new ByteArrayInputStream("test string here".getBytes())));
System.out.println("Comparison result : " + compareStreams(new ByteArrayInputStream("test string test".getBytes()), new ByteArrayInputStream("test string here".getBytes())));
System.out.println("Comparison result : " + compareStreams(new ByteArrayInputStream("test".getBytes()), new ByteArrayInputStream("test string here".getBytes())));
}
}
我需要实现相同的逻辑:比较文件使用 InputStream
以二进制形式进行比较,使用 Reader
以 unicode 进行比较。
我能以某种方式制作一个采用 InputStream
或 Reader
的方法,并与采用参数的 read()
方法执行相同的逻辑吗?
找不到这种情况的通配符,因为据我所知,InputStream
和 Reader
没有交互层次结构。
我需要一个采用 BufferedInputStream
或 BufferedReader
的方法。
您可以使用重载创建两个方法,这意味着每个方法都采用您想要支持的输入之一。
定义一个具有您需要从这两个方法访问的功能的接口,然后编写实现该接口的包装器 类(这些可以是相应方法中的匿名内部 类)。
将包装的输入传递给在接口上工作的内部私有处理方法,而不关心它可能包装的是什么。
这可以扩展为支持任意数量的不同类型的传入对象(只要可以包装它们),只需为每个对象添加一个新方法和一个新包装器即可。
一些或多或少通用的方法,您可以根据需要进行扩展。这个想法是将原始流通过管道传输到另一个流,以便在当前线程中读取原始流时由另一个线程读取。所以这里的 TeeInputStream
用于包装原始流并将流中的数据副本发送到 PipeOutputStream
。反过来,PipeOutputStream
正在被 PipeInputStream
读取,即单独线程中的 运行。流的内容是 "hashed" 通过 MD5 进行比较,当两个流都被完全读取时,但是您可以使用任何您想要比较字节数据的方法(差异等)。
这有点冗长,但如果您需要将流提供给 XML reader 并同时计算流的 CRC 或 MD5 校验和,则效果很好无需从流中读取两次。
import org.apache.commons.io.input.TeeInputStream;
import java.io.*;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Test1 {
private static final ExecutorService executor = Executors.newFixedThreadPool(2);
public static boolean compareStreams(InputStream is1, InputStream is2) throws Exception {
// create pipe that will copy data from is1 to pipe accessible by pis1
final PipedOutputStream pos1 = new PipedOutputStream();
final PipedInputStream pis1 = new PipedInputStream(pos1, 1024);
final TeeInputStream tee1 = new TeeInputStream(is1, pos1, true);
// create pipe that will copy data from is2 to pipe accessible by pis2
final PipedOutputStream pos2 = new PipedOutputStream();
final PipedInputStream pis2 = new PipedInputStream(pos2, 1024);
final TeeInputStream tee2 = new TeeInputStream(is2, pos2, true);
class Comparator implements Runnable {
private final InputStream is;
final MessageDigest md = MessageDigest.getInstance("MD5");
public Comparator(InputStream is) throws Exception {
this.is = is;
}
@Override
public void run() {
byte[] arr = new byte[1024];
int read = 0;
try {
while ((read = is.read(arr)) >= 0) {
md.update(arr, 0, read);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Comparator comparatorIs1 = new Comparator(pis1);
Future<?> f1 = executor.submit(comparatorIs1);
Comparator comparatorIs2 = new Comparator(pis2);
Future<?> f2 = executor.submit(comparatorIs2);
Reader r1 = new InputStreamReader(is1);
Reader r2 = new InputStreamReader(is2);
char[] c1 = new char[1024];
char[] c2 = new char[1024];
int read1 = 0;
int read2 = 0;
boolean supposeEquals = true;
while (supposeEquals) {
read1 = r1.read(c1);
read2 = r2.read(c2);
if (read1 != read2 || (read1 < 0 && read2 < 0)) {
break;
}
for (int i = 0; i < read1; i++) {
if (c1[i] != c2[i]) {
supposeEquals = false;
break;
}
}
}
f1.cancel(true);
f2.cancel(true);
return read1 == read2 && supposeEquals && Arrays.equals(comparatorIs1.md.digest(), comparatorIs2.md.digest());
}
public static void main(String[] args) throws Exception {
System.out.println("Comparison result : " + compareStreams(new ByteArrayInputStream("test string here".getBytes()), new ByteArrayInputStream("test string here".getBytes())));
System.out.println("Comparison result : " + compareStreams(new ByteArrayInputStream("test string test".getBytes()), new ByteArrayInputStream("test string here".getBytes())));
System.out.println("Comparison result : " + compareStreams(new ByteArrayInputStream("test".getBytes()), new ByteArrayInputStream("test string here".getBytes())));
}
}