Czy System.IO.Path.Combine()
w C # / .NET istnieje odpowiednik Java ? Lub jakiś kod, aby to osiągnąć?
Ta metoda statyczna łączy jeden lub więcej ciągów w ścieżkę.
Czy System.IO.Path.Combine()
w C # / .NET istnieje odpowiednik Java ? Lub jakiś kod, aby to osiągnąć?
Ta metoda statyczna łączy jeden lub więcej ciągów w ścieżkę.
Odpowiedzi:
Zamiast utrzymywać wszystko oparte na łańcuchach, powinieneś użyć klasy zaprojektowanej do reprezentowania ścieżki systemu plików.
Jeśli używasz Java 7 lub Java 8, powinieneś zdecydowanie rozważyć użycie java.nio.file.Path
; Path.resolve
można użyć do połączenia jednej ścieżki z drugą lub z łańcuchem. Paths
Klasa pomocnika jest zbyt przydatny. Na przykład:
Path path = Paths.get("foo", "bar", "baz.txt");
Jeśli chcesz obsługiwać środowiska starsze niż Java-7, możesz użyć java.io.File
:
File baseDirectory = new File("foo");
File subDirectory = new File(baseDirectory, "bar");
File fileInDirectory = new File(subDirectory, "baz.txt");
Jeśli chcesz później wrócić jako ciąg znaków, możesz zadzwonić getPath()
. Rzeczywiście, jeśli naprawdę chcesz naśladować Path.Combine
, możesz po prostu napisać coś takiego:
public static String combine(String path1, String path2)
{
File file1 = new File(path1);
File file2 = new File(file1, path2);
return file2.getPath();
}
path2
(ignoruje path1
), jeśli path2
jest to ścieżka bezwzględna. Wersja Java upuści wiodący /
lub \
potraktuje go jako ścieżkę względną.
File.getCanonicalPath
.
File
w C #, jeśli chcesz. (Zakładam, że masz na myśli istnienie File
korzyści, z którą się zgodziłbym.)
W Javie 7 powinieneś użyć resolve
:
Path newPath = path.resolve(childPath);
Chociaż klasa Ścieżka NIO2 może wydawać się nieco redundantna dla File z niepotrzebnie innym API, jest w rzeczywistości subtelniej bardziej elegancka i solidna.
Zauważ, że Paths.get()
(jak sugeruje ktoś inny) nie ma przeciążenia biorąc Path
, a robienie Paths.get(path.toString(), childPath)
NIE jest tym samym resolve()
. Z Paths.get()
dokumentów :
Zauważ, że chociaż ta metoda jest bardzo wygodna, jej użycie będzie oznaczało domniemane odniesienie do domyślnego systemu plików i ograniczy użyteczność kodu wywołującego. Dlatego nie należy go stosować w kodzie biblioteki przeznaczonym do elastycznego ponownego wykorzystania. Bardziej elastyczną alternatywą jest użycie istniejącej instancji Path jako kotwicy, na przykład:
Path dir = ... Path path = dir.resolve("file");
Funkcja siostrzana resolve
to doskonała relativize
:
Path childPath = path.relativize(newPath);
Główną odpowiedzią jest użycie obiektów File. Jednak Commons IO ma klasę FilenameUtils, która potrafi tego typu rzeczy, takie jak metoda concat () .
Wiem, że minęło dużo czasu od oryginalnej odpowiedzi Jona, ale miałem podobny wymóg co OP.
Rozszerzając rozwiązanie Jona, wymyśliłem następujące, które zajmą jeden lub więcej segmentów ścieżki, zajmując tyle segmentów ścieżki, ile możesz na nią rzucić.
Stosowanie
Path.combine("/Users/beardtwizzle/");
Path.combine("/", "Users", "beardtwizzle");
Path.combine(new String[] { "/", "Users", "beardtwizzle", "arrayUsage" });
Kod tutaj dla innych z podobnym problemem
public class Path {
public static String combine(String... paths)
{
File file = new File(paths[0]);
for (int i = 1; i < paths.length ; i++) {
file = new File(file, paths[i]);
}
return file.getPath();
}
}
niezależne od platformy podejście (wykorzystuje File.separator, tzn. będzie działać, zależy od systemu operacyjnego, w którym działa kod:
java.nio.file.Paths.get(".", "path", "to", "file.txt")
// relative unix path: ./path/to/file.txt
// relative windows path: .\path\to\filee.txt
java.nio.file.Paths.get("/", "path", "to", "file.txt")
// absolute unix path: /path/to/filee.txt
// windows network drive path: \\path\to\file.txt
java.nio.file.Paths.get("C:", "path", "to", "file.txt")
// absolute windows path: C:\path\to\file.txt
Aby ulepszyć odpowiedź JodaStephen, Apache Commons IO ma FilenameUtils, który to robi. Przykład (w systemie Linux):
assert org.apache.commons.io.FilenameUtils.concat("/home/bob", "work\\stuff.log") == "/home/bob/work/stuff.log"
Jest niezależny od platformy i produkuje wszelkie separatory, których potrzebuje Twój system.
Oto rozwiązanie, które obsługuje wiele części ścieżki i warunki krawędzi:
public static String combinePaths(String ... paths)
{
if ( paths.length == 0)
{
return "";
}
File combined = new File(paths[0]);
int i = 1;
while ( i < paths.length)
{
combined = new File(combined, paths[i]);
++i;
}
return combined.getPath();
}
Jeśli nie potrzebujesz więcej niż ciągów, możesz użyć com.google.common.io.Files
Files.simplifyPath("some/prefix/with//extra///slashes" + "file//name")
dostać
"some/prefix/with/extra/slashes/file/name"
Może późno na imprezę, ale chciałem się z tym zgodzić. Używam wzorca konstruktora i zezwalam na wygodne append
połączenia łańcuchowe . Można go łatwo rozszerzyć, aby obsługiwał także pracę z Path
obiektami.
public class Files {
public static class PathBuilder {
private File file;
private PathBuilder ( File root ) {
file = root;
}
private PathBuilder ( String root ) {
file = new File(root);
}
public PathBuilder append ( File more ) {
file = new File(file, more.getPath()) );
return this;
}
public PathBuilder append ( String more ) {
file = new File(file, more);
return this;
}
public File buildFile () {
return file;
}
}
public static PathBuilder buildPath ( File root ) {
return new PathBuilder(root);
}
public static PathBuilder buildPath ( String root ) {
return new PathBuilder(root);
}
}
Przykład użycia:
File root = File.listRoots()[0];
String hello = "hello";
String world = "world";
String filename = "warez.lha";
File file = Files.buildPath(root).append(hello).append(world)
.append(filename).buildFile();
String absolute = file.getAbsolutePath();
Wynikowy absolute
będzie zawierać coś takiego:
/hello/world/warez.lha
a może nawet:
A:\hello\world\warez.lha
Działa to również w Javie 8:
Path file = Paths.get("Some path");
file = Paths.get(file + "Some other path");
To rozwiązanie oferuje interfejs do łączenia fragmentów ścieżek z tablicy String []. Używa java.io.File.File (String string, child String) :
public static joinPaths(String[] fragments) {
String emptyPath = "";
return buildPath(emptyPath, fragments);
}
private static buildPath(String path, String[] fragments) {
if (path == null || path.isEmpty()) {
path = "";
}
if (fragments == null || fragments.length == 0) {
return "";
}
int pathCurrentSize = path.split("/").length;
int fragmentsLen = fragments.length;
if (pathCurrentSize <= fragmentsLen) {
String newPath = new File(path, fragments[pathCurrentSize - 1]).toString();
path = buildPath(newPath, fragments);
}
return path;
}
Następnie możesz po prostu zrobić:
String[] fragments = {"dir", "anotherDir/", "/filename.txt"};
String path = joinPaths(fragments);
Zwroty:
"/dir/anotherDir/filename.txt"