2016-10-31 1 views
0

Ich schreibe eine Anwendung in Java, die eine Liste der Dateien anzeigt, in denen das erste Wort im Dateinamen mit der benutzerdefinierten Zeichenfolge übereinstimmt und sie dann löscht oder neu anordnet, abhängig von einigen Einstellungen. Ich bin gerade dabei, einen guten Weg zu finden, meine Dateien zu finden. Mit this Java Tutorial endete ich mit so etwas wie dies oben:Java Regex und PathMatcher

Path source = Paths.get(sourceText.getText()); 
Path dest = Paths.get(destText.getText()); 

System.out.println("Source:" + source.toString()); 
System.out.println("P/N: " + partNoText.getText()); 

String matchString = "glob:**" + partNoText.getText() + "*"; 

System.out.println("Matching: " + matchString); 

fileFinder = new FileFinder(matchString); 

try { 
    Files.walkFileTree(source, fileFinder); 
} catch (IOException e1) { 
    e1.printStackTrace(); 
} 
for (Path path : fileFinder.getResult()) { 
    System.out.println("Moving: " + path.getFileName()); 
    Path target = Paths.get(dest.toString() + "\\" + path.getFileName()); 

    try { 
     Files.move(path, target, REPLACE_EXISTING); 
    } catch (IOException e1) { 
     e1.printStackTrace(); 
    } 
} 

wo Filefinder SimpleFileVisitor erstreckt und diese visitFile Methode:

public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 
    System.out.println(file.toString()); 
    System.out.println(fileMatcher.matches(file)); 
    if (fileMatcher.matches(file)) { 
     result.add(file); 
     return FileVisitResult.CONTINUE; 
    } 
    return FileVisitResult.CONTINUE; 
} 

Mein Problem dabei ist, dass die glob jede Datei abholt, wo der Dateiname enthält die Teile-Nr. in irgendeiner Weise. Wenn meine Datei also "12345 RevA Really Big Part 2: Elektrisches Bugaloo" heißt, würde die Zeichenfolge übereinstimmen, wenn der Benutzer "1" oder "123" oder "Bugaloo" eingegeben hätte. Idealerweise würde es nur passen, wenn der Benutzer "12345" eingegeben hätte.

Ich habe versucht, meine MatchString zu "regex: .*" + partNoText + "\\b", die in der Regex-Test-Kabelbaum ich geändert von this other Java Tutorial funktioniert. Was mache ich falsch? Funktioniert PathMatcher anders als ein normales Matcher?

P.S. Jede Variable, die das Wort "Text" enthält, wie sourceText und partNoText sind JTextFields. Hoffentlich ist das der einzige Teil des Codes, der größtenteils unklar ist von dem, was ich herausgeschnitten habe.

+1

Dateiname _globbing_ ist _ ** nicht ** _ ein regulärer Ausdruck; Globbing ist viel begrenzter als Regex. Auch, 'foo *' als ein Glob passt foo-with-away-after-after, das Äquivalent als Regex wäre 'foo. *' = Foo, gefolgt von jedem einzelnen Zeichen '.' null-oder-mehr-mal' * ' –

+0

_ "Im Idealfall würde es nur passen, wenn der Benutzer" 12345 "eingegeben hätte." _ Ist Teilenummer _always_ der erste Teil des Dateinamens? Sind alle Teilenummern _exactly_ 5 Ziffern? Ist die Teilenummer _always_ gefolgt von einem Leerzeichen? Eine genaue Definition kann Ihnen helfen, eine gute Regex zu finden. Ich glaube nicht, dass Globbing es in diesem Fall tun würde, obwohl Sie den Match-Space reduzieren könnten und dann das, was Globbing gefunden hat, wiederfinden. –

+0

@StephenP Für Ihren ersten Kommentar verstehe ich, dass Globbing und Regex beide unterschiedliche Möglichkeiten sind, generalisierte Strings zu erzeugen, mit denen sie übereinstimmen. Sie können aus dem unteren Teil meiner Frage sehen, dass ich aufgrund seiner Beschränkungen entschied, von Globbing zu Regex zu wechseln –

