パス内のFile.separatorとスラッシュの違い


200

Java Path-Stringでの使用File.separatorと通常の違いは何/ですか?

二重のバックスラッシュとは対照的に\\、両方のバージョンがWindowsとUnixで動作するため、プラットフォームの独立性は理由ではないようです。

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

質問を言い換えると、もし/UnixとWindowsで動作するなら、なぜ使用したいのFile.separatorでしょうか?


5
@Ring何のような「歴史的理由」?
ローン侯爵2014

回答:


246

ファイルを処理するためのJavaライブラリを使用すると/、すべてのプラットフォームで安全に(バックスラッシュではなくスラッシュ)を使用できます。ライブラリコードは、内部でプラットフォーム固有のパスへの変換を処理します。

File.separatorただし、UIで使用することをお勧めします。これは、Javaにとって意味のあるものではなく、OSで意味のあるものを人々に示すのが最善だからです。

更新:5分間の検索で、「常にスラッシュを使用できる」という動作を文書化することができませんでした。今では、それが文書化されているのを見たと確信していますが、公式の参考文献を見つけられないので(私の記憶は完全ではないため)、それが機能するFile.separatorことを知っているので、使用を続けます。


2
実行時にセパレーターが別のものに変換されることを期待しているため、これもパフォーマンスに問題があるかもしれません。また、これがサポートされていないすべてのJVMで発生することを期待しないでください。
jpabluz

7
@TJ Crowder:「私は、5分間の検索で、「常にスラッシュを使用できる」という動作を文書化することができませんでした。」これはJVMの機能ではなく、Windows NT APIの機能です。
Powerlord、

12
@Powerlord:Windowsでも同じことができればすばらしいですが、ライブラリ(JVMではありません)でも同じことができます。具体的にFileFileSystem.normalize、パブリックAPIを介して受信したパスを「正規化」するために至る所で使用し、ファイルパス文字列を処理するほとんどすべて(たとえばFileWriter(String))は内部で使用Fileします。
TJクラウダー

9
Java7以降、File.separatorを使用する必要はありません。dirからdirおよびdirからファイル名への結合にjava.nio.file.Paths(Paths.get(first、more ...))を使用する方がはるかに単純でクリーンです。
魔法製作者2014

6
@jpabluz「パフォーマンスの問題」!真剣ですか?ファイル名がディスクに配置されることを考慮すると、変換の実行時の影響はまったく重要ではありません。の仕様の一部であるため、JVMでサポートされている必要がありFileます。
ローンの侯爵

316

File.separatorいつかあなたのプログラムは、馬が泣き、牛がすべてのエレベーターを操作する、奇妙なものや見知らぬ人の土地である遠く離れた土地で開発されたプラットフォームで実行される可能性があるために使用します。この土地では、人々は伝統的に「:」文字をファイル区切りとして使用してきたため、JVMは忠実に彼らの希望に従います。


4
うん、Pointyは本当に私たちをエルボニアに連れて行ってくれます(彼が先のとがったヘアカットがないといいのですが
;

4
「...そして牛はすべてのエレベーターを操作します。」同様に、私はそれを読んだときにコーヒーを一口飲んでいませんでした。鮮やかさ。
TJクラウダー

8
そのような国では、新しいorg.apache.chicken.elevators.OperatorUtilityクラスを使用します。このクラスは、すべてのこの狂気をあなたの便宜のために組み込んでいます。
2015年

27

ファイル名を参照するようにFile.separatorを使用すると、過剰ですが(これまでの土地オフ想像する人のために私は彼らのJVMの実装が代わるだろうと想像/して:だけで窓JVM置き換え、それが好き\)。

ただし、ファイル参照を取得して作成するのではなく、解析する必要がある場合があります。これを行うには、プラットフォームのセパレーターを知る必要があります。File.separatorはそのために役立ちます。


11

では、コードをいくつか調べてみましょう。
File.java428〜435行目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);

そして、fs/*(FileSystem)*/.fromURIPath()ドキュメントを読んでみましょう:

java.io.FileSystem
public abstract String fromURIPath(String path)
必要に応じて、指定されたURIパス文字列を後処理します。これは、たとえば「/ c:/ foo」を「c:/ foo」に変換するために、win32で使用されます。パス文字列には引き続きスラッシュセパレータがあります。Fileクラスのコードは、このメソッドが戻った後にそれらを変換します。

これはFileSystem.fromURIPath()、WindowsでのみURIパスで後処理を行うことを意味します。これは、次の行が原因です。

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

各「/」をシステム依存に置き換えseperatorCharます。すべての OS で「/」が安全であることを常に確認できます。


8

まあ、UnixやWindows(ポータブルデバイスなど)よりも多くのOSがあり、Javaはその移植性で知られています。ベストプラクティスはそれを使用することです。そのため、JVMはそのOSに最適なものを決定できます。


これらのOSのほとんどは、UNIXのバリアントを実行しています。古いMacスタイルの:セパレータは廃​​止されて久しい。Windowsを除くすべての人が標準を使用しているよう/です。そして、Windowsでもスラッシュをうまく処理できるようになりました。cd /windows/systemメインシステムドライブからWindows 10システムを試します。(ユーザーを混乱させないために)システムセパレーターを使用してパスを表示したい場合/でも、他のすべての場所でスラッシュを使用すれば、コードが展開する可能性のある場所でコードが機能することを確信できます。
シャドウマン

