2015-11-23 55 views
2

我需要實現相同的邏輯:比較文件使用InputStream進行比較的二進制形式,和Reader比較unicode。 我可以不知何故做一個方法,採取InputStreamReader並採取相同的邏輯read()採取參數的方法。InputStream或Reader。具有相同邏輯的方法

找不到通配符,因爲我看到InputStreamReader沒有交互層次結構。

我需要一個方法,需要BufferedInputStreamBufferedReader

+0

你還需要一些共同的字符和字節... – wero

+0

這兩種情況下的邏輯實際上是否相同?你在比較什麼? –

回答

1

您可以使用重載創建兩個方法來表示每個方法都需要您想要支持的輸入之一。

定義一個接口,其中包含您需要從兩個方法訪問的功能,然後編寫實現該接口的包裝類(這些可以是相應方法中的匿名內部類)。

將包裝後的輸入傳遞給一個在接口上工作的內部私有處理方法,並且不關心它可能包裝什麼。

只需爲每個對象添加一個新的方法和一個新的包裝器,就可以擴展它來支持任意數量的不同類型的傳入對象(只要它們可以包裝它們)。

+0

有趣的解決方案。也許有人知道更簡單的方法? – serhii

+0

我很確定這是唯一的方法,如果他們沒有共同的繼承,那麼你的選擇是有限的。 –

+0

另一點。它應該採用兩個'InputrStream'或兩個'Reader'。如何實現這個想法? – serhii

1

一些或多或少的通用方法,您可以根據自己的需求進行擴展。這個想法是將原始流傳輸到另一個流,以便在當前線程中讀取原始流時由另一個線程讀取。所以TeeInputStream這裏用於包裝原始流並將數據流的副本發送到PipeOutputStreamPipeOutputStream正在被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()))); 
     } 

    }