Java에서 파일을 수정일별로 정렬하는 가장 좋은 방법은 무엇입니까?
디렉토리의 파일 목록을 가져오고 싶은데 가장 오래된 파일이 먼저 오도록 정렬하고 싶습니다.해결방법은 File.listFiles를 호출하여 File.lastModified를 기반으로 목록을 다시 작성하는 것이었는데, 더 나은 방법이 없을까 생각했습니다.
편집: 현재 제안하신 바와 같이 익명의 Comparator를 사용하는 방법이 있습니다.
File[] files = directory.listFiles();
Arrays.sort(files, new Comparator<File>(){
public int compare(File f1, File f2)
{
return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());
} });
저는 당신의 해결책만이 합리적인 방법이라고 생각합니다.파일 목록을 가져오는 유일한 방법은 File.listFiles()를 사용하는 것입니다.이 문서에서는 반환되는 파일의 순서를 보증하지 않습니다.따라서 File.lastModified()를 사용하는 Comparator를 작성하여 파일 배열과 함께 Arrays.sort()에 전달해야 합니다.
Java 8 이후 우아한 솔루션:
File[] files = directory.listFiles();
Arrays.sort(files, Comparator.comparingLong(File::lastModified));
또는 내림차순으로 하려면 다음 순서로 되돌리십시오.
File[] files = directory.listFiles();
Arrays.sort(files, Comparator.comparingLong(File::lastModified).reversed());
파일이 많으면 이 작업이 더 빠를 수 있습니다.이것은 decorate-sort-undecorate 패턴을 사용하기 때문에 정렬 알고리즘이2개의 파일을 비교할 때마다가 아니라 각 파일의 마지막 수정일을 1회만 가져옵니다.이것에 의해, O(n log n)로부터 O(n)에의 I/O 콜수가 삭감될 가능성이 있습니다.
다만, 이것은 더 많은 코드이기 때문에, 주로 속도에 관심이 있고 실제로 측정이 더 빠른 경우에만 사용해야 합니다(체크하지 않았습니다).
class Pair implements Comparable {
public long t;
public File f;
public Pair(File file) {
f = file;
t = file.lastModified();
}
public int compareTo(Object o) {
long u = ((Pair) o).t;
return t < u ? -1 : t == u ? 0 : 1;
}
};
// Obtain the array of (file, timestamp) pairs.
File[] files = directory.listFiles();
Pair[] pairs = new Pair[files.length];
for (int i = 0; i < files.length; i++)
pairs[i] = new Pair(files[i]);
// Sort them by timestamp.
Arrays.sort(pairs);
// Take the sorted pairs and extract only the file part, discarding the timestamp.
for (int i = 0; i < files.length; i++)
files[i] = pairs[i].f;
Long 객체에 대한 복싱이 없는 유사한 접근 방식은 무엇입니까?
File[] files = directory.listFiles();
Arrays.sort(files, new Comparator<File>() {
public int compare(File f1, File f2) {
return Long.compare(f1.lastModified(), f2.lastModified());
}
});
또한 Apache Commons IO에는 마지막으로 수정된 비교기 및 파일 작업을 위한 기타 많은 유용한 유틸리티가 내장되어 있습니다.
Java 8의 경우:
Arrays.sort(files, (a, b) -> Long.compare(a.lastModified(), b.lastModified()));
정렬 중인 파일을 정렬하는 동시에 수정하거나 업데이트할 수 있는 경우:
자바 8 이상
private static List<Path> listFilesOldestFirst(final String directoryPath) throws IOException {
try (final Stream<Path> fileStream = Files.list(Paths.get(directoryPath))) {
return fileStream
.map(Path::toFile)
.collect(Collectors.toMap(Function.identity(), File::lastModified))
.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
// .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) // replace the previous line with this line if you would prefer files listed newest first
.map(Map.Entry::getKey)
.map(File::toPath) // remove this line if you would rather work with a List<File> instead of List<Path>
.collect(Collectors.toList());
}
}
자바 7
private static List<File> listFilesOldestFirst(final String directoryPath) throws IOException {
final List<File> files = Arrays.asList(new File(directoryPath).listFiles());
final Map<File, Long> constantLastModifiedTimes = new HashMap<File,Long>();
for (final File f : files) {
constantLastModifiedTimes.put(f, f.lastModified());
}
Collections.sort(files, new Comparator<File>() {
@Override
public int compare(final File f1, final File f2) {
return constantLastModifiedTimes.get(f1).compareTo(constantLastModifiedTimes.get(f2));
}
});
return files;
}
두 솔루션 모두 디렉토리 내의 각 파일에 대해 일정하게 마지막으로 수정한 시간을 절약하기 위해 임시 지도 데이터 구조를 만듭니다.이 작업을 수행해야 하는 이유는 정렬 실행 중에 파일이 업데이트 또는 변경되면 비교기 인터페이스의 일반 계약 이행성 요건을 위반하게 되기 때문입니다.이는 비교 중에 마지막으로 변경된 시간이 변경될 수 있기 때문입니다.
한편, 정렬 중에 파일이 업데이트 또는 수정되지 않는 것을 알고 있다면, 이 질문에 대한 다른 답변은 대부분 생략할 수 있습니다.이 질문에 대한 답변은 다음과 같습니다.
Java 8+(정렬 중 동시 수정 없음)
private static List<Path> listFilesOldestFirst(final String directoryPath) throws IOException {
try (final Stream<Path> fileStream = Files.list(Paths.get(directoryPath))) {
return fileStream
.map(Path::toFile)
.sorted(Comparator.comparing(File::lastModified))
.map(File::toPath) // remove this line if you would rather work with a List<File> instead of List<Path>
.collect(Collectors.toList());
}
}
주의: 위의 예에서는 파일::getLastModified를 사용하면 파일 객체와 파일 객체의 변환을 피할 수 있습니다.정렬된 스트림 조작의 time api. 단, lamda 내에서 체크된 IO 예외에 대처해야 합니다.이것은 항상 귀찮은 일입니다.성능이 매우 중요하여 번역이 허용되지 않을 경우 람다에서 체크된 IOException을 Uncladed로 전파하여 처리할 수 있습니다.IOException 또는 Files api를 모두 포기하고 File 객체만 취급합니다.
final List<File> sorted = Arrays.asList(new File(directoryPathString).listFiles());
sorted.sort(Comparator.comparing(File::lastModified));
Imports:
org.apache.commons.io.comparator.LastModifiedFileComparator
코드:
public static void main(String[] args) throws IOException {
File directory = new File(".");
// get just files, not directories
File[] files = directory.listFiles((FileFilter) FileFileFilter.FILE);
System.out.println("Default order");
displayFiles(files);
Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
System.out.println("\nLast Modified Ascending Order (LASTMODIFIED_COMPARATOR)");
displayFiles(files);
Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
System.out.println("\nLast Modified Descending Order (LASTMODIFIED_REVERSE)");
displayFiles(files);
}
public String[] getDirectoryList(String path) {
String[] dirListing = null;
File dir = new File(path);
dirListing = dir.list();
Arrays.sort(dirListing, 0, dirListing.length);
return dirListing;
}
찾고 있는 사람이 있다면 Kotlin의 방법은 다음과 같습니다.
val filesList = directory.listFiles()
filesList?.let{ list ->
Arrays.sort(list) {
f1, f2 -> f2.lastModified().compareTo(f1.lastModified())
}
}
Collections.sort(listFiles, new Comparator<File>() {
public int compare(File f1, File f2) {
return Long.compare(f1.lastModified(), f2.lastModified());
}
});
서 ''는listFiles
List에 있는 모든 입니다.
let array name -> 파일.
Ascending -> Arrays.sort(files, (o1, o2) -> Long.compare(o1.lastModified(), o2.lastModified()));
Descending -> Arrays.sort(files, (o1, o2) -> Long.compare(o2.lastModified(), o1.lastModified()));
guava 오더:
Function<File, Long> getLastModified = new Function<File, Long>() {
public Long apply(File file) {
return file.lastModified();
}
};
List<File> orderedFiles = Ordering.natural().onResultOf(getLastModified).
sortedCopy(files);
Apache LastModifiedFileComparator 라이브러리를 사용할 수 있습니다.
import org.apache.commons.io.comparator.LastModifiedFileComparator;
File[] files = directory.listFiles();
Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);
for (File file : files) {
Date lastMod = new Date(file.lastModified());
System.out.println("File: " + file.getName() + ", Date: " + lastMod + "");
}
private static List<File> sortByLastModified(String dirPath) {
List<File> files = listFilesRec(dirPath);
Collections.sort(files, new Comparator<File>() {
public int compare(File o1, File o2) {
return Long.compare(o1.lastModified(), o2.lastModified());
}
});
return files;
}
때 이 만, 같은 문제를 찾고 있을 때,android
마지막으로 수정한 날짜까지 정렬된 파일을 가져오는 가장 좋은 방법은 아니지만, 지금까지 찾은 방법 중 가장 쉽습니다.
아래 코드는 누군가에게 도움이 될 수 있습니다.
File downloadDir = new File("mypath");
File[] list = downloadDir.listFiles();
for (int i = list.length-1; i >=0 ; i--) {
//use list.getName to get the name of the file
}
감사해요.
별도의 비교기 없이 문제를 쉽게 처리할 수 있는 방법이 있습니다.변경된 날짜를 파일 이름으로 문자열에 코드화하고 정렬한 후 나중에 다시 제거합니다.
고정 길이 20의 문자열을 사용하고 수정된 날짜(길이)를 입력한 후 선행 0으로 채웁니다.그런 다음 이 문자열에 파일 이름을 추가합니다.
String modified_20_digits = ("00000000000000000000".concat(Long.toString(temp.lastModified()))).substring(Long.toString(temp.lastModified()).length());
result_filenames.add(modified_20_digits+temp.getAbsoluteFile().toString());
다음과 같은 상황이 발생합니다.
파일 이름 1:C:\data\file1.html 최종 갱신일:1532914451455 최종 갱신일:00000001532914451455
파일 이름 1:C:\data\file2.html 최종 갱신일:1532918086822 최종 갱신일:00000001532918086822
는 파일명을 다음과 같이 변환합니다.
파일명 1: 00000001532914451455C:\data\file1.html
파일명 2: 00000001532918086822C:\data\file2.html
그런 다음 이 목록을 정렬할 수 있습니다.
나중에 다시 20자를 삭제하기만 하면 됩니다(Java 8에서는 .replaceAll 함수를 사용하여 어레이 전체를 한 줄만으로 삭제할 수 있습니다).
@jason-orendorf의 답변을 조금 더 현대화한 버전입니다.
주의: 이 구현에서는 원래 어레이를 변경하지 않고 새 어레이를 반환합니다.이것은 바람직할 수도 있고 바람직하지 않을 수도 있습니다.
files = Arrays.stream(files)
.map(FileWithLastModified::ofFile)
.sorted(comparingLong(FileWithLastModified::lastModified))
.map(FileWithLastModified::file)
.toArray(File[]::new);
private static class FileWithLastModified {
private final File file;
private final long lastModified;
private FileWithLastModified(File file, long lastModified) {
this.file = file;
this.lastModified = lastModified;
}
public static FileWithLastModified ofFile(File file) {
return new FileWithLastModified(file, file.lastModified());
}
public File file() {
return file;
}
public long lastModified() {
return lastModified;
}
}
하지만 다시 한 번 @jason-Orendorf의 아이디어에 대한 모든 공로를 인정합니다!
Java 6에서는 다음 방법이 가장 좋습니다.
File[] listaArchivos = folder.listFiles();
Arrays.sort(listaArchivos, new Comparator<File>() {
@Override
public int compare(File f1, File f2) {
return (f1.lastModified() < f2.lastModified()) ? -1 : ((f1.lastModified() == f2.lastModified()) ? 0 : 1);
}
});
다른 방법도 있습니다.다수는 취급하지 않기 때문에, 한층 더 쉬워질지도 모릅니다.
모든 파일 이름과 last Modified 날짜를 가져온 후 배열 전체를 정렬하는 대신 목록의 올바른 위치에 가져온 직후에 모든 파일 이름을 삽입할 수 있습니다.
다음과 같이 할 수 있습니다.
list.add(1, object1)
list.add(2, object3)
list.add(2, object2)
object2를 위치2에 추가하면 object3가 위치3으로 이동합니다.
언급URL : https://stackoverflow.com/questions/203030/best-way-to-list-files-in-java-sorted-by-date-modified
'source' 카테고리의 다른 글
PHP로 작성된 괜찮은 PHP 파서는 없습니까? (0) | 2022.11.18 |
---|---|
사전을 값별로 정렬하려면 어떻게 해야 합니까? (0) | 2022.11.18 |
최대 식별자 이름 길이를 늘리는 방법 (0) | 2022.11.18 |
HTML php 스크립트를 통해 mysql 데이터베이스에 연결할 수 없습니다. (0) | 2022.11.18 |
Uncourched ReferenceError: $가 정의되지 않았습니까? (0) | 2022.11.18 |