问题
I have to retrieve a set of JPG files from the folder so that I can create a movie with it. The problem is that the files are listed in a haphazard manner and hence are processed in a haphazard manner. Here is a screenshot:
I need them in a sequential manner as img0,img1.....imgn
How do I do that?
**I deveopled a custom sorting scheme but I get an exception. The coding is given here: "
try{
int totalImages = 0;
int requiredImage = 0;
jpegFiles = Files.newDirectoryStream(Paths.get(pathToPass).getParent(), "*.JPG");
Iterator it = jpegFiles.iterator();
Iterator it2 = jpegFiles.iterator();
Iterator it3 = jpegFiles.iterator();
while(it.hasNext()){
it.next();
totalImages++;
}
System.out.println(totalImages);
sortedJpegFiles = new String[totalImages];
while(it2.hasNext()){
Path jpegFile = (Path)it2.next();
String name = jpegFile.getFileName().toString();
int index = name.indexOf(Integer.toString(requiredImage));
if(index!=-1){
sortedJpegFiles[requiredImage] = jpegFile.toString();
}
requiredImage++;
}
for(String print : sortedJpegFiles){
System.out.println(print);
}
}catch(IOException e){
e.printStackTrace();
}
Exception:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Iterator already obtained
at sun.nio.fs.WindowsDirectoryStream.iterator(Unknown Source)
at ScreenshotDemo.SCapGUI$VideoCreator.run(SCapGUI.java:186)
at ScreenshotDemo.SCapGUI$1.windowClosing(SCapGUI.java:30)
at java.awt.Window.processWindowEvent(Unknown Source)
at javax.swing.JFrame.processWindowEvent(Unknown Source)
at java.awt.Window.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
回答1:
Custom Comparator
You'll have to extract the number part, possibly using some regular expression, and then use that to sort. A custom Comparator might encapsulate the custom numerical comparison for you.
import java.util.*;
import java.util.regex.*;
// Sort strings by last integer number contained in string.
class CompareByLastNumber implements Comparator<String> {
private static Pattern re = Pattern.compile("[0-9]+");
public boolean equals(Object obj) {
return obj != null && obj.getClass().equals(getClass());
}
private int num(String s) {
int res = -1;
Matcher m = re.matcher(s);
while (m.find())
res = Integer.parseInt(m.group());
return res;
}
public int compare(String a, String b) {
return num(a) - num(b);
}
public static void main(String[] args) {
Arrays.sort(args, new CompareByLastNumber());
for (String s: args)
System.out.println(s);
}
}
Avoiding the IllegalStateException
Referring to your updated question: the exception you encounter is because you attempt to iterate over the DirectoryStream multiple times. Quoting from its reference:
While
DirectoryStreamextendsIterable, it is not a general-purposeIterableas it supports only a singleIterator; invoking the iterator method to obtain a second or subsequent iterator throwsIllegalStateException.
So the behaviour you see is to be expected. You should collect all your files to a single list. Something along these lines:
List<Path> jpegFilesList = new ArrayList<>();
while (Path p: jpegFiles)
jpegFilesList.add(p);
sortedJpegFiles = new String[jpegFilesList.size()];
for(Path jpegFile: jpegFilesList) {
…
}
Note that this issue about the IllegalStateException is rather distinct from the original question you asked. So it would be better off in a separate question. Remember that SO is not a forum. So please stick to one issue per question.
回答2:
The files are ordered lexicographically, which may seem unnatural to a human, but is perfectly logical for a computer.
There are several algorithms to sort according to "human logic" if you don't want to do it yourself, one example is The Alphanum Algorithm.
来源:https://stackoverflow.com/questions/12412938/directorystreampath-lists-files-in-a-haphazard-manner