Antwort

1

"Funktioniert der PathMatcher anders als ein normaler Matcher?"
Ja. a PathMatcher arbeitet mit dem Dateinamen globbing[1], während ein Matcher mit regulären Ausdrücken funktioniert.

Siehe What Is a Glob? in der Anleitung, die Sie verknüpft haben, und vergleichen Sie das mit der Dokumentation für java.util.regex.Pattern.
Globbing ist ziemlich viel begrenzter als reguläre Ausdrücke.

Wenn Sie eine strenge Dateibenennungskonvention haben, die streng zu Ihnen passt, können Sie wahrscheinlich globbing verwenden (ich nehme den letzten Teil meines vorherigen Kommentars zurück).

Lassen Sie uns sagen, dass Ihre Dateien als
numeric part number benannt sind - space-optional revision & space - description

Das heißt, die Teilenummer, eine variable Anzahl von Ziffern haben, aber den Raum nach der Teilenummer erforderlich ist und immer vorhanden .

So Ihr Beispiel "12345 RevA Really Big Teil 2: Elektrisch Bugaloo" passt, dass mit partNum == 12345, Revision = "RevA", description = "Really Big Teil 2: Elektrisch Bugaloo"

A Benutzer gibt eine Teilenummer P/N: 123 als Variable userPN und Sie eine glob als
String glob = userPN + " *"; was zu glob konstruieren "123 *"
Dies wird nicht Spiel 12345 gleich, wie Sie es wünschen, weil der Raum nach dem 3 nicht die 4 entsprechen .

Wenn es nicht ein Platzbedarf nach der Teilenummer im Dateinamen ist, aber was ist folgt immer alphabetische entweder die Revision oder die Beschreibung können Sie eine glob konstruieren als
String glob = userPN + "[A-Z,a-z]*"; glob geben = 123[A-Z,a-z]* das stimmt auch nicht mit 12345 überein, weil ein Alphabet der 123 folgen muss und die 4 nicht in diesem Zeichenbereich ist.

Sie können Ihren Charakter Bereich komplizierter, sagen [A-Z,a-z, ] für einen optional Raum, je nach Bedarf, aber allem wirklich kommt auf Ihre Dateinamenskonvention machen. Sie müssen diese Konvention sehr genau angeben und sich daran halten.


[1] a PathMatcherkann einen regulären Ausdruck verwenden, anstatt Globbing, wenn Sie die "Syntax" als regex angeben, wenn FileSystem.getPathMatcher(String) aufrufen. Das wäre so etwas wie

FileSystem fs = FileSystems.getDefault(); 
PathMatcher pm = fs.getPathMatcher("regex:\\d{5}\\s.*"); 
+0

Wenn Sie den ersten Link, den ich gepostet habe, direkt unter dem Link "Was ist ein Glob?" ist eine Zeile, die besagt, dass Regex mit PathMatchers verwendet werden kann. Deshalb setze ich "regex: ..." anstelle von "glob: ..." in meine übereinstimmende Aussage. Es sieht jedoch so aus, als hätte ich das zu kompliziert gemacht. Danke, dass du es für mich vereinfacht hast. –

+0

@Eric - Ich sah das _ "Glob Syntax ist einfach zu bedienen und flexibel, aber, wenn Sie bevorzugen, können Sie auch reguläre Ausdrücke oder Regex, Syntax verwenden." _ Aber sah keine Möglichkeit, das zu tun. Ich habe nun [getPathMatcher] (https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-) gefunden, wo Sie sind kann "regex: " als das Argument _syntaxAndPattern_ angeben. Dies zu wissen könnte zukünftigen Lesern zugute kommen. –

0

Ich denke, Sie gehen auf sehr komplizierten Weg. Warum solltest du Pat Marc zuerst benutzen, wenn du nicht nach Ereignissen suchst?

Viel einfacher wäre es, durch den Dateibaum zu gehen und für jeden Verzeichnis-Iterate-Verzeichnis-Stream zu Ihrem Glob zu passen.