Java'da yollar nasıl birleştirilir?


350

System.IO.Path.Combine()C # /. NET için bir Java eşdeğeri var mı ? Veya bunu gerçekleştirmek için herhangi bir kod?

Bu statik yöntem, bir veya daha fazla dizeyi bir yol içinde birleştirir.


1
Bu SO sorusu yardımcı olabilir.
Jim Blizard

Yanıtlar:


408

Her şeyi dizeye dayalı tutmak yerine, bir dosya sistemi yolunu temsil edecek şekilde tasarlanmış bir sınıf kullanmalısınız.

Java 7 veya Java 8 kullanıyorsanız java.nio.file.Path, kullanmayı kesinlikle düşünmelisiniz ; Path.resolvebir yolu başka bir yolla veya bir dize ile birleştirmek için kullanılabilir. PathsYardımcı sınıfı çok yararlıdır. Örneğin:

Path path = Paths.get("foo", "bar", "baz.txt");

Java-7 öncesi ortamlara hitap etmeniz gerekiyorsa, aşağıdakini kullanabilirsiniz java.io.File:

File baseDirectory = new File("foo");
File subDirectory = new File(baseDirectory, "bar");
File fileInDirectory = new File(subDirectory, "baz.txt");

Daha sonra bir dize olarak geri almak isterseniz, arayabilirsiniz getPath(). Gerçekten, eğer gerçekten taklit etmek Path.Combineistiyorsanız, sadece şöyle bir şey yazabilirsiniz:

public static String combine(String path1, String path2)
{
    File file1 = new File(path1);
    File file2 = new File(file1, path2);
    return file2.getPath();
}

10
Mutlak yollara dikkat edin. Mutlak bir path2yolsa .NET sürümü (yoksayılıyor path1) döndürür path2. Java sürümü öncüyü bırakır /veya \ göreli bir yol olarak görür.
finnw

23
@Matthew - bir dizin bir dosya olduğundan. İçeriği o
dizinin alt öğelerini

7
@Hugo: Demek iki nesneyi boşa harcıyor ? Şok edici! Bana çok temiz görünüyor, dürüst olmak gerekirse ... Dosya sınıfında ait olduğu göreceli dosya adları için mantığı tutar .
Jon Skeet

1
@modosansreves: Şuna bak File.getCanonicalPath.
Jon Skeet

1
@SargeBorsch: C # sadece bir dildir. İsterseniz FileC # ile kolayca kendi eşdeğerinizi oluşturabilirsiniz . (Varlığını kabul etmenin Filebir fayda olduğunu düşündüğünüzü varsayıyorum .)
Jon Skeet

118

Java 7'de şunları kullanmalısınız resolve:

Path newPath = path.resolve(childPath);

NIO2 Path sınıfı, gereksiz bir şekilde farklı bir API ile File'a biraz gereksiz gibi görünse de, aslında daha zarif ve sağlamdır.

Not Paths.get()aşırı yük bir alarak yoktur (başkası tarafından önerildiği gibi) Path, ve yapıyor Paths.get(path.toString(), childPath)aynı şey değildir resolve(). Gönderen Paths.get()docs :

Bu yöntem çok uygun olsa da, kullanmanın varsayılan FileSystem için varsayılan bir başvuru anlamına geleceğini ve arama kodunun yardımcı programını sınırlayacağını unutmayın. Bu nedenle, esnek yeniden kullanım için tasarlanmış kütüphane kodunda kullanılmamalıdır. Daha esnek bir alternatif, varolan bir Path örneğini bağlantı olarak kullanmaktır, örneğin:

Path dir = ...
Path path = dir.resolve("file");

Kardeş işlevi resolvemükemmel relativize:

Path childPath = path.relativize(newPath);


17

Jon'un orijinal cevabından bu yana uzun zaman geçtiğini biliyorum, ama OP'ye benzer bir gereksinimim vardı.

Jon'un çözümünü genişleterek, bir ya da daha fazla yol segmenti alacak olan aşağıdakileri buldum.

kullanım

Path.combine("/Users/beardtwizzle/");
Path.combine("/", "Users", "beardtwizzle");
Path.combine(new String[] { "/", "Users", "beardtwizzle", "arrayUsage" });

Benzer bir sorunu olan diğerleri için buraya kod yazın

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();
    }
}

12

platformdan bağımsız yaklaşım (File.separator kullanır, yani çalışır kodun çalıştığı işletim sistemine bağlıdır:

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

11

JodaStephen'in cevabını geliştirmek için Apache Commons IO'nun bunu yapan FilenameUtils vardır. Örnek (Linux'ta):

assert org.apache.commons.io.FilenameUtils.concat("/home/bob", "work\\stuff.log") == "/home/bob/work/stuff.log"

Platformdan bağımsızdır ve sisteminizin ihtiyaç duyduğu ayırıcıları üretecektir.


2

Birden çok yol parçasını ve kenar koşulunu işleyen bir çözüm:

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();
}


1

Partiye geç belki de, ama bunu kabul etmek istedim. Bir Oluşturucu kalıbı kullanıyorum ve uygun şekilde zincirleme appendçağrılara izin veriyorum . PathNesnelerle çalışmayı desteklemek için kolayca genişletilebilir .

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);
    }
}

Kullanım örneği:

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();

Ortaya çıkan sonuç şöyle absoluteolacaktır:

/hello/world/warez.lha

hatta belki:

A:\hello\world\warez.lha

1

Java 8'de de çalışır:

Path file = Paths.get("Some path");
file = Paths.get(file + "Some other path");

0

Bu çözüm, bir String [] dizisinden yol parçalarını birleştirmek için bir arabirim sunar. O kullanır java.io.File.File (Dize ebeveyn, dize çocuk) :

    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;
    }

Sonra sadece şunları yapabilirsiniz:

String[] fragments = {"dir", "anotherDir/", "/filename.txt"};
String path = joinPaths(fragments);

İadeler:

"/dir/anotherDir/filename.txt"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.