    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 */
    017package org.apache.commons.io.filefilter;
    018
    019import java.io.File;
    020import java.io.IOException;
    021import java.io.Serializable;
    022import java.nio.file.FileVisitResult;
    023import java.nio.file.Files;
    024import java.nio.file.Path;
    025import java.nio.file.attribute.BasicFileAttributes;
    026
    027/**
    028 * Filters files based on size, can filter either smaller files or
    029 * files equal to or larger than a given threshold.
    030 * <p>
    031 * For example, to print all files and directories in the
    032 * current directory whose size is greater than 1 MB:
    033 * </p>
    034 * <h2>Using Classic IO</h2>
    035 * <pre>
    036 * File dir = new File(".");
    037 * String[] files = dir.list(new SizeFileFilter(1024 * 1024));
    038 * for (String file : files) {
    039 *     System.out.println(file);
    040 * }
    041 * </pre>
    042 *
    043 * <h2>Using NIO</h2>
    044 * <pre>
    045 * final Path dir = Paths.get("");
    046 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new SizeFileFilter(1024 * 1024));
    047 * //
    048 * // Walk one dir
    049 * Files.<b>walkFileTree</b>(dir, Collections.emptySet(), 1, visitor);
    050 * System.out.println(visitor.getPathCounters());
    051 * System.out.println(visitor.getFileList());
    052 * //
    053 * visitor.getPathCounters().reset();
    054 * //
    055 * // Walk dir tree
    056 * Files.<b>walkFileTree</b>(dir, visitor);
    057 * System.out.println(visitor.getPathCounters());
    058 * System.out.println(visitor.getDirList());
    059 * System.out.println(visitor.getFileList());
    060 * </pre>
    061 *
    062 * @since 1.2
    063 * @see FileFilterUtils#sizeFileFilter(long)
    064 * @see FileFilterUtils#sizeFileFilter(long, boolean)
    065 * @see FileFilterUtils#sizeRangeFileFilter(long, long)
    066 */
    067public class SizeFileFilter extends AbstractFileFilter implements Serializable {
    068
    069    private static final long serialVersionUID = 7388077430788600069L;
    070
    071    /** Whether the files accepted will be larger or smaller. */
    072    private final boolean acceptLarger;
    073
    074    /** The size threshold. */
    075    private final long size;
    076
    077    /**
    078     * Constructs a new size file filter for files equal to or
    079     * larger than a certain size.
    080     *
    081     * @param size  the threshold size of the files
    082     * @throws IllegalArgumentException if the size is negative
    083     */
    084    public SizeFileFilter(final long size) {
    085        this(size, true);
    086    }
    087
    088    /**
    089     * Constructs a new size file filter for files based on a certain size
    090     * threshold.
    091     *
    092     * @param size  the threshold size of the files
    093     * @param acceptLarger  if true, files equal to or larger are accepted,
    094     * otherwise smaller ones (but not equal to)
    095     * @throws IllegalArgumentException if the size is negative
    096     */
    097    public SizeFileFilter(final long size, final boolean acceptLarger) {
    098        if (size < 0) {
    099            throw new IllegalArgumentException("The size must be non-negative");
    100        }
    101        this.size = size;
    102        this.acceptLarger = acceptLarger;
    103    }
    104
    105    /**
    106     * Checks to see if the size of the file is favorable.
    107     * <p>
    108     * If size equals threshold and smaller files are required,
    109     * file <b>IS NOT</b> selected.
    110     * If size equals threshold and larger files are required,
    111     * file <b>IS</b> selected.
    112     * </p>
    113     *
    114     * @param file  the File to check
    115     * @return true if the file name matches
    116     */
    117    @Override
    118    public boolean accept(final File file) {
    119        return accept(file.length());
    120    }
    121
    122    private boolean accept(final long length) {
    123        return acceptLarger != length < size;
    124    }
    125
    126    /**
    127     * Checks to see if the size of the file is favorable.
    128     * <p>
    129     * If size equals threshold and smaller files are required,
    130     * file <b>IS NOT</b> selected.
    131     * If size equals threshold and larger files are required,
    132     * file <b>IS</b> selected.
    133     * </p>
    134     * @param file  the File to check
    135     *
    136     * @return true if the file name matches
    137     */
    138    @Override
    139    public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) {
    140        try {
    141            return toFileVisitResult(accept(Files.size(file)), file);
    142        } catch (final IOException e) {
    143            return handle(e);
    144        }
    145    }
    146
    147    /**
    148     * Provide a String representation of this file filter.
    149     *
    150     * @return a String representation
    151     */
    152    @Override
    153    public String toString() {
    154        final String condition = acceptLarger ? ">=" : "<";
    155        return super.toString() + "(" + condition + size + ")";
    156    }
    157
    158    @Override
    159    public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
    160        return toFileVisitResult(accept(Files.size(file)), file);
    161    }
    162
    163}