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 contentEquals(final RandomAccessFile raf1, final RandomAccessFile raf2)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 length(final RandomAccessFile raf)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 */ read(final RandomAccessFile input, final long position, final int length)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 */ reset(final RandomAccessFile raf)93 public static RandomAccessFile reset(final RandomAccessFile raf) throws IOException { 94 raf.seek(0); 95 return raf; 96 } 97 98 } 99