Alle Dateinamen ermitteln

Diskutiere Alle Dateinamen ermitteln im Allgemeine Java-Themen Bereich.
S

Schuriko

Wie kann ich am effektivsten aus einem gegebenen Verzeichnis alle Dateinamen ohne Endung ermitteln?

z.B.
c:\temp
name1.txt
name2.txt
name3.txt


ergibt
name1
name2
name3

P.S.
Die Endung ist identisch
 
mihe7

mihe7

Zum Beispiel:
Java:
Files.list(Paths.get("."))
    .map(Path::getFileName)
    .map(Path::toString)
    .map(x -> (x.lastIndexOf('.') > 0 ? x.substring(0, x.lastIndexOf('.')) : x))
    .forEach(System.out::println)
 
S

Schuriko

Danke dir. Könntest du mir dein Konstrukt etwas erklären. Wo gebe ich z.B. das Verzeichnis an????
 
mihe7

mihe7

Java:
Files.list(Paths.get("."))  // Stream aller Pfade im aktuellen Verzeichnis (".") erzeugen
    .map(Path::getFileName)  // von jedem Pfad nur das letzte Element (=Dateiname) betrachten 
    .map(Path::toString) // und zwar als String
    .map(x -> (x.lastIndexOf('.') > 0 ? x.substring(0, x.lastIndexOf('.')) : x)) // die Extension, falls vorhanden, abschneiden
    .forEach(System.out::println)  // und ausgeben
 
G

GrünerPlanet

Oder so:
Java:
public static void main(String[] args) throws IOException {
	Files.list(Paths.get("."))
	.map(Path::getFileName)
	.map(Path::toString)
	.collect(Collectors.toMap(Function.identity(), t -> t.lastIndexOf(".")))
	.entrySet().stream()
	.filter(e -> e.getValue() >= 0)
	.map(e -> e.getKey().substring(e.getValue(), e.getKey().length()))
	.forEach(System.out::println);
}
Du hattest zweimal den lastIndexOf Aufruf und den ternären Operator.
 
L

LimDul

Oder so:
Java:
public static void main(String[] args) throws IOException {
	Files.list(Paths.get("."))
	.map(Path::getFileName)
	.map(Path::toString)
	.collect(Collectors.toMap(Function.identity(), t -> t.lastIndexOf(".")))
	.entrySet().stream()
	.filter(e -> e.getValue() >= 0)
	.map(e -> e.getKey().substring(e.getValue(), e.getKey().length()))
	.forEach(System.out::println);
}
Du hattest zweimal den lastIndexOf Aufruf und den ternären Operator.
Das finde ich aber schwerer lesbarer - ab der toMap Funktion muss ich genau überlegen, was passiert.
Wenn würde ich eher das map von @mihe7, wo der ternäre Operator und das indexOf vorkommt in eine eigene Funktion auslagen - String removeFileExtension(String fileName). Dann wird er Stream ausdruck zum einen lesbarer, zum anderen aus architektonischer Sicht kann ich die Funktion dann auch separat testen.
 
G

GrünerPlanet

Nein, den ternären Operator sollte man in Streams vermeiden, er verschlechtert die Lesbarkeit. Was möchtest du denn testen? Ob "e.getValue() >= 0" das richtige Ergebnis zurück gibt?
 
mrBrown

mrBrown

Nein, den ternären Operator sollte man in Streams vermeiden, er verschlechtert die Lesbarkeit.
Deshalb sagte er ja auch, den Teil in eine extra Funktion auslagern. Der ternäre Operator ist dem Lambda geschuldet.

Wenn man es auslagert sieht das im Vergleich so aus:

Java:
Files.list(Paths.get("."))
.map(Path::getFileName)
.map(Path::toString)
.map(FileHelper::removeSuffix)



.forEach(System.out::println)
Java:
Files.list(Paths.get("."))
.map(Path::getFileName)
.map(Path::toString)
.collect(Collectors.toMap(Function.identity(), t -> t.lastIndexOf(".")))
.entrySet().stream()
.filter(e -> e.getValue() >= 0)
.map(e -> e.getKey().substring(e.getValue(), e.getKey().length()))
.forEach(System.out::println);

Bei letzterem wird jeder mit etwas Erfahrung schreiend im Kreis rennen oder die nächste Brücke suchen.

Was möchtest du denn testen? Ob "e.getValue() >= 0" das richtige Ergebnis zurück gibt?
Ob die Dateiendung korrekt entfernt wird.

Wenn man Testet würde man zB merken, dass dein Code im Gegensatz zu dem von @mihe7 falsch ist.
 
L

LimDul

Nein, den ternären Operator sollte man in Streams vermeiden, er verschlechtert die Lesbarkeit. Was möchtest du denn testen? Ob "e.getValue() >= 0" das richtige Ergebnis zurück gibt?
Ob folgendes passiert:

EingabeAusgabe
a.txta
.txt
a.b.c.txta.b.c
a.txt.a.txt
aa

Bei deinem Code passiert davon gar nichts.
a) Dateien ohne Endung werden ausgefiltert und nicht ausgegeben.
b) Du gibts nicht den Teil vor der Endung aus, sondern den Teil ab der Endung

