尝试获取扩展名为“java”的最大尺寸的文件名

Trying to get file name with the largest size with extension "java"

提问人:Rostnik5522 提问时间:11/17/2023 最后编辑:Rostnik5522 更新时间:11/18/2023 访问量:87

问:

我用来列出目录中的所有文件,包括所有级别的子目录,并带有以“java”结尾的文件过滤器。Files.walk

public static void main(String[] args) throws IOException {
    List<String> files = findFiles(Paths.get("C:\\project"),"java");
    files.forEach(System.out::println);

public static List<String> findFiles(Path path, String extension) throws IOException {
    List<String> result;
    try (Stream<Path> walk = Files.walk(path)) {
        result = walk.filter(p -> !Files.isDirectory(p))
                     .map(p -> p.toString().toLowerCase())
                     .filter(f -> f.endsWith(extension))
                     .collect(Collectors.toList());
    }
    return result;
}

现在,我希望将文件的字符串列表转换为另一种方法,以查找具有最大大小的文件名。

我不知道该怎么做,也许把它放在字符串列表中是个坏主意。 所以我正在寻求帮助,或者可能以不同的方式解决这个问题。

Java 文件

评论

0赞 Abra 11/17/2023
Java 源代码文件,即具有扩展名的文件通常与其定义的类同名。那么你在寻找最长的类名吗?例如,如果一个文件是,而另一个文件是,那么你需要 .这是对的吗?.javaA.javaXyz.javaXyz
0赞 Rostnik5522 11/17/2023
不,对不起,我没有给我一个标题。我想要最大的文件大小。比如:最大的文件:.java 1.23 mb。

答:

1赞 tquadrat 11/17/2023 #1

试试这个:

public static void main( final String... args ) throws IOException 
{
  final var file = findLargestFile( Paths.get( "C:\\project" ),"java" );
  System.out.println( file.getAbsolutePath() );
}

public static final File findLargestFile( final Path path, final String extension ) throws IOException 
{
  try( final var walk = Files.walk( path ) ) 
  {
    return walk.filter( p -> !Files.isDirectory( p ) )
      .map( Path::toFile ) 
      .filter( f -> f.getName().toLowerCase( ROOT ).endsWith( extension ) )
      .max( comparingLong( File::length ) )
      .orElse( null );
  }
}

findLargestFile()消除没有正确扩展名的文件,然后获取剩余文件中最大的文件并返回该文件,或者如果源文件夹为空。null

如果要取回 的实例,它可能如下所示:Path

public static final Path findLargestPath( final Path path, final String extension ) throws IOException 
{
  final ToLongFunction<Path> size = p ->
  {
     var result = 0L;
     try
     {
       result = Files.size( p );
     }
     catch( final IOException ignored ) {}
     return result;
  }; 

  final Predicate<Path> validExtension = p -> p.getName( p.getNameCount() - 1 )
    .toString()
    .toLowerCase( ROOT )
    .endsWith( extension );

  try( final var walk = Files.walk( path ) ) 
  {
    return walk.filter( p -> !Files.isDirectory( p ) )
      .filter( validExtension )
      .max( comparingLong( size ) )
      .orElse( null );
  }
}

与其吞下 ,不如把它包成一个 然后扔掉。IOExceptionUncheckedIOException

评论

0赞 Rostnik5522 11/17/2023
但是当我使用它时,需要一个参数,我应该在调用时始终指定语言环境,还是只能指定语言环境?.filter( p -> p.getName().toLowerCase( ROOT ).toLowerCase()
0赞 tquadrat 11/18/2023
@Rostnik5522 – 不带参数,是的,为了确保 / 的行为不依赖于使用操作系统配置的区域设置,您应该始终指定您期望的区域设置。但是返回一个 not,我纠正了这一点。File::getNameString::toLowerCaseString::toUpperCaseFiles::walkStream<Path>Stream<File>
0赞 Abra 11/17/2023 #2

在下面的代码中,方法遍历目录树,从 dir 开始,并过滤文件扩展名为findFiles.java

然后,它按文件的大小从大到小对文件进行排序。

然后,它将文件收集到 其中 [map] 键是文件的路径,[map] 值是文件的大小。 维护向其添加条目的顺序。由于在将条目添加到 之前先对条目进行排序,因此第一个条目是具有最大大小的文件。LinkedHashMapLinkedHashMapLinkedHashMap

请注意,实现了 [interface] – 它是在 Java 21 中添加的。 声明返回第一个条目的方法,该条目是具有最大大小的文件。LinkedHashMapSequencedMapSequencedMapfirstEntry()

最后,该方法打印出最大文件的名称和大小。

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.SequencedMap;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Greatest {

    private static void findFiles(Path dir, String ext) throws IOException {

        // Map key is path to the file.
        Function<Path, Path> keyMapper = path -> path;

        // Map value is file size.
        Function<Path, Long> valueMapper = path -> {
            try {
                return Files.size(path);
            }
            catch (IOException xIo) {
                throw new UncheckedIOException(xIo);
            }
        };

        // If two files have the same path (shouldn't occur), return the size
        // of the first file.
        BinaryOperator<Long> mergeFunction = (s1, s2) -> s1;

        // Collect the stream elements into a 'LinkedHashMap'
        Supplier<Map<Path, Long>> mapFactory = () -> new LinkedHashMap<Path, Long>();

        try (Stream<Path> files = Files.walk(dir)) {
            System.out.println(((SequencedMap<Path, Long>) files.filter(p -> Files.isRegularFile(p)  &&
                                                                        p.getFileName().toString().endsWith(ext))
                 .sorted(Comparator.comparing((Path p) -> {
                     try {
                        return Files.size(p);
                    }
                    catch (IOException x) {
                        throw new UncheckedIOException(x);
                    }
                 }).reversed())
                 .collect(Collectors.toMap(keyMapper,
                                           valueMapper,
                                           mergeFunction,
                                           mapFactory))).firstEntry());
        };
    }

    public static void main(String[] args) {
        Path dir;
        if (args.length > 0) {
            dir = Paths.get(args[0]);
        }
        else {
            dir = Paths.get(System.getProperty("user.dir"));
        }
        String ext;
        if (args.length > 1) {
            ext = args[1];
        }
        else {
            ext = ".java";
        }
        try {
            findFiles(dir, ext);
        }
        catch (IOException xIo) {
            xIo.printStackTrace();
        }
    }
}
0赞 Reilas 11/18/2023 #3

"...我希望将文件的字符串列表转换为另一种方法,以查找具有最大大小的文件名。..."

多个文件的大小可能相同。

利用带有 TreeMapCollectors#groupingBy 方法仅返回最大值。

List<String> findFiles(Path path, String extension) throws IOException {
    List<String> result;
    try (Stream<Path> walk = Files.walk(path)) {
        result
            = walk.filter(p -> !Files.isDirectory(p) && p.toString().endsWith(extension))
                  .collect(
                      Collectors.groupingBy(
                          x -> x.toFile().length(),
                          TreeMap::new,
                          Collectors.mapping(Path::toString, Collectors.toList())
                      ))
                  .lastEntry()
                  .getValue();
    }
    return result;
}

例如,我有一个包含三个文件的目录,“a.txt”、“ab.txt”“abc.txt”。
大小分别为 2、3 和 4 字节。
还有一个子目录,其中包含两个文件,“b.txt”“bc.txt”,大小分别为 3 和 4 字节。

输出

files/abc.txt
files/more/bc.txt

评论

0赞 Abra 11/18/2023
你误解了这个问题 - 在评论中得到了澄清:我想要最大的文件大小
0赞 Reilas 11/18/2023
@Abra,“......我希望将文件的字符串列表转换为另一种方法来查找最大的文件名。...".从那时起,他们就编辑了这个问题。我会修复它,谢谢。