फ़ाइलसिस्टम निर्देशिकाओं की लिंक की गई कार्यान्वयन
मैं जावा में रैपर कक्षाएं लिख रहा हूं जो एक किनारे के मामले को संभालने के लिए मौजूदा कार्यान्वयन के तरीकों को ओवरराइड करता है। पूर्ण कार्यान्वयन यहां पोस्ट किए जाने की तुलना में थोड़ा अधिक जटिल है, इसलिए मैंने एक सरलीकृत वर्ग लिखा है जिसमें केवल उन हिस्सों को शामिल किया गया है जिन पर मैं सहायता का अनुरोध कर रहा हूं।
समस्या का सारांश
मैं दो वर्गों का विस्तार कर रहा हूं:
एक वर्ग "एन्यूमरेशन" वर्ग के रूप में डिज़ाइन किया गया है, जो एक फाइल सिस्टम पर एक निर्देशिका को अमूर्त करता है जिसमें अन्य निर्देशिकाओं के प्रतीकात्मक लिंक होते हैं। (वास्तविक दुनिया: "/ sys / ब्लॉक")। इसकी दो विधियाँ हैं, scan()
(लिंक्ड) उपनिर्देशिकाओं की सूची बनाने के लिए एक विधि और सूची के getFirst()
पहले तत्व को वापस करने के लिए।
दूसरी कक्षा एक "प्रवेश" वर्ग है, जो प्रथम श्रेणी द्वारा इंगित की गई निर्देशिका को सार करती है। इसकी दो विधियां हैं, एक getName()
स्ट्रिंग के रूप में निर्देशिका के पथ को वापस करने की एक getNext()
विधि , और अगले तत्व को पुनरावृति करने की एक विधि।
अड़चन होती है
- जेडीके 8 या उससे पहले की संगतता
- एकल-थ्रेडेड उपयोग माना जा सकता है
- आवश्यकता के अनुसार कंस्ट्रक्टर्स को बदला जा सकता है।
- दो निर्दिष्ट वर्गों और प्रत्येक पर दो विधियों को (कम से कम) लागू करना चाहिए।
समीक्षा का फोकस
scan()
विधि मेरे संघर्ष यहाँ है। मुझे लगता है कि मैंने समाधान को दो तरीकों से पूरा किया हो सकता है:
- विधि
try ... catch
में नेस्टेड ब्लॉकscan()
असामान्य लगते हैं। क्या मुझे इसे संभालने का एक सरल तरीका याद आ रहा है? - (अद्यतन: नीचे इस दूसरे प्रश्न का स्व-उत्तर दिया गया है।) कार्यान्वित किया गया पैटर्न स्पष्ट रूप से एक एकल लिंक की गई सूची है जिसे मैं एक
ArrayList
कार्यान्वयन के आसपास से गुजर कर काम कर रहा हूं । मैं उसDirEntry
वर्ग की कल्पना कर सकता हूं जिसमें केवल उसकीPath
और एकDirEntry next
वस्तु है, लेकिन इस तरह की सूची उत्पन्न करने का प्रयास उस पर किए गए वर्कअराउंड से भी अधिक जटिल या कम प्रदर्शनकारी लगता है।
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DeviceList {
/**
* Class representing a parent directory which contains symbolic links to other
* directories
*/
static class DirEnumerator {
private Path dirPath;
private List<DirEntry> entryList = Collections.emptyList();
public DirEnumerator(String path) {
dirPath = FileSystems.getDefault().getPath(path);
}
/**
* Scans the directory for entries
*
* @return The number of entries found
*/
public int scan() {
try (Stream<Path> paths = Files.walk(dirPath)) {
List<Path> linkedDirs = paths.filter(Files::isSymbolicLink).map(p -> {
try {
return Files.readSymbolicLink(p);
} catch (IOException e) {
return p;
}
}).collect(Collectors.toList());
this.entryList = new ArrayList<>();
for (int i = 0; i < linkedDirs.size(); i++) {
this.entryList.add(new DirEntry(entryList, linkedDirs.get(i), i));
}
return this.entryList.size();
} catch (IOException e) {
this.entryList = Collections.emptyList();
return 0;
}
}
/**
* Gets the first entry in the scanned list
*
* @return The first entry if it exists; null otherwise
*/
public DirEntry getFirst() {
return entryList.isEmpty() ? null : entryList.get(0);
}
}
/**
* Class representing a directory
*/
static class DirEntry {
private List<DirEntry> entryList;
private Path path;
private int index;
public DirEntry(List<DirEntry> entryList, Path path, int i) {
this.entryList = entryList;
this.path = path;
this.index = i;
}
/**
* Gets the path name of the directory entry
*
* @return a string representing the path
*/
public String getName() {
return this.path.toString();
}
/**
* Gets the next entry in the list
*
* @return the next entry if it exists; null otherwise
*/
public DirEntry getNext() {
int nextIndex = index + 1;
return nextIndex < entryList.size() ? entryList.get(nextIndex) : null;
}
}
public static void main(String[] args) {
// Test on any directory containing symbolic links to other directories
DirEnumerator de = new DirEnumerator("/sys/block");
int n = de.scan();
System.out.println("Found " + n + " directories.");
DirEntry e = de.getFirst();
while (e != null) {
System.out.println("Directory: " + e.getName());
e = e.getNext();
}
}
}
```
जवाब
मैंने दूसरे प्रश्न को करने के लिए एक सरल तरीका खोजा है, लिंक की गई सूची को निर्मित रास्तों से पीछे की ओर जोड़कर बनाया है।
static class DirEnumerator {
private Path dirPath;
private DirEntry first = null;
// ...
public int scan() {
try (Stream<Path> paths = Files.walk(dirPath)) {
List<Path> linkedDirs = paths.filter(Files::isSymbolicLink).map(p -> {
try {
return Files.readSymbolicLink(p);
} catch (IOException e) {
return p;
}
}).collect(Collectors.toList());
this.first = null;
int i = linkedDirs.size();
while (i-- > 0) {
this.first = new DirEntry(linkedDirs.get(i), first);
}
return linkedDirs.size();
} catch (IOException e) {
this.first = null;
return 0;
}
}
// ...
}
static class DirEntry {
private Path path;
private DirEntry next;
public DirEntry(Path path, DirEntry next) {
this.path = path;
this.next = next;
}
// ...
}
```