Und genau das meine ich mit schwerer lesbar - ich muss bei deinem substring Audruck zurückdenken, was Key und was Value ist - das ist zwar nicht schwer, aber ist eine notwendige Transferleistung. Das heißt, diese Zeile ist nicht für sich alleine verständlich. Sowas lässt sich zwar nicht immer vermeiden, aber wenn möglich sollte man es man es versuchen zu vermeiden. Denn wie man schön an diesem Beispiel sieht, schleichen sich da schnell Fehler ein.
 
G

GrünerPlanet

Der . gehört mit zur Dateiendung.

dass dein Code im Gegensatz zu dem von @mihe7 falsch ist
Wie bist du denn drauf?

Wenn der vordere Teil gewünscht ist, dann eben so, aber so viel Transferleistung hätte ich von jedem erwartet:
Java:
public static void main(String[] args) throws IOException {
	Files.list(Paths.get("."))
	.map(Path::getFileName)
	.map(Path::toString)
	.collect(Collectors.toMap(Function.identity(), t -> t.lastIndexOf(".")))
	.entrySet().stream()
	.filter(e -> e.getValue() > 0) // write >= 0, if you want empty Strings
	.map(e -> e.getKey().substring(0, e.getValue()))
	.forEach(System.out::println);
}
 
Zuletzt bearbeitet:
L

LimDul

Der . gehört mit zur Dateiendung.


Wie bist du denn drauf?
Weil es im ersten Post steht

Wenn der vordere Teil gewünscht ist, dann eben so, aber so viel Transferleistung hätte ich von jedem erwartet:
Java:
public static void main(String[] args) throws IOException {
	Files.list(Paths.get("."))
	.map(Path::getFileName)
	.map(Path::toString)
	.collect(Collectors.toMap(Function.identity(), t -> t.lastIndexOf(".")))
	.entrySet().stream()
	.filter(e -> e.getValue() > 0) // write >= 0, if you want empty Strings
	.map(e -> e.getKey().substring(0, e.getValue()))
	.forEach(System.out::println);
}
Immer noch falsch, weil Dateien ohne Endung weiterhin ausgefiltert werden.
 
J

JustNobody

Ach je, wieder einmal
a) wurden die Anforderungen falsch beschrieben und
b) alle bis auf einen haben keine Ahnung.

Und natürlich ist es für ein Genie sehr schwer zu erfassen, was weniger geniale Menschen noch als lesbar empfinden....

Also kann nicht mal ein Mod hier eingreifen und zum einen die Frage des TEs editieren so dass der einzig wahre Code passt und zum anderen die absolut lachhafte Kritik sowie die schlechten Lösungsversuche der Anderen löschen? Das kürzt das alles, was noch kommt, direkt ab.

*SCNR*

Und ja, bei mir gab es heute Mittag Clown - daher bitte nicht böse mit mir sein. Danach bin ich halt so :)
 
B

BigRiverEntertain

Weil es im ersten Post steht
In der Aufgabe steht nirgendwo, was mit "foo.", ".bar" und "baz" passieren soll, von daher lässt sich gar nicht sagen das sei falsch...
Wenn Dateien ohne Endung berücksichtigt werden sollen...
Java:
public static void main(String[] args) throws IOException {
	Map<Boolean, List<String>> groups = Files.list(Paths.get(".")).map(Path::getFileName).map(Path::toString)
			.collect(Collectors.groupingBy(s -> s.contains(".")));
	groups.get(true).stream().map(s -> s.substring(0, s.lastIndexOf("."))).forEach(System.out::println);
	groups.get(false).stream().forEach(System.out::println);
}
Eine Fallunterscheidung in Streams ist immer hässlich... Insofern ist "GrünerPlanet" zuzustimmen. :)
 
J

JustNobody

Also den ternären Operator selbst finde ich auch unschön - da ist die Methode wie in #8 zu sehen - eine sehr schöne Lösung.

Die Alternative aus #5 ist aber extrem unleserlich. Selbst die Lösung aus #17 sehe ich als suboptimal an.

Wieso muss man so viel in streams machen? Meine Lösung wäre da sogar gewesen:
Code:
Files.list(Paths.get("."))
    .map(FileHelper::getFileNameWithoutSuffix)
    .forEach(System.out::println);
 
mrBrown

mrBrown

In der Aufgabe steht nirgendwo, was mit "foo.", ".bar" und "baz" passieren soll, von daher lässt sich gar nicht sagen das sei falsch...
Es lässt sich völlig eindeutig sagen, dass der Code falsch war. Nur die Endung zurückgeben ist einfach das völlige Gegenteil von "Dateinamen ohne Endung".

Man kann natürlich über "foo.", ".bar" und "baz" streiten. Allerdings ist die Annahme, dass ein Dateiname ohne Endung bereits ein Dateiname ohne Endung ist, deutlich sinnvoller als die Annahme, dass Dateinamen ohne Endung wegzuwerfen sind. Okhams Razor, Principle of Least Surprise, etc...

Eine Fallunterscheidung in Streams ist immer hässlich... Insofern ist "GrünerPlanet" zuzustimmen. :)
Allerdings ist kaum etwas hässlicher als eine Map für sowas zu missbrauchen, nicht mal Fallunterscheidung in Streams.
 
Thema: 

Alle Dateinamen ermitteln

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben