Java 输入流或读取器。具有相同逻辑的方法

Java 输入流或读取器。具有相同逻辑的方法,java,io,inputstream,filereader,Java,Io,Inputstream,Filereader,我需要实现相同的逻辑:使用InputStream比较二进制格式的文件,使用Reader比较unicode格式的文件。 我是否可以创建一个方法,该方法采用InputStream或Reader,并对参数采用的read()方法执行相同的逻辑 在这种情况下找不到通配符,因为我看到,InputStream和Reader没有交互层次结构 我需要一个接受BufferedInputStream或BufferedReader的方法。您可以使用重载创建两个方法,这意味着每个方法接受一个您想要支持的输入 定义一个具有

我需要实现相同的逻辑:使用
InputStream
比较二进制格式的文件,使用
Reader
比较unicode格式的文件。 我是否可以创建一个方法,该方法采用
InputStream
Reader
,并对参数采用的
read()
方法执行相同的逻辑

在这种情况下找不到通配符,因为我看到,
InputStream
Reader
没有交互层次结构


我需要一个接受
BufferedInputStream
BufferedReader

的方法。您可以使用重载创建两个方法,这意味着每个方法接受一个您想要支持的输入

定义一个具有需要从这两个方法访问的功能的接口,然后编写实现该接口的包装器类(它们可以是相应方法中的匿名内部类)

将包装好的输入传递给内部私有处理方法,该方法在接口上工作,而不关心包装的内容


只需为每个对象添加一个新方法和一个新包装器,就可以将其扩展为支持任意数量的不同类型的传入对象(只要有可能包装它们)。

一些或多或少通用的方法,您可以根据需要进行扩展。其思想是在当前线程中读取原始流的同时,将原始流通过管道传输到另一个流以供另一个线程读取。因此这里使用
TeeInputStream
包装原始流,并将数据副本从流发送到
PipeOutputStream
。反过来,
PipeOutputStream
被运行在单独线程中的
PipeInputStream
读取。流的内容被MD5“散列”,以便在两个流被完全读取时进行比较,但是您可以使用任何您想要比较字节数据的方法(差异等)

这有点冗长,但在需要将流馈送到XML读取器并同时计算流的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())));
        }

    }
import org.apache.commons.io.input.TeeInputStream;
导入java.io.*;
导入java.security.MessageDigest;
导入java.util.array;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.Future;
公共类Test1{
private static final ExecutorService executor=Executors.newFixedThreadPool(2);
公共静态布尔比较流(InputStream为1,InputStream为2)引发异常{
//创建将数据从is1复制到pis1可访问的管道的管道
final PipedOutputStream pos1=新的PipedOutputStream();
最终PipedInputStream pis1=新的PipedInputStream(位置1024);
最终TeeInputStream tee1=新的TeeInputStream(is1,pos1,true);
//创建将数据从is2复制到pis2可访问的管道的管道
final PipedOutputStream pos2=新的PipedOutputStream();
最终PipedInputStream pis2=新的PipedInputStream(位置2,1024);
最终的TeeInputStream tee2=新的TeeInputStream(is2,pos2,true);
类比较器实现可运行{
私有最终输入流为;
final MessageDigest md=MessageDigest.getInstance(“MD5”);
公共比较器(InputStream is)引发异常{
this.is=is;
}
@凌驾
公开募捐{
字节[]arr=新字节[1024];
int read=0;
试一试{
而((read=is.read(arr))>=0){
md.update(arr,0,读取);
}
}捕获(IOE异常){
抛出新的运行时异常(e);
}
}
}
比较器比较器1=新比较器(pis1);
未来f1=执行人提交(比较器1);
比较器比较器2=新比较器(pis2);
未来f2=执行人提交(比较2);
读卡器r1=新的InputStreamReader(is1);
读卡器r2=新的InputStreamReader(is2);
char[]c1=新字符[1024];
char[]c2=新字符[1024];
int read1=0;
int read2=0;
布尔值=真;
while(假设相等){
read1=r1。read(c1);
read2=r2.read(c2);
if(read1!=read2 | |(read1<0&&read2<0)){
打破
}
for(int i=0;i
您还需要一些字符和字节的共同点……这两种情况下的逻辑是否完全相同?你在比较什么?有趣的解决方案。也许有人知道