001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.io.channels; 019 020import java.io.IOException; 021import java.nio.ByteBuffer; 022import java.nio.channels.FileChannel; 023import java.util.Objects; 024 025import org.apache.commons.io.IOUtils; 026 027/** 028 * Works with {@link FileChannel}. 029 * 030 * @since 2.15.0 031 */ 032public final class FileChannels { 033 034 /** 035 * Tests if two RandomAccessFiles contents are equal. 036 * 037 * @param channel1 A FileChannel. 038 * @param channel2 Another FileChannel. 039 * @param byteBufferSize The two internal buffer capacities, in bytes. 040 * @return true if the contents of both RandomAccessFiles are equal, false otherwise. 041 * @throws IOException if an I/O error occurs. 042 */ 043 public static boolean contentEquals(final FileChannel channel1, final FileChannel channel2, final int byteBufferSize) throws IOException { 044 // Short-circuit test 045 if (Objects.equals(channel1, channel2)) { 046 return true; 047 } 048 // Short-circuit test 049 final long size1 = size(channel1); 050 final long size2 = size(channel2); 051 if (size1 != size2) { 052 return false; 053 } 054 if (size1 == 0 && size2 == 0) { 055 return true; 056 } 057 // Dig in and do the work 058 final ByteBuffer byteBuffer1 = ByteBuffer.allocateDirect(byteBufferSize); 059 final ByteBuffer byteBuffer2 = ByteBuffer.allocateDirect(byteBufferSize); 060 while (true) { 061 final int read1 = channel1.read(byteBuffer1); 062 final int read2 = channel2.read(byteBuffer2); 063 byteBuffer1.clear(); 064 byteBuffer2.clear(); 065 if (read1 == IOUtils.EOF && read2 == IOUtils.EOF) { 066 return byteBuffer1.equals(byteBuffer2); 067 } 068 if (read1 != read2) { 069 return false; 070 } 071 if (!byteBuffer1.equals(byteBuffer2)) { 072 return false; 073 } 074 } 075 } 076 077 private static long size(final FileChannel channel) throws IOException { 078 return channel != null ? channel.size() : 0; 079 } 080 081 /** 082 * Don't instantiate. 083 */ 084 private FileChannels() { 085 // no-op 086 } 087}