ファイルパス文字列を結合する従来の方法はありますか?


34

例では:

var assets = "images/"

var sounds = assets+"sounds/"

ファイルパスの後ろにスラッシュを置くのがより一般的ですか?

var assets = "/images"

var sounds = assets+"/sounds"

良い一般的な方法である別の方法はありますか?


Javaには静的な文字列File.separatorとFile.pathSeparatorがあり、関連性があります。このように、すべてのプラットフォームで安全です
-Evorlor

1
@Evorlor使用する必要はほとんどありませんがFile.separatorFilePathAPIは両方/と `\`を受け入れます。
カペックス

2
使用している言語を教えてください。おそらく、対応するタグを追加する価値があります。
クリストファー・クロイツィグ

@ChristopherCreutzig私はJavaを使用しています。ただし、文字列でファイルディレクトリを結合するために一般的に使用される規則があるかどうかを尋ねていました。どうやら一般的に受け入れられているルールがいくつかあり、常識が関係しているようですが、言語によって多少異なります。
虹色

1
UNIXの世界(およびurl)では、パスの中央にある複数のスラッシュは単一のスラッシュと同じように扱われますので、スラッシュの側を間違えても何も悪いことは起こりません。これは、Single Unix Specificationの一部です。この回答を参照してください-unix.stackexchange.com/a/1919/21161-yoniLavi 15
1

回答:


37

ほぼすべての主要なプログラミング言語には、ディレクトリセパレータを処理するライブラリがあります。それらを活用する必要があります。これにより、コードが簡素化され、バグが防止されます。

私の経験では、このような文字列を組み合わせる通常の理由は、それらが異なるソースから来るということです。構成ファイルとは異なる場合があります。時々、それは関数の引数と結合する定数です。いずれの場合でも、それらが異なるソースからのものである場合、結合する両端のセパレーターに関して考えられるいくつかの異なるケースを考慮する必要があります。

  • 両端は、セパレータを持つことができます:"images/""/sounds"
  • 一つだけは、セパレータを持っています"images"し、"/sounds"あるいは"images/""sounds"
  • どちらにもセパレータはありません:"images"および"sounds"

各部分が異なるソースからのものであるという事実は、誰かがそれを考えた場合、従うべき規則について各ソースが独自のアイデアを持っている可能性があることを意味します!コード呼び出すものは何でも、これについて心配する必要はありません。誰かがあなたの慣習に違反するので、あなたのコードはすべてのケースを処理すべきです。これにより、エラーの原因を調査して修正を行うのに無駄な時間がかかります。同僚が構成ファイル内でパスをどのようにフォーマットするかについて不愉快な思いをすることが何度かありました。つまり、コードを探し出して、何を期待しているか(またはコードを修正)する必要がありました。

ほとんどの主要言語には、すでに多くのケースを処理する方法が用意されています。

これらには注意点があります。これらの多くは、2番目の引数の先頭のディレクトリセパレータがルートパスを参照し、これが最初の引数を完全に削除する必要があることを前提としているようです。これがなぜ有用であると考えられるのかわかりません。私にとっては、それは単に問題を引き起こします。2つのパス部分を組み合わせて、最初の部分がドロップされることはありませんでした。特別なケースについてはドキュメントを注意深く読み、必要であれば、特別な処理の代わりにこれらで必要なことを行うラッパーを作成してください。

さらに、異なるオペレーティングシステムをサポートする必要がある場合にも役立ちます。これらのクラスは、ほぼどこでも正しいセパレーターの選択を説明しています。ライブラリには通常、OSの規則に合わせてパスを正規化する方法もあります。

プログラミング言語にすぐに使用できるライブラリがない場合はこれらすべてのケースを処理するメソッドを記述し、それをプロジェクト間で自由に使用する必要があります。

これは、「想定しない」および「役立つツールを使用する」というカテゴリに分類されます。


2
.NETのPath.Combineは壊れていません。区切り文字を入れないでください。2番目の引数がルートパスである場合、定義された結果が得られるように、必ずドキュメントを読んでください。気に入らないかもしれませんが、壊れているという意味ではありません。
エルノ

4
ドキュメントを読んで、あまりにも巧妙にならないようにしてください。私はかつて* nixシステムC:\Documents and Settings\Adminとうまく組み合わせて作成できるライブラリを使用していましたが、これはかわいいトリックですが、現実の世界では、ヒューリスティックによって修正されたよりも多くのバグが発生しました。my folder:document.txt/home/admin/my folder/document.txt
マーク

1
また、Javaの場合Paths.get()、シングルStringPathオブジェクトに変換するだけです。パスを結合するにPath.resolve()は、別のPathまたはを取り込むことができるを使用しますStringPathクラスには他にもさまざまな方法でパスを結合できるメソッドがあります。
キャット

1
悪いことですが、ドキュメントをPathsあまりよく読んでいないようです。
キャット

1
PowerShellで、[System.IO.Path]::Combine("abc", "\def")説明された動作を持つ.NETメソッドの代替は、Join-Path "abc" "\def"を与えるコマンドレット"abc\def"です。
ジェッペスティグニールセン

38

Javaでは、答えは「上記のどちらでもない」でしょう。ベストプラクティスは、java.io.Fileクラスを使用してパス名をアセンブルすることです。例えば

File assets = new File("images");
File sounds = new File(assets, "sounds");

このFileクラスは、プラットフォーム固有のパス名セパレータも処理します。

パス名をスラッシュで開始するかどうかの別の問題があります。しかし、それはベストプラクティスよりも正確さに関係しています。スラッシュで始まるパス名は、そうでないパス名とは異なるものを意味します !!


コア(ECMA)Javascriptライブラリでのパス名処理の明示的なサポートはありませんが、(少なくとも)Node.jsはPathモジュールを介してサポートを提供します。


4
同様のことが、.Net Framework言語およびファイルシステムクラスを提供する他の言語の場合にも当てはまります。
ジェームズスネル

3
ありがとうございました!これは最も有用な回答のように思えました。たとえ言語固有であるとしても、.NETやC ++のような他の言語全般のライブラリは存在するはずです。
虹色

3
実際、ライブラリを使用しないコードはコードレビューで拒否する必要があります。まれに、ライブラリが存在しない場合は、生の文字列を貼り付けるのではなく、自分でライブラリを作成するという答えがあります。
ロボットを取得


Pythonにはがありos.path.joinます。PowerShellは持っていjoin-pathます。この答えに何かを追加します。複数のファイルパスが必要な場合、特定の場所にファイルパスがあると仮定すると、コードが非常に脆弱になることがわかりました。これらのクラスを使用すると、移植性が向上するだけでなく、考えられるすべてのエッジケース(結合される両端のスラッシュ、片側のみのスラッシュ、まったくスラッシュなし)も処理されます。構成ファイルにファイルパスをドロップする場合、この柔軟性は非常に重要です。
jpmc26

21

.NETでは、Path.Combineメソッドを使用する必要があることに注意してください。

var path = System.IO.Path.Combine("assets", "sounds");

これは、フォルダ名を作成するときに使用される正しい文字を「認識」しているためです。

これにより、事前または事後修正の「問題」がなくなります。


4
os.path.joinは基本的にPythonでも同じことを行います
-StarWeaver

:path.combineは区切り文字について心配のビジネスのあなたを取得しないことに注意してくださいstackoverflow.com/questions/53102/...
jmoreno

1
@jmoreno-私の例では、セパレータはありません。リンクした質問には、ハードコードされたセパレータがあり、2番目のパスが絶対パスであるために根本的に間違っている場合。
エルノ

ただし、これには注意してください。.NETについてはわかりませんos.path.join('src', '../../../your_secret_stuff') 、Pythonでは有効です。つまり、これらのメソッドをユーザー入力で盲目的に使用しないでください。
サピ

@sapi-もちろん、ユーザー入力は常にサニタイズする必要がありますが、それはプログラマーの責任であり、APIの責任ではありません。
エルノ

5

パスを作成するときは、末尾のスラッシュがまだない場合は追加する関数をよく使用します。次に、パスを次のように構築できます。

filename := fs( 'assets') + fs( 'images') + fs( 'icons') + 'some.png';

fs()は、必要に応じて末尾にスラッシュを追加します。


5

フォルダーとファイルの違いは1つだけです。フォルダーでは、ファイルではなくスラッシュで終わります。さらに、絶対パスは/、相対パスではない場所から始まります。これを一貫して連結するパスとファイルを一緒に使用しても問題はないはずです。

var absolutepath = "/my/path/";
var relativepath = "css/";
var filename = "test.css";
var relativepathtofilename = "js/test.js";

var a = absolutepath + relativepath + filename; //Output: /my/path/css/test.css
var b = absolutepath + relativepathtofilename;  //Output: /my/path/js/test.js

2番目のパスは最初のパスに対して相対的である必要があるため、2つの絶対パスを連結しても意味がありません。2つの相対パスを連結しても問題はありませんが、プログラムが相対パスの相対位置を知らない場合、未定義の動作を引き起こす可能性があります。


これはおそらく私の最初の質問に最もよく答えたものです。StephenCやErnoが言ったように、言語ライブラリが最初の最善策だとはいえ、ファイルパスをよく理解していると思います。しかし、これは慣習をよりよく説明します。ありがとうございました!
虹色

ファイルシステムのパスまたはURLですか?
MrWhite

1
すべての意図と目的のために、これをuriにも適用できます。絶対URIはプロトコルで始まりますが、それ以外は同じだと思います。
Sumurai8

出力がどのように機能しているかわかりません。私がそれをするとき、私は得る:var a = "/my/path" + "css/" + "test.css"; //Output: "/my/pathcss/test.css"
デイモン

1
@Damon編集しました。absolutepathパスであるため、スラッシュで終了する必要がありました。どういうわけか私はこれを書いたときにそれを見落としていました。
-Sumurai8

4

パスを実装する方法について魔法や「一般的な慣行」はないと思いますが、確かに文字列の連結は進むべき方法ではありません。ケースを処理するための独自のAPIを開発できますが、多少の努力が必要になる場合があります。特に、異なるプラットフォームに注意する必要があります。たとえば、Windowsでは\区切り記号が、Unixベースのシステム/では区切り記号が使用されます。

私はJavascriptライブラリに精通していませんが、これらのケースを処理するためのライブラリがあるはずです。たとえば、Javaでは、Path APIを使用して、プラットフォームに依存しないパス操作を処理できます。


3
Windowsは、実際には/パスファイル名の区切り文字としてサポートしています。これにはコマンドラインでの癖が必要ですが、ファイルI / O APIはスラッシュでうまく動作します。
ルスラン

en.wikipedia.org/wiki/…「WindowsシステムAPIはスラッシュを受け入れます。したがって、上記のUnixの例はすべて動作します。しかし、Windowsの多くのアプリケーションは、他の目的でスラッシュを解釈するか、それを無効な文字として扱います。バックスラッシュを入力します。特にcmd.exeシェル(通常、ターミナルウィンドウで実行されるため、「ターミナル」と呼ばれます)。
Mooingダック

0

私の個人的な好みはこれです:

var assets = "/images"

var sounds = assets+"/sounds"

私は常に絶対パス(/images/...)を使用します。エラーが発生しにくいと感じています。末尾のスラッシュがあり、あなたが終わったとしても、それはまだ解決するvar sounds = assets+"/sounds"ので、使用するのはより馬鹿な証拠assetsです。1つの免責事項は、リクエストハンドラに依存するということです。Apacheはそれをうまく処理しているようです(少なくとも特定のバージョン/構成、http://www.amazon.com//gp//site-directory//ref=nav_sadを参照)。他の方法では、最終的にで終わることになりますが、それほど簡単な証拠ではありません。他のアプローチのオプションではありません。/images//sounds/images/sounds/imagessounds


11
私が知っているすべてのコンテキストでは、スラッシュ(/)で始まるパスは絶対パスであり、相対パスではありません。または、最初のパスセクション以外のパスセクションに対してのみそれを意味しましたか?
バートヴァンインゲンシェ

@BartvanIngenSchenau私はあなたに完全に同意し、何年も彼らに電話をかけてきましたが、フロントエンド開発者が書いた記事を読むたびに、彼らはそれらを相対パスと呼んでいます。私は仮定をしたくなかったので、2つの悪のうち小さい方を選んだと思います...?私の側に何人かの人々がいることがわかったので、答えを更新します:)
rpaskett

2
Web開発者にとって/somewhereは、ホストが含まれていないため、相対パスです。したがって、ブラウザーは現在のページのホストに基づいて検索します。Webの世界でhttp://here/somewhereは、絶対URIであり、それ/somewhereelseに対して相対的です。ファイルシステムの世界で/somewhereは、rootから来る絶対的なもの/であり、「somewhereelse」は現在の作業ディレクトリに相対的です。
ロブ

3
@ RobY、rpaskett:RFC3986(URIを定義するRFC)に準拠http://here/somewhereし、絶対パスを持つURIであり/somewhere、絶対パスをsomewhere/else持つ相対参照であり、相対パスを持つ相対参照です。どうやら、これらの円では、相対参照を参照するために「相対パス」が使用されています。
バートヴァンインゲンシェナウ

1
@BartvanIngenSchenau:Windowsでは、スラッシュで始まるパスは相対パスであり、CWDに相対的です。 en.wikipedia.org/wiki/...
ダックMooing

0

Smalltalkでは、次のように動作するようにStringで/メソッドを定義するのは簡単です。

'assets' / 'sounds' => 'assets/sounds'.
'assets/' / 'sounds' => 'assets/sounds'.
'assets' / '/sounds' => 'assets/sounds'.
'assets/' / '/sounds' => 'assets/sounds'.

メソッドの簡単な実装は次のとおりです(改善することができます)。

/ aString
    | slash first second |
    slash := Directory separator.
    first := self.
    (first endsWith: slash) ifTrue: [first := first allButLast].
    second := aString.
    (second beginsWith: slash) ifTrue: [second := second allButFirst].
    ^first , slash , second

:あなたはまたのような境界例に、より良い注意を払うようにしたいかもしれません'' / '''x/' / ''適切な行動を決定するために、など。

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