File.separator ile yollardaki eğik çizgi arasındaki fark


200

Java Path-String'de kullanma File.separatorve normal /arasındaki fark nedir ?

İki ters eğik çizgi \\platformunun aksine , her iki sürüm de Windows ve Unix altında çalıştığı için bağımsızlık nedeni görünmüyor.

public class SlashTest {
    @Test
    public void slash() throws Exception {
        File file = new File("src/trials/SlashTest.java");
        assertThat(file.exists(), is(true));
    }

    @Test
    public void separator() throws Exception {
        File file = new File("src" + File.separator + "trials" + File.separator + "SlashTest.java");
        assertThat(file.exists(), is(true));
    }
}

Soruyu yeniden ifade etmek için /, Unix ve Windows üzerinde çalışıyorsa neden kullanmak istesin ki File.separator?


5
@Ring 'Tarihsel nedenler' gibi ne?
Lorne Marquis

Yanıtlar:


247

Dosyalarla uğraşmak için Java kitaplıklarıyla /, tüm platformlarda güvenle (eğik çizgi, ters eğik çizgi kullanamazsınız) kullanabilirsiniz . Kütüphane kodu, şeyleri dahili olarak platforma özgü yollara çevirmeyi işler.

File.separatorBununla birlikte, kullanıcı arayüzünde kullanmak isteyebilirsiniz , çünkü insanlara Java için anlamlı olanlardan ziyade işletim sistemlerinde neyin anlamlı olacağını göstermek en iyisidir.

Güncelleme : Beş dakika aramayla belgelenmiş "her zaman bir eğik çizgi kullanabilirsiniz" davranışını bulamadım. Şimdi, belgelenmiş olduğunu gördüm eminim, ama resmi bir referans bulma eksikliği (çünkü hafızam mükemmel değil), ben işe yarayacağını biliyorFile.separator çünkü .


2
Ayırıcıların çalışma zamanında başka bir şeye dönüştürülmesini beklediğiniz için, bu performansla ilgili bir sorun da olabilir. Ayrıca, bunun tüm desteklenmeyen JVM'lerde olmasını beklemeyin.
jpabluz

7
@TJ Crowder: "Beş dakika aramayla" her zaman eğik çizgi kullanabilirsiniz "davranışını bulamadım." JVM'nin bir özelliği değil, Windows NT API'sinin bir özelliği.
Mart'ta Powerlord

12
@ Powerlord: Windows da yaparsa, harika - ama kütüphane (JVM değil) de bunu yapıyor. Özellikle, Filekullandığı FileSystem.normalize"normalleştirmek" kamu API üzerinden alınan yolları ve neredeyse hiçbir şeye yerde bütün bu dosya yolu dizeleri ile fırsatlar (örneğin FileWriter(String)) kullandığı Fileörtülerin altında.
TJ Crowder

9
Java7 beri artık File.separator kullanmaya gerek yok. Dir - dir ve dir - dosya adı birleştirmek için java.nio.file.Paths (Paths.get (ilk olarak, daha fazla ...)) kullanmak çok daha basit ve daha temizdir.
magiccrafter

6
@jpabluz 'Performansla ilgili bir sorun'! Ciddi misin? Kullanım adlarının disk üzerine konulduğu dikkate alındığında, bir çevirinin çalışma zamanı etkisi tamamen önemsizdir. Şartnamenin bir parçası olduğu için herhangi bir JVM tarafından desteklenmelidir File.
Lorne

316

Sen kullanmak File.separatorbirgün programı geliştirilen bir platformda aday olabileceğini çünkü uzak bir arazi, at ağlama ve inekler tüm asansörler işletmek garip şeyler ve yabancı insanların, bir arazi. Bu ülkede, insanlar geleneksel olarak ":" karakterini bir dosya ayırıcısı olarak kullandılar ve böylece JVM isteklerine uyuyor.


4
Evet, sivri gerçekten elbonia bizi took (umarım sivri saç kesimi yoktur ;-) (geek pun içeride)
Riduidel

5
"... ve inekler tüm asansörleri çalıştırıyor." Bunu okuduğumda da bir yudum kahve içmemiştim. Parlak.
TJ Crowder

8
Böyle bir ülkede, tüm bu deliliği rahatınız için yerleştiren yeni org.apache.chicken.elevators.OperatorUtility sınıfından yararlanacaksınız.
Beyin

27

Her ne kadar bir dosya adına başvurmak için File.separator kullanmak aşırıya kaçmış olsa da (çok uzak toprakları hayal edenler için, JVM uygulamalarının bir Windows jvm'nin a /ile değiştirdiği gibi bir ile değiştireceğini hayal ediyorum ).:\

Ancak, bazen dosya referansını alırsınız, oluşturmazsınız ve ayrıştırmanız gerekir ve bunu yapabilmek için platformdaki ayırıcıyı bilmeniz gerekir. File.separator bunu yapmanıza yardımcı olur.


11

Tamam, bazı kodları inceleyelim.
File.java428 ila 435 hatları File.<init>:

String p = uri.getPath();
if (p.equals(""))
    throw new IllegalArgumentException("URI path component is empty");

// Okay, now initialize
p = fs.fromURIPath(p);
if (File.separatorChar != '/')
p = p.replace('/', File.separatorChar);

Ve fs/*(FileSystem)*/.fromURIPath()dokümanları okuyalım:

java.io.FileSystem
public abstract Dize fromURIPath (Dize yolu)
Gerekirse, verilen URI yolu dizesini sonradan işleyin . Bu, win32'de, örneğin "/ c: / foo" yu "c: / foo" ya dönüştürmek için kullanılır. Yol dizgisi hala eğik çizgi ayırıcılarına sahiptir; File sınıfındaki kod, bu yöntem döndükten sonra bunları çevirir.

Bu, FileSystem.fromURIPath()yalnızca Windows'ta ve sonraki satırda URI yolunda sonradan işlem yapılması anlamına gelir :

p = p.replace('/', File.separatorChar);

Her bir '/' yerine sisteme bağımlıdır seperatorChar, her işletim sisteminde '/' güvenli olduğundan her zaman emin olabilirsiniz .


8

Unix ve Windows'dan (Taşınabilir cihazlar, vb.) Daha fazla işletim sistemi vardır ve Java taşınabilirliği ile bilinir. En iyi uygulama onu kullanmaktır, böylece JVM o işletim sistemi için hangisinin en iyi olduğunu belirleyebilir.


Bu işletim sistemlerinin çoğu UNIX'in bazı varyantlarını çalıştırıyor. Eski Mac tarzı :ayırıcılar çoktan gitti. Windows dışındaki herkes /artık standardı kullanıyor gibi görünüyor . Ve pencereler bile artık eğik çizgileri ele alıyor gibi görünüyor. cd /windows/systemAna sistem sürücünüzden bir Windows 10 sistemi deneyin . Yine de sistem ayırıcısını kullanarak yolları görüntülemek isteseniz de (kullanıcılarınızı karıştırmamak için) eğik çizgiyi /başka her yerde kullanabilir ve kodunuzun konuşlandırdığınız her yerde çalışacağından emin olabilirsiniz.
Gölge Adam

7

Giriş yolunda fazla bir fark yaratmasa da, geri dönüş yolunda.

Elbette yeni Dosya'da (Dize yolu) '/' veya '\' kullanabilirsiniz, ancak File.getPath () size bunlardan yalnızca birini verecektir.


Hafif düzeltme ... Windows'da ileri /veya geri \\ eğik çizgi kullanabilirsiniz. Ancak başka herhangi bir yerde, eğik çizgi kullanmanız iyi olur, yoksa /sorunlarınız olur.
Shadow Man

6

Partiye geç. JDK 1.8 ve Eclipse MARS 1 ile Windows 10
kullanıyorum.

getClass().getClassLoader().getResourceAsStream("path/to/resource");

çalışır ve

getClass().getClassLoader().getResourceAsStream("path"+File.separator+"to"+File.separator+"resource");

çalışmıyor ve

getClass().getClassLoader().getResourceAsStream("path\to\resource");

çalışmıyor. Son ikisi eşdeğerdir. Yani ... File.separator'ı KULLANMAMAK için iyi bir nedenim var.


6
Bu satırda getClass().getClassLoader().getResourceAsStream("path\to\resource");, bir tabulation ( \t) ve bir satırbaşı ( \r) vardır.
Stephan

9
Bu soru için farklı bir senaryo. ClassLoader'ın getResourceAsStream yöntemi bir Dosya yolu almaz, ancak dosya sisteminde olabilecek veya olmayabilecek bir kaynak adı alır ve yalnızca kaynak yolu ayırıcısı olarak '/' kabul ettiği belgelenir .
daiscog

@Stephan File.separatorbir ters eğik çizgi olduğu için orada komik bir kaçış yok . Yalnızca ters eğik çizgiden kaçmanız gereken bir kaçış karakteri olarak değerlendirildiği sabit kodlu dizelerde. Karakteri bir metin dosyasında sakladıysanız veya bir charveya Stringdaha sonra, beklenen ters eğik çizgi karakterine dönüştürüldüğünden 2. kez kaçmanıza gerek yoktur. Kendiniz görmek için bunu deneyin:String backslash = "\\"; System.out.println("welcome" + backslash + "to" + backslash + "reality");
Shadow Man

2
@Stephan oh, anlıyorum ... Sen 3. satırdan bahsediyordun. Haklısın. Bu satırda (sabit kodlu bir dize) kaçış karakterinden kaçmanız gerekir. Gözlerim 2. hatta durdu ve ilk başta 3. hatta fark etmedim.
Gölge Adam

3

taşınabilirlik sade ve basit.


Evet, taşınabilirlik için, do not ters eğik çizgi kullanın. Eğik çizgi /veya sistem ayırıcı kullanın File.separator. Her ikisi de her yerde çalışıyor gibi görünüyor. Her File.separatoryerde çalışacağı garanti edilirken , basit eğik çizgi /de her yerde çalışıyor gibi görünüyor. Bir yerde çalışmazsa, bunu duymak isterim. Tüm sistemlerde çalışacağına inanıyorum. En azından henüz çalışmayan bir yer bulamadım /(Mac OSX, Windows, * nix, Android, iOS - Bir ayırıcı olarak ":" kullanan OSX Mac'leri kontrol etmedim, OS / 2, NeXT veya diğer gerçekten eski işletim sistemlerinden herhangi biri).
Gölge Adam

1

"Programcılar için Java SE8" olduğunu iddia Java ya başa çıkacak. (s. 480, son paragraf). Örnekte şunlar iddia edilmektedir:

c:\Program Files\Java\jdk1.6.0_11\demo/jfc

gayet iyi ayrışacak. Son (Unix tarzı) ayırıcıyı not edin.

Bu yapışkan ve muhtemelen hata eğilimli, ama onlar (Deitel ve Deitel) iddia.

Java yerine insanlar için karışıklık, bu (mis?) Özelliğini kullanmamak için yeterli neden olduğunu düşünüyorum.


1

Beyler farkı değişken detaylarla tarif ettikleri gibi.

Birden fazla işletim sistemine dağıtım olanağı olan bir programdaki dosyalarla uğraşırken Apache Commons io api, sınıfının kullanılmasını tavsiye etmek istiyorum FilenameUtils.


0

Bir dosya veya dizinin yol adı, ana bilgisayar sisteminin adlandırma kuralları kullanılarak belirtilir. Ancak File sınıfı, dosya ve dizin adlarını platformdan bağımsız bir şekilde işlemek için kullanılabilen platforma bağımlı sabitleri tanımlar.

Files.seperator, bir yol adındaki dizini ve dosya bileşenlerini ayıran karakteri veya dizeyi tanımlar. Bu ayırıcı, Unix, Windows ve Macintosh için sırasıyla '/', '\' veya ':' şeklindedir.


Macintosh için ":" çok eskidir. OSX'ten beri Mac, başlık altında standart UNIX dosya sistemine sahip bir UNIX biçimi çalıştırdığı için "/" (eğik çizgi) de kullanır.
Gölge Adam


0

File.separator kullanımı Ubuntu'nun dizinler yerine adında "\" bulunan dosyalar üretmesini sağladı. Belki ben nasıl dosyaları (ve dizinleri) yapmak tembel ve bu adından "\" ile dosyaları önlemek için her zaman "/" kullanmak ne olursa olsun, kaçınmış olabilir


0

Linux ayırıcısını kullanarak hazır bir yoldan (örneğin, veritabanına kaydedilir) bir Dosya oluşturmaya çalışıyorsanız ne yapmalıyım?

Belki sadece dosyayı oluşturmak yolunu kullanın:

new File("/shared/folder/file.jpg");

Ancak Windows farklı bir ayırıcı ( \) kullanır. Peki, alternatif eğik çizgi ayırıcısını platforma dönüştürüyor mu? Sevmek:

new File(convertPathToPlatformIndependent("/shared/folder"));

Bu yöntem convertPathToPlatformIndependentmuhtemelen "/" ile bir tür bölünmeye sahip olacak ve File.separator ile birleşecektir.

Eh, benim için işte hoş değil (? Sağda) platform bağımsız bir dil için ve Java zaten kullanımını destekleyen /Windows veya Linux üzerinde. Ancak yollarla çalışıyorsanız ve bu dönüşüme her seferinde hatırlamanız gerekiyorsa, bu bir kabus olacaktır ve gelecekte uygulama için gerçek bir kazancınız olmayacaktır (belki de @Pointy'nin tanımladığı evrende).

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.