View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.io;
19  
20  import java.io.IOException;
21  import java.io.RandomAccessFile;
22  import java.nio.channels.FileChannel;
23  import java.util.Objects;
24  
25  import org.apache.commons.io.channels.FileChannels;
26  
27  /**
28   * Works with {@link RandomAccessFile}.
29   *
30   * @since 2.13.0
31   */
32  public class RandomAccessFiles {
33  
34      /**
35       * Tests if two RandomAccessFile contents are equal.
36       *
37       * @param raf1 A RandomAccessFile.
38       * @param raf2 Another RandomAccessFile.
39       * @return true if the contents of both RandomAccessFiles are equal, false otherwise.
40       * @throws IOException if an I/O error occurs.
41       * @since 2.15.0
42       */
43      @SuppressWarnings("resource") // See comments
44      public static boolean contentEquals(final RandomAccessFile raf1, final RandomAccessFile raf2) throws IOException {
45          // Short-circuit test
46          if (Objects.equals(raf1, raf2)) {
47              return true;
48          }
49          // Short-circuit test
50          final long length1 = length(raf1);
51          final long length2 = length(raf2);
52          if (length1 != length2) {
53              return false;
54          }
55          if (length1 == 0 && length2 == 0) {
56              return true;
57          }
58          // Dig in and to the work
59          // We do not close FileChannels because that closes the owning RandomAccessFile.
60          // Instead, the caller is assumed to manage the given RandomAccessFile objects.
61          final FileChannel channel1 = raf1.getChannel();
62          final FileChannel channel2 = raf2.getChannel();
63          return FileChannels.contentEquals(channel1, channel2, IOUtils.DEFAULT_BUFFER_SIZE);
64      }
65  
66      private static long length(final RandomAccessFile raf) throws IOException {
67          return raf != null ? raf.length() : 0;
68      }
69  
70      /**
71       * Reads a byte array starting at "position" for "length" bytes.
72       *
73       * @param input    The source RandomAccessFile.
74       * @param position The offset position, measured in bytes from the beginning of the file, at which to set the file pointer.
75       * @param length   How many bytes to read.
76       * @return a new byte array.
77       * @throws IOException If the first byte cannot be read for any reason other than end of file, or if the random access file has been closed, or if some
78       *                     other I/O error occurs.
79       */
80      public static byte[] read(final RandomAccessFile input, final long position, final int length) throws IOException {
81          input.seek(position);
82          return IOUtils.toByteArray(input::read, length);
83      }
84  
85      /**
86       * Resets the given file to position 0.
87       *
88       * @param raf The RandomAccessFile to reset.
89       * @return The given RandomAccessFile.
90       * @throws IOException If {@code pos} is less than {@code 0} or if an I/O error occurs.
91       * @since 2.15.0
92       */
93      public static RandomAccessFile reset(final RandomAccessFile raf) throws IOException {
94          raf.seek(0);
95          return raf;
96      }
97  
98      /**
99       * Make private in 3.0.
100      *
101      * @deprecated TODO Make private in 3.0.
102      */
103     @Deprecated
104     public RandomAccessFiles() {
105         // empty
106     }
107 }