OSDN Git Service

Merge pull request #38 from dictzip/topic/miurahr/fix-dictzip-outputstream
[dictzip-java/dictzip-java.git] / dictzip-cli / src / test / java / tokyo / northside / io / IOUtils2.java
1 /*
2  * FileUtils library.
3  *
4  * Copyright (C) 2016 Hiroshi Miura
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 package tokyo.northside.io;
20
21 import java.io.InputStream;
22 import java.io.IOException;
23 import java.util.Arrays;
24
25 import org.apache.commons.io.IOUtils;
26
27 /**
28  * General IO stream manipulation utility.
29  * <p>
30  * This class provides static utility methods for input/output operations.
31  * <ul>
32  * <li>contentEquals - these methods compare the content of two streams
33  * </ul>
34  * <p>
35  * The methods in this class that read a stream are buffered internally.
36  * This means that there is no cause to use a <code>BufferedInputStream</code>
37  * or <code>BufferedReader</code>. The default buffer size of 4K has been shown
38  * to be efficient in tests.
39  * <p>
40  * Wherever possible, the methods in this class do <em>not</em> flush or close
41  * the stream. This is to avoid making non-portable assumptions about the
42  * streams' origin and further use. Thus the caller is still responsible for
43  * closing streams after use.
44  * <p>
45  * Created by Hiroshi Miura on 16/04/09.
46  *
47  * @author Hiroshi Miura
48  */
49 public final class IOUtils2 extends IOUtils {
50
51    private static final int BUF_LEN = 4096;
52
53     /**
54      * Compare the contents of two Streams to determine if they are equal or not.
55      *
56      * @param first  first input stream.
57      * @param second  second input stream.
58      * @param off     compare from offset
59      * @param len     comparison length
60      * @return boolean true if content of input streams are equal, true if streams are equal,
61      *     otherwise false.
62      * @throws IOException when I/O error occurred.
63      */
64     public static boolean contentEquals(final InputStream first, final InputStream second,
65             final long off, final long len) throws IOException {
66         boolean result;
67
68         if (len < 1) {
69             throw new IllegalArgumentException();
70         }
71         if (off < 0) {
72             throw new IllegalArgumentException();
73         }
74         if (first.equals(second)) {
75             return false;
76         }
77
78         try {
79             byte[] firstBytes = new byte[BUF_LEN];
80             byte[] secondBytes = new byte[BUF_LEN];
81
82             if (off > 0) {
83                 long totalSkipped = 0;
84                 while (totalSkipped < off) {
85                     long skipped = first.skip(off - totalSkipped);
86                     if (skipped == 0) {
87                         throw new IOException("Cannot seek offset bytes.");
88                     }
89                     totalSkipped += skipped;
90                 }
91                 totalSkipped = 0;
92                 while (totalSkipped < off) {
93                     long skipped = second.skip(off - totalSkipped);
94                     if (skipped == 0) {
95                         throw new IOException("Cannot seek offset bytes.");
96                     }
97                     totalSkipped += skipped;
98                 }
99             }
100
101             long readLengthTotal = 0;
102             result = true;
103             while (readLengthTotal < len) {
104                 int readLength = BUF_LEN;
105                 if (len - readLengthTotal < (long) BUF_LEN) {
106                     readLength = (int) (len - readLengthTotal);
107                 }
108                 int lenFirst = first.read(firstBytes, 0, readLength);
109                 int lenSecond = second.read(secondBytes, 0, readLength);
110                 if (lenFirst != lenSecond) {
111                     result = false;
112                     break;
113                 }
114                 if ((lenFirst < 0) && (lenSecond < 0)) {
115                     result = true;
116                     break;
117                 }
118                 readLengthTotal += lenFirst;
119                 if (lenFirst < firstBytes.length) {
120                     byte[] a = Arrays.copyOfRange(firstBytes, 0, lenFirst);
121                     byte[] b = Arrays.copyOfRange(secondBytes, 0, lenSecond);
122                     if (!Arrays.equals(a, b)) {
123                         result = false;
124                         break;
125                     }
126                 } else if (!Arrays.equals(firstBytes, secondBytes)) {
127                     result = false;
128                     break;
129                 }
130             }
131         } catch (RuntimeException e) {
132             throw e;
133         } catch (IOException ioe) {
134             throw ioe;
135         }
136         return result;
137     }
138
139     /**
140      * Static utility should not be instantiated.
141      */
142     private IOUtils2() {
143     }
144 }