Приєднання шляхів у Java


99

У Pythonсклеїти два шляхи з os.path.join:

os.path.join("foo", "bar") # => "foo/bar"

Я намагаюся досягти того ж на Java, не переживаючи, чи OSє Unix, Solarisчи Windows:

public static void main(String[] args) {
    Path currentRelativePath = Paths.get("");
    String current_dir = currentRelativePath.toAbsolutePath().toString();
    String filename = "data/foo.txt";
    Path filepath = currentRelativePath.resolve(filename);

    // "data/foo.txt"
    System.out.println(filepath);

}

Я очікував, що Path.resolve( )приєднається до мого поточного каталогу /home/user/testіз data/foo.txtстворенням /home/user/test/data/foo.txt. Що я помиляюся?


1
це може бути щось, чого я не бачу. Ваш поточний шлях "". Ваш другий шлях - "data / foo.txt". Можливо, ваша проблема полягає в тому, що вам здається, що ви друкуєте об'єкт Path замістьfilepath.toString()
cjds

2
Використанняnew File(parent, child)
saka1029

Відповіді:


99

Навіть незважаючи на те, що оригінальне рішення для отримання поточного каталогу з використанням empty Stringтворів. Але рекомендується використовувати user.dirвластивість для поточного каталогу та user.homeдля домашнього каталогу.

Path currentPath = Paths.get(System.getProperty("user.dir"));
Path filePath = Paths.get(currentPath.toString(), "data", "foo.txt");
System.out.println(filePath.toString());

вихід:

/Users/user/coding/data/foo.txt

З документації класу Java Path :

Шлях вважається порожнім шляхом, якщо він складається виключно з одного елемента імені, який є empty. Доступ до файлу за допомогою empty path is equivalent to accessing the default directoryфайлової системи.


Чому Paths.get("").toAbsolutePath()працює

Коли порожній рядок передається до Paths.get(""), повернутий Pathоб'єкт містить порожній шлях. Але коли ми дзвонимо Path.toAbsolutePath(), він перевіряє, чи довжина шляху більша за нуль, інакше він використовуєuser.dir властивість системи та повертає поточний шлях.

Ось код для реалізації файлової системи Unix: UnixPath.toAbsolutePath ()


В основному вам потрібно створити Pathекземпляр ще раз, коли ви вирішите поточний шлях до каталогу.

Також я б запропонував використовувати File.separatorCharдля незалежної платформи код.

Path currentRelativePath = Paths.get("");
Path currentDir = currentRelativePath.toAbsolutePath(); // <-- Get the Path and use resolve on it.
String filename = "data" + File.separatorChar + "foo.txt";
Path filepath = currentDir.resolve(filename);

// "data/foo.txt"
System.out.println(filepath);

Вихід:

/Users/user/coding/data/foo.txt

Не я, можливо, хтось думає, що працює над струнами і separatorCharпоступається якійсь "абстракції вищого рівня", щось подібнеPathBuilder(currentRelativePath).append("data").append("foo.txt")
jingyu9575

22

Paths#get(String first, String... more) штати,

Перетворює рядок шляху або послідовність рядків, які, приєднавшись, утворюють рядок шляху, до Path.

...

Path, Що представляють собою порожній шлях повертається , якщо перша порожній рядок і більше не містять будь - яких непусті рядки.

Щоб отримати поточний каталог користувачів, ви можете просто скористатися ним System.getProperty("user.dir").

Path path = Paths.get(System.getProperty("user.dir"), "abc.txt");
System.out.println(path);

Крім того, getметод використовує змінну довжину аргумент з String, який буде використовуватися , щоб забезпечити наступні рядки шляху. Таким чином, щоб створити Pathдля /test/inside/abc.txtвас повинні використовувати його в такий спосіб,

Path path = Paths.get("/test", "inside", "abc.txt");

11

Не конкретний метод.

Якщо ви використовуєте java 8 або вище, у вас є 2 варіанти:

а) Використовуйте java.util.StringJoiner

StringJoiner joiner = new StringJoiner(File.pathSeparator); //Separator
joiner.add("path1").add("path2");
String joinedString = joiner.toString();

б) Використовуйте String.join(File.pathSeparator, "path1", "path2");

Якщо ви використовуєте java 7 або новішу версію, ви можете використовувати бібліотеку commons-lang від apache commons. Клас StringUtils має метод з'єднання рядків за допомогою роздільника.

в) StringUtils.join(new Object[] {"path1", "path2"}, File.pathSeparator);

Сторінка: Ви можете використовувати linux pathseparator "/" для Windows (просто пам’ятайте, що абсолютні шляхи є чимось на зразок "/ C: / mydir1 / mydir2". Використання завжди "/" дуже корисно, якщо ви використовуєте протоколи, такі як файл: //


StringJoiner повернув мене/home/user/test:foo.txt
cybertextron

Ваші варіанти, про які ви знаєте, не єдині, що існують. Наприклад, StringBuilder можна використовувати замість столярного. Насправді ваша реалізація на основі Strings, а не файлів / контурів є досить наївною і може призвести до проблем у багатьох сценаріях.
XenoRo

2
File.separatorпрацював у мене замістьFile.pathSeparator
Еван Сірокі

використовуйте Pathes.get ("path1", "path2"). toAbsolutePath (). toString ()
Erdinc Ay

5

Найбільш основний спосіб:

Path filepath = Paths.get("foo", "bar");

Ніколи не слід писати Paths.get(""). Я здивований, що це взагалі працює. Якщо ви хочете прямо посилатися на поточний каталог, використовуйте Paths.get(System.getProperty("user.dir")). Якщо ви хочете домашній каталог користувача, використовуйте Paths.get(System.getProperty("user.home")).

Ви також можете комбінувати підходи:

Path filepath = Paths.get(
    System.getProperty("user.home"), "data", "foo.txt");

1

Найбільш надійний, незалежний від платформи спосіб приєднання шляхів на Java - це за допомогою Path::resolve(як зазначено в JavaDoc for Paths::get). Для масиву рядків довільної довжини, що представляють фрагменти шляху, їх можна об'єднати за допомогою потоку Java:

private static final String[] pieces = {
    System.getProperty("user.dir"),
    "data",
    "foo.txt"};
public static void main (String[] args) {
    Path dest = Arrays.stream(pieces).reduce(
    /* identity    */ Paths.get(""),
    /* accumulator */ Path::resolve,
    /* combiner    */ Path::resolve);
    System.out.println(dest);
}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.