7

途中で大きな違いはありませんが、帰りは違います。

確かに、新しいFile(String path)では '/'または '\'を使用できますが、File.getPath()はそのうちの1つしか提供しません。


わずかな補正が...でWindowsは、どちらかの前方に使用することができます/または後方\\ スラッシュ。しかし、他の場所では、フォワードスラッシュを使用する方が適切です。そうし/ないと、問題が発生します。
シャドウマン

6

パーティーに遅れました。私はJDK 1.8とEclipse MARS 1
を搭載したWindows 10を使用しています。

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

作品と

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

機能しません

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

動作しません。最後の2つは同等です。だから... File.separatorを使わないのには十分な理由があります。


6
この行getClass().getClassLoader().getResourceAsStream("path\to\resource");には、表(\t)と復帰(\r)があります。
ステファン

9
それは質問とは異なるシナリオです。クラスローダのgetResourceAsStreamメソッドは、ファイルのパスを取るのではなく、リソース名またはファイル・システム上にあってもなくてもよいとされる文書のみリソース・パスの区切り文字として「/」を受け入れるよう。
daiscog 2016年

@StephanはFile.separatorバックスラッシュなので、そこからの脱出はおかしい。これは、バックスラッシュをエスケープする必要があるエスケープ文字として扱われるハードコードされた文字列でのみです。あなたは、テキストファイル内の文字を保存した、またはにした場合charまたはString、あなたはそれを、それはすでに予想バックスラッシュ文字に変換されていて第二の時間をエスケープする必要はありません。:自分で見るために、これを試してみてくださいString backslash = "\\"; System.out.println("welcome" + backslash + "to" + backslash + "reality");
シャドーマン

2
@Stephanああ、なるほど。あなたは3行目について話していました。あなたは正しいです。その行(ハードコードされた文字列)では、エスケープ文字をエスケープする必要があります。2行目で目が止まり、3行目にも気付かなかった。
シャドウマン

3

シンプルでシンプルな携帯性。


はい、移植性のため、バックスラッシュ使用しないでください。スラッシュ/またはシステム区切り文字を使用してくださいFile.separator。どちらもどこでも機能するようです。一方でFile.separator、どこでも動作することが保証され、簡単なスラッシュは/また、どこでも動作するようです。それがどこかで機能しない場合は、私はそれについて聞きたいです。私はそれがすべてのシステムで機能すると信じています。少なくとも、/動作しない場所はまだ見つけていません(Mac OSX、Windows、* nix、Android、iOS-OS:以前の「:」をセパレーターとして使用していたOSX Macは確認していませんが、OS / 2、NeXT、または他の本当に古いOSのいずれか)。
シャドウマン

1

「プログラマーのためのJava SE8」は、Javaがどちらにも対応すると主張しています。(pp。480、最後の段落)。この例では、次のように主張しています。

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

うまく解析されます。最後の(Unixスタイルの)セパレータに注意してください。

それは粘着性があり、おそらくエラーが発生しやすいですが、それは彼ら(デイテルとデイテル)が主張するものです。

Javaではなく人々の混乱が、この(ミス?)機能を使用しない理由であると思います。


1

紳士が違いの詳細で違いを説明したように。

複数のOSに展開する可能性のあるプログラムでファイルを処理する場合は、Apache Commons io api、クラスの使用をお勧めFilenameUtilsします。


0

ファイルまたはディレクトリのパス名は、ホストシステムの命名規則を使用して指定されます。ただし、Fileクラスは、プラットフォームに依存しない方法でファイル名とディレクトリ名を処理するために使用できるプラットフォーム依存の定数を定義します。

Files.seperatorは、パス名でディレクトリとファイルコンポーネントを区切る文字または文字列を定義します。この区切り文字は、Unix、Windows、Macintoshの場合、それぞれ「/」、「\」、または「:」です。


Macintoshの「:」は古いものです。OSX以降、Macは "/"(スラッシュ)も使用しています。これは、Macが標準のUNIXファイルシステムを使用してUNIXの形式を実行しているためです。
シャドウマン


0

File.separatorを使用すると、Ubuntuはディレクトリではなく、名前に「\」が付いたファイルを生成しました。たぶん私はファイル(およびディレクトリ)を作成する方法に怠惰で、それを回避できたかもしれませんが、名前に「\」が付いているファイルを避けるために毎回「/」を使用してください


0

Linuxセパレーターを使用して、(たとえば、データベースに保存されている)準備ができたパスからファイルを作成しようとしている場合、どうすればよいですか?

多分ちょうどパスを使用してファイルを作成します:

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

ただし、Windowsは別の区切り文字(\)を使用します。それで、代替案はスラッシュセパレータをプラットフォームに依存しないものに変換するのでしょうか?お気に入り:

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

このメソッドはconvertPathToPlatformIndependentおそらく「/」で分割され、File.separatorと結合されます。

まあ、私にとっては、プラットフォームに依存しない言語(これは正しいですか?)にとっては良くありません。Javaはすでに/WindowsまたはLinuxでの使用をサポートしています。しかし、パスを使用していて、毎回この変換を覚えておく必要がある場合、これは悪夢となり、将来のアプリケーションに真の利益はありません(多分、@ Pointyが説明した宇宙で)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.