আমি কীভাবে জাভাতে একটি ডিরেক্টরিতে সমস্ত ফাইলকে পুনরাবৃত্তভাবে তালিকাবদ্ধ করব? ফ্রেমওয়ার্কটি কোনও উপযোগিতা সরবরাহ করে?
আমি হ্যাকি বাস্তবায়ন অনেক দেখেছি। তবে ফ্রেমওয়ার্ক বা নিও থেকে কোনওটিই নয়
আমি কীভাবে জাভাতে একটি ডিরেক্টরিতে সমস্ত ফাইলকে পুনরাবৃত্তভাবে তালিকাবদ্ধ করব? ফ্রেমওয়ার্কটি কোনও উপযোগিতা সরবরাহ করে?
আমি হ্যাকি বাস্তবায়ন অনেক দেখেছি। তবে ফ্রেমওয়ার্ক বা নিও থেকে কোনওটিই নয়
উত্তর:
জাভা 8 একটি গাছের সমস্ত ফাইল প্রক্রিয়া করার জন্য একটি দুর্দান্ত স্ট্রিম সরবরাহ করে।
Files.walk(Paths.get(path))
.filter(Files::isRegularFile)
.forEach(System.out::println);
এটি ফাইলগুলিকে ট্র্যাভার করার প্রাকৃতিক উপায় সরবরাহ করে। যেহেতু এটি একটি স্ট্রিম হিসাবে আপনি ফলাফলের সমস্ত স্রোত অপারেশন যেমন সীমাবদ্ধতা, গোষ্ঠীকরণ, ম্যাপিং, প্রারম্ভিক প্রস্থান ইত্যাদি করতে পারেন can
আপডেট : আমি এখানে ফাইলসফাইন্ডটি উল্লেখ করতে পারি যা একটি বাইপ্রেডিকেট নেয় যা আপনাকে ফাইলের বৈশিষ্ট্যগুলি পরীক্ষা করার প্রয়োজন হলে আরও কার্যকর হতে পারে।
Files.find(Paths.get(path),
Integer.MAX_VALUE,
(filePath, fileAttr) -> fileAttr.isRegularFile())
.forEach(System.out::println);
নোট করুন যে জাভাডোকটি ছাড়িয়েছে যে এই পদ্ধতিটি ফাইলসওয়াকের চেয়ে আরও কার্যকর হতে পারে এটি কার্যকরভাবে অভিন্ন, আপনি যদি আপনার ফিল্টারের মধ্যেও ফাইল বৈশিষ্ট্য পুনরুদ্ধার করে থাকেন তবে পারফরম্যান্সের পার্থক্য লক্ষ্য করা যায়। শেষ পর্যন্ত, যদি আপনার ফাইলগুলি ফাইলফাইন্ড ব্যবহার করে বৈশিষ্ট্যগুলিতে ফিল্টার করা দরকার হয় , অন্যথায় ফাইলসওয়াক ব্যবহার করুন , বেশিরভাগ কারণেই ওভারলোড রয়েছে এবং এটি আরও সুবিধাজনক।
পরীক্ষা : অনুরোধ হিসাবে আমি উত্তরের অনেকের সাথে একটি পারফরম্যান্স তুলনা সরবরাহ করেছি। পরীক্ষা করে দেখুন গিটহাব প্রকল্পে ফলাফল এবং একটি পরীক্ষা ক্ষেত্রে রয়েছে ।
Files.walk
সমান্তরাল স্ট্রিমের সাহায্যে ব্যবহার করা সবচেয়ে ভাল, নিকটে অনুসরণ করা হয় Files.walkFileTree
যার দ্বারা কেবল সামান্য ধীর হয়। কমন্স-আইও ব্যবহার করে গৃহীত উত্তরটি আমার পরীক্ষাগুলির দ্বারা 4 গুণ ধীর হতে এখন পর্যন্ত সবচেয়ে ধীর।
Exception in thread "main" java.io.UncheckedIOException: java.nio.file.AccessDeniedException
। আমি কীভাবে এটি সংশোধন করতে পারি
FileUtils আছে iterateFiles
এবং listFiles
পদ্ধতি। তাদের চেষ্টা করুন। ( কমন্স-আইও থেকে )
সম্পাদনা করুন: আপনি বিভিন্ন পদ্ধতির একটি মানদণ্ডের জন্য এখানে পরীক্ষা করতে পারেন । দেখে মনে হচ্ছে কমন্স-আইও পদ্ধতির ধীর গতি রয়েছে, সুতরাং এখান থেকে দ্রুততম কয়েকটি বেছে নিন (যদি এটি বিবেচনা করে)
FileUtils.listFiles(dir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE)
, যেখানে dir
কোনও ফাইল অবজেক্ট যা বেস ডিরেক্টরিকে নির্দেশ করে।
listFilesAndDirs()
, যেমন listFiles()
খালি ফোল্ডার ফেরত দেয় না।
FileUtils.listFiles(dir, true, true)
। ব্যবহার করে FileUtils.listFiles(dir, null, true)
একটি ব্যতিক্রম ছুঁড়ে ফেলা হবে, FileUtils.listFiles(dir, true, null)
এবং সাব-ডিরেক্টরি ডিরেক্টরি না দেখে সমস্ত ফাইল তালিকাভুক্ত করবে।
// চালানোর জন্য প্রস্তুত
import java.io.File;
public class Filewalker {
public void walk( String path ) {
File root = new File( path );
File[] list = root.listFiles();
if (list == null) return;
for ( File f : list ) {
if ( f.isDirectory() ) {
walk( f.getAbsolutePath() );
System.out.println( "Dir:" + f.getAbsoluteFile() );
}
else {
System.out.println( "File:" + f.getAbsoluteFile() );
}
}
}
public static void main(String[] args) {
Filewalker fw = new Filewalker();
fw.walk("c:\\" );
}
}
-> .
।
"/"
, "./"
বা "../"
রুট ডিরেক্টরি, সাম্প্রতিক কাজ করা, এবং পেরেন্ট ডাইরেক্টরি যথাক্রমে জন্য
জাভা 7 থাকবে রয়েছে Files.walkFileTree :
আপনি যদি একটি শুরুর পয়েন্ট এবং কোনও ফাইল দর্শনার্থী সরবরাহ করেন তবে ফাইল ট্রিতে ফাইলের মধ্য দিয়ে হাঁটার সাথে সাথে এটি ফাইল দর্শকের বিভিন্ন পদ্ধতি গ্রহণ করবে। আমরা প্রত্যাশা করি যে লোকেরা এটি ব্যবহার করবে যদি তারা পুনরাবৃত্তির অনুলিপি, পুনরাবৃত্তি পদক্ষেপ, একটি পুনরাবৃত্ত মোছা, বা একটি পুনরাবৃত্ত অপারেশন যা অনুমতি নির্ধারণ করে বা ফাইলগুলির প্রতিটিতে অন্য ক্রিয়াকলাপ সম্পাদন করে।
এই প্রশ্নের এখন একটি সম্পূর্ণ ওরাকল টিউটোরিয়াল আছে ।
কোন বাহ্যিক গ্রন্থাগার প্রয়োজন।
একটি সংগ্রহ ফেরত দেয় যাতে আপনি কল করার পরে এটি দিয়ে যা খুশি করতে পারেন।
public static Collection<File> listFileTree(File dir) {
Set<File> fileTree = new HashSet<File>();
if(dir==null||dir.listFiles()==null){
return fileTree;
}
for (File entry : dir.listFiles()) {
if (entry.isFile()) fileTree.add(entry);
else fileTree.addAll(listFileTree(entry));
}
return fileTree;
}
আমি এরকম কিছু নিয়ে যাব:
public void list(File file) {
System.out.println(file.getName());
File[] children = file.listFiles();
for (File child : children) {
list(child);
}
}
সিস্টেম.আউট.প্রিন্টলন ফাইলের সাথে কিছু করার ইঙ্গিত দেওয়ার জন্য কেবল সেখানে রয়েছে। ফাইল এবং ডিরেক্টরিগুলির মধ্যে পার্থক্য করার দরকার নেই, যেহেতু একটি সাধারণ ফাইলে কেবল শূন্য শিশু থাকে।
listFiles()
: "যদি এই বিমূর্ত পথের নামটি কোনও ডিরেক্টরিকে বোঝায় না, তবে এই পদ্ধতিটি ফিরে আসবে null
।"
আমি এই জাতীয় সরল ট্র্যাভার্সনের জন্য পুনরাবৃত্তির উপরে একটি সারি ব্যবহার করা পছন্দ করি:
List<File> allFiles = new ArrayList<File>();
Queue<File> dirs = new LinkedList<File>();
dirs.add(new File("/start/dir/"));
while (!dirs.isEmpty()) {
for (File f : dirs.poll().listFiles()) {
if (f.isDirectory()) {
dirs.add(f);
} else if (f.isFile()) {
allFiles.add(f);
}
}
}
কেবল সাধারণ পুনরাবৃত্তি ব্যবহার করে এটি লিখুন:
public List<File> addFiles(List<File> files, File dir)
{
if (files == null)
files = new LinkedList<File>();
if (!dir.isDirectory())
{
files.add(dir);
return files;
}
for (File file : dir.listFiles())
addFiles(files, file);
return files;
}
আমি মনে করি এটি কাজ করা উচিত:
File dir = new File(dirname);
String[] files = dir.list();
এইভাবে আপনার কাছে ফাইল এবং ডায়ার রয়েছে। এখন পুনরাবৃত্তি ব্যবহার করুন এবং ডিয়ারদের জন্য একই করুন ( File
শ্রেণীর isDirectory()
পদ্ধতি রয়েছে)।
জাভা 7 এর সাহায্যে আপনি নিম্নলিখিত ক্লাসটি ব্যবহার করতে পারেন:
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
public class MyFileIterator extends SimpleFileVisitor<Path>
{
public MyFileIterator(String path) throws Exception
{
Files.walkFileTree(Paths.get(path), this);
}
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attributes) throws IOException
{
System.out.println("File: " + file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attributes) throws IOException
{
System.out.println("Dir: " + dir);
return FileVisitResult.CONTINUE;
}
}
এই কোডটি চালানোর জন্য প্রস্তুত
public static void main(String... args) {
File[] files = new File("D:/").listFiles();
if (files != null)
getFiles(files);
}
public static void getFiles(File[] files) {
for (File file : files) {
if (file.isDirectory()) {
getFiles(file.listFiles());
} else {
System.out.println("File: " + file);
}
}
}
পুনরাবৃত্তিমূলক ট্র্যাভারসাল ছাড়াও একজন দর্শনার্থী ভিত্তিক পদ্ধতি ব্যবহার করতে পারে।
নীচের কোডটি ট্র্যাভারসালের জন্য দর্শনার্থী ভিত্তিক পদ্ধতির ব্যবহার করে t এটি প্রত্যাশিত যে প্রোগ্রামটির ইনপুটটি ট্র্যাভ্রাস্টের মূল ডিরেক্টরি।
public interface Visitor {
void visit(DirElement d);
void visit(FileElement f);
}
public abstract class Element {
protected File rootPath;
abstract void accept(Visitor v);
@Override
public String toString() {
return rootPath.getAbsolutePath();
}
}
public class FileElement extends Element {
FileElement(final String path) {
rootPath = new File(path);
}
@Override
void accept(final Visitor v) {
v.visit(this);
}
}
public class DirElement extends Element implements Iterable<Element> {
private final List<Element> elemList;
DirElement(final String path) {
elemList = new ArrayList<Element>();
rootPath = new File(path);
for (File f : rootPath.listFiles()) {
if (f.isDirectory()) {
elemList.add(new DirElement(f.getAbsolutePath()));
} else if (f.isFile()) {
elemList.add(new FileElement(f.getAbsolutePath()));
}
}
}
@Override
void accept(final Visitor v) {
v.visit(this);
}
public Iterator<Element> iterator() {
return elemList.iterator();
}
}
public class ElementWalker {
private final String rootDir;
ElementWalker(final String dir) {
rootDir = dir;
}
private void traverse() {
Element d = new DirElement(rootDir);
d.accept(new Walker());
}
public static void main(final String[] args) {
ElementWalker t = new ElementWalker("C:\\temp");
t.traverse();
}
private class Walker implements Visitor {
public void visit(final DirElement d) {
System.out.println(d);
for(Element e:d) {
e.accept(this);
}
}
public void visit(final FileElement f) {
System.out.println(f);
}
}
}
পুনরাবৃত্তভাবে নির্দিষ্ট ফোল্ডার বা ডিরেক্টরিগুলির ফাইলগুলির একটি তালিকা পেতে আপনি নীচের কোডটি ব্যবহার করতে পারেন।
public static void main(String args[]) {
recusiveList("D:");
}
public static void recursiveList(String path) {
File f = new File(path);
File[] fl = f.listFiles();
for (int i = 0; i < fl.length; i++) {
if (fl[i].isDirectory() && !fl[i].isHidden()) {
System.out.println(fl[i].getAbsolutePath());
recusiveList(fl[i].getAbsolutePath());
} else {
System.out.println(fl[i].getName());
}
}
}
গৃহীত উত্তর তবে প্রায় ভেঙে পড়েছে যখন আপনি ল্যামডা ভিতরে আই কাজ করতে চান, মহান।
যদি আপনার ক্রিয়াটি আইওএক্সেপশন ঘোষণা করে তবে আপনি যা করতে পারেন তা এখানে।
আপনি ফিল্টার করা স্ট্রিমটিকে একটি হিসাবে গণ্য করতে পারেন Iterable
এবং তারপরে প্রতিটি লুপের জন্য নিয়মিত আপনার ক্রিয়াটি করতে পারেন। এইভাবে, আপনাকে ল্যাম্বডারের অভ্যন্তরে ব্যতিক্রমগুলি পরিচালনা করতে হবে না।
try (Stream<Path> pathStream = Files.walk(Paths.get(path))
.filter(Files::isRegularFile)) {
for (Path file : (Iterable<Path>) pathStream::iterator) {
// something that throws IOException
Files.copy(file, System.out);
}
}
সেই কৌশলটি এখানে পেয়েছে: https://stackoverflow.com/a/32668807/1207791
একক তালিকার সাথে অ-পুনরাবৃত্ত বিএফএস (বিশেষ উদাহরণে *। এমএল ফাইল অনুসন্ধান করা হয়):
final FileFilter filter = new FileFilter() {
@Override
public boolean accept(File file) {
return file.isDirectory() || file.getName().endsWith(".eml");
}
};
// BFS recursive search
List<File> queue = new LinkedList<File>();
queue.addAll(Arrays.asList(dir.listFiles(filter)));
for (ListIterator<File> itr = queue.listIterator(); itr.hasNext();) {
File file = itr.next();
if (file.isDirectory()) {
itr.remove();
for (File f: file.listFiles(filter)) itr.add(f);
}
}
আমার সংস্করণ (অবশ্যই আমি জাভা 8 ;-) এ বিল্ট ইন ওয়াকটি ব্যবহার করতে পারতাম):
public static List<File> findFilesIn(File rootDir, Predicate<File> predicate) {
ArrayList<File> collected = new ArrayList<>();
walk(rootDir, predicate, collected);
return collected;
}
private static void walk(File dir, Predicate<File> filterFunction, List<File> collected) {
Stream.of(listOnlyWhenDirectory(dir))
.forEach(file -> walk(file, filterFunction, addAndReturn(collected, file, filterFunction)));
}
private static File[] listOnlyWhenDirectory(File dir) {
return dir.isDirectory() ? dir.listFiles() : new File[]{};
}
private static List<File> addAndReturn(List<File> files, File toAdd, Predicate<File> filterFunction) {
if (filterFunction.test(toAdd)) {
files.add(toAdd);
}
return files;
}
এখানে একটি সাধারণ তবে পুরোপুরি কার্যকর সমাধান সমাধান recursion
:
public static List<Path> listFiles(String rootDirectory)
{
List<Path> files = new ArrayList<>();
listFiles(rootDirectory, files);
return files;
}
private static void listFiles(String path, List<Path> collectedFiles)
{
File root = new File(path);
File[] files = root.listFiles();
if (files == null)
{
return;
}
for (File file : files)
{
if (file.isDirectory())
{
listFiles(file.getAbsolutePath(), collectedFiles);
} else
{
collectedFiles.add(file.toPath());
}
}
}
private void fillFilesRecursively(File file, List<File> resultFiles) {
if (file.isFile()) {
resultFiles.add(file);
} else {
for (File child : file.listFiles()) {
fillFilesRecursively(child, resultFiles);
}
}
}
আমি সমস্ত ফাইল / ফাইলের নাম পুনরাবৃত্তভাবে মুদ্রণের জন্য এটি নিয়ে এসেছি।
private static void printAllFiles(String filePath,File folder) {
if(filePath==null) {
return;
}
File[] files = folder.listFiles();
for(File element : files) {
if(element.isDirectory()) {
printAllFiles(filePath,element);
} else {
System.out.println(" FileName "+ element.getName());
}
}
}
উদাহরণস্বরূপ java.nio থেকে ফাইল.ফাইন্ড () ব্যবহার করে ডিরেক্টরি পুনরাবৃত্তিতে অনুসন্ধানের উপ-ডিরেক্টরিগুলিতে * .csv ফাইলগুলি আউটপুট করুন:
String path = "C:/Daten/ibiss/ferret/";
logger.debug("Path:" + path);
try (Stream<Path> fileList = Files.find(Paths.get(path), Integer.MAX_VALUE,
(filePath, fileAttr) -> fileAttr.isRegularFile() && filePath.toString().endsWith("csv"))) {
List<String> someThingNew = fileList.sorted().map(String::valueOf).collect(Collectors.toList());
for (String t : someThingNew) {
t.toString();
logger.debug("Filename:" + t);
}
}
এই উদাহরণটি পোস্ট করাতে, যেমন স্ট্রিম-ফলাফলের উপর পূর্বাভাস ব্যবহার করে ব্রায়ান প্রদত্ত # 1 উদাহরণে ফাইলনাম পরামিতিটি কীভাবে পাস করতে হয় তা বুঝতে আমার সমস্যা হয়েছিল -
আশাকরি এটা সাহায্য করবে.
কোটলিন FileTreeWalk
এই উদ্দেশ্যে আছে। উদাহরণ স্বরূপ:
dataDir.walkTopDown().filter { !it.isDirectory }.joinToString("\n") {
"${it.toRelativeString(dataDir)}: ${it.length()}"
}
প্রদত্ত রুটের অধীনে সমস্ত নন-ডিরেক্টরি ফাইলের একটি পাঠ্য তালিকা তৈরি করবে, মূল এবং দৈর্ঘ্যের সাথে সম্পর্কিত পাথের সাথে প্রতি লাইনে একটি ফাইল।
স্ট্যাকার উত্তরের ভিত্তিতে। এখানে কোনও সমাধান কোনও বাহ্যিক লাইব্রেরি ছাড়াই জেএসপিতে কাজ করছে যাতে আপনি এটি আপনার সার্ভারে প্রায় যে কোনও জায়গায় রাখতে পারেন:
<!DOCTYPE html>
<%@ page session="false" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%!
public List<String> files = new ArrayList<String>();
/**
Fills files array with all sub-files.
*/
public void walk( File root ) {
File[] list = root.listFiles();
if (list == null) return;
for ( File f : list ) {
if ( f.isDirectory() ) {
walk( f );
}
else {
files.add(f.getAbsolutePath());
}
}
}
%>
<%
files.clear();
File jsp = new File(request.getRealPath(request.getServletPath()));
File dir = jsp.getParentFile();
walk(dir);
String prefixPath = dir.getAbsolutePath() + "/";
%>
তাহলে আপনি ঠিক এর মতো কিছু করুন:
<ul>
<% for (String file : files) { %>
<% if (file.matches(".+\\.(apk|ipa|mobileprovision)")) { %>
<li><%=file.replace(prefixPath, "")%></li>
<% } %>
<% } %>
</ul>