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 * https://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 package org.apache.commons.io.filefilter;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.Serializable;
22 import java.nio.file.FileVisitResult;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25 import java.nio.file.attribute.BasicFileAttributes;
26
27 /**
28 * Filters files based on size, can filter either smaller files or
29 * files equal to or larger than a given threshold.
30 * <p>
31 * For example, to print all files and directories in the
32 * current directory whose size is greater than 1 MB:
33 * </p>
34 * <h2>Using Classic IO</h2>
35 * <pre>
36 * File dir = FileUtils.current();
37 * String[] files = dir.list(new SizeFileFilter(1024 * 1024));
38 * for (String file : files) {
39 * System.out.println(file);
40 * }
41 * </pre>
42 *
43 * <h2>Using NIO</h2>
44 * <pre>
45 * final Path dir = PathUtils.current();
46 * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new SizeFileFilter(1024 * 1024));
47 * //
48 * // Walk one directory
49 * Files.<strong>walkFileTree</strong>(dir, Collections.emptySet(), 1, visitor);
50 * System.out.println(visitor.getPathCounters());
51 * System.out.println(visitor.getFileList());
52 * //
53 * visitor.getPathCounters().reset();
54 * //
55 * // Walk directory tree
56 * Files.<strong>walkFileTree</strong>(dir, visitor);
57 * System.out.println(visitor.getPathCounters());
58 * System.out.println(visitor.getDirList());
59 * System.out.println(visitor.getFileList());
60 * </pre>
61 * <h2>Deprecating Serialization</h2>
62 * <p>
63 * <em>Serialization is deprecated and will be removed in 3.0.</em>
64 * </p>
65 *
66 * @since 1.2
67 * @see FileFilterUtils#sizeFileFilter(long)
68 * @see FileFilterUtils#sizeFileFilter(long, boolean)
69 * @see FileFilterUtils#sizeRangeFileFilter(long, long)
70 */
71 public class SizeFileFilter extends AbstractFileFilter implements Serializable {
72
73 private static final long serialVersionUID = 7388077430788600069L;
74
75 /** Whether the files accepted will be larger or smaller. */
76 private final boolean acceptLarger;
77
78 /** The size threshold. */
79 private final long size;
80
81 /**
82 * Constructs a new size file filter for files equal to or
83 * larger than a certain size.
84 *
85 * @param size the threshold size of the files.
86 * @throws IllegalArgumentException if the size is negative.
87 */
88 public SizeFileFilter(final long size) {
89 this(size, true);
90 }
91
92 /**
93 * Constructs a new size file filter for files based on a certain size
94 * threshold.
95 *
96 * @param size the threshold size of the files.
97 * @param acceptLarger if true, files equal to or larger are accepted,
98 * otherwise smaller ones (but not equal to).
99 * @throws IllegalArgumentException if the size is negative.
100 */
101 public SizeFileFilter(final long size, final boolean acceptLarger) {
102 if (size < 0) {
103 throw new IllegalArgumentException("The size must be non-negative");
104 }
105 this.size = size;
106 this.acceptLarger = acceptLarger;
107 }
108
109 /**
110 * Tests to see if the size of the file is favorable.
111 * <p>
112 * If size equals threshold and smaller files are required,
113 * file <strong>IS NOT</strong> selected.
114 * If size equals threshold and larger files are required,
115 * file <strong>IS</strong> selected.
116 * </p>
117 *
118 * @param file the File to check.
119 * @return true if the file name matches.
120 */
121 @Override
122 public boolean accept(final File file) {
123 return accept(file != null ? file.length() : 0);
124 }
125
126 private boolean accept(final long length) {
127 return acceptLarger != length < size;
128 }
129
130 /**
131 * Tests to see if the size of the file is favorable.
132 * <p>
133 * If size equals threshold and smaller files are required, file <strong>IS NOT</strong> selected. If size equals threshold and larger files are required,
134 * file <strong>IS</strong> selected.
135 * </p>
136 *
137 * @param file the File to check.
138 * @param attributes the path's basic attributes (may be null).
139 * @return true if the file name matches.
140 */
141 @Override
142 public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) {
143 return get(() -> toFileVisitResult(accept(Files.size(file))));
144 }
145
146 /**
147 * Provide a String representation of this file filter.
148 *
149 * @return a String representation.
150 */
151 @Override
152 public String toString() {
153 final String condition = acceptLarger ? ">=" : "<";
154 return super.toString() + "(" + condition + size + ")";
155 }
156
157 @Override
158 public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
159 return toFileVisitResult(accept(Files.size(file)));
160 }
161
162 }