Apakah ada cara konvensional untuk menggabungkan string jalur file?

34

Dalam sebuah contoh:

var assets = "images/"

var sounds = assets+"sounds/"

Apakah lebih konvensional untuk meletakkan garis miring di belakang jalur file?

var assets = "/images"

var sounds = assets+"/sounds"

Apakah ada metode lain yang merupakan praktik umum yang baik?

iiridescent
sumber
Java memiliki Strings File.separator statis dan File.pathSeparator yang terdengar relevan. Dengan cara ini Anda aman di semua platform
Evorlor
1
@Evorlor Anda jarang perlu menggunakannya File.separator, Filedan PathAPI menerima keduanya /dan `\`.
kapex
2
Bisakah Anda menunjukkan bahasa yang Anda gunakan? Mungkin perlu menambahkan tag yang sesuai.
Christopher Creutzig
@ChristopherCreutzig Saya menggunakan Java - walaupun saya bertanya apakah ada konvensi yang biasa digunakan untuk menggabungkan direktori file dalam string. Rupanya ada beberapa aturan yang diterima secara umum dan ada beberapa akal sehat yang terlibat, tetapi sedikit berbeda dari satu bahasa ke bahasa lainnya.
iiridescent
1
Untuk apa nilainya, di dunia unix (dan dalam url), beberapa garis miring ke depan di tengah jalan diperlakukan secara identik dengan jalur tunggal, jadi tidak ada hal buruk yang akan terjadi jika Anda melakukan kesalahan di sisi garis miring yang lebih banyak. Ini bagian dari Spesifikasi Unix Tunggal; lihat jawaban ini - unix.stackexchange.com/a/1919/21161
yoniLavi

Jawaban:

37

Hampir setiap bahasa pemrograman utama memiliki perpustakaan untuk menangani pemisah direktori untuk Anda. Anda harus memanfaatkannya. Ini akan menyederhanakan kode Anda dan mencegah bug .

Dalam pengalaman saya, alasan umum untuk menggabungkan string seperti ini adalah bahwa mereka berasal dari sumber yang berbeda. Terkadang potongan berbeda dari file konfigurasi. Terkadang ini adalah gabungan konstan dengan argumen fungsi. Dalam setiap dan semua kasus, ketika mereka berasal dari sumber yang berbeda, Anda harus mempertimbangkan beberapa kasus yang mungkin berbeda mengenai pemisah di ujung yang akan digabungkan:

  • Kedua ujungnya bisa memiliki pemisah: "images/"dan"/sounds"
  • Hanya satu yang memiliki pemisah: "images"dan "/sounds"atau "images/"dan"sounds"
  • Tidak ada yang memiliki pemisah: "images"dan"sounds"

Fakta bahwa setiap bagian berasal dari sumber yang berbeda berarti masing-masing sumber mungkin memiliki ide sendiri tentang konvensi apa yang harus diikuti, jika seseorang memikirkannya sama sekali! Apa pun panggilan kode Anda tidak perlu khawatir tentang ini . Kode Anda harus menangani semua kasus karena seseorang akan melanggar konvensi Anda . Ini akan menghasilkan waktu yang terbuang untuk menyelidiki penyebab kesalahan dan membuat perbaikan. Saya memiliki beberapa kejadian tidak menyenangkan di mana seorang rekan kerja membuat asumsi tentang bagaimana path harus diformat dalam file konfigurasi, artinya saya harus mencari kode dan mencari tahu apa yang mereka harapkan (atau memperbaiki kode).

Sebagian besar bahasa utama menyediakan metode untuk melakukan ini untuk Anda yang sudah menangani banyak kasus:

Ada peringatan dengan ini. Sejumlah ini tampaknya mengasumsikan bahwa pemisah direktori terkemuka dalam argumen kedua merujuk ke path root dan bahwa ini berarti argumen pertama harus dibuang seluruhnya. Saya tidak tahu mengapa ini dianggap berguna; bagi saya, itu hanya menyebabkan masalah. Saya tidak pernah ingin menggabungkan dua bagian jalur dan berakhir dengan bagian pertama dijatuhkan. Baca dokumentasi dengan seksama untuk kasus-kasus khusus, dan jika perlu, tulis pembungkus yang melakukan apa yang Anda inginkan dengan ini daripada penanganan khusus mereka.

Ini juga membantu jika Anda memiliki kebutuhan untuk mendukung sistem operasi yang berbeda. Kelas-kelas ini hampir di mana-mana bertanggung jawab untuk memilih pemisah yang benar. Perpustakaan biasanya memiliki cara normalisasi jalur agar sesuai dengan konvensi OS, juga.

Jika bahasa pemrograman Anda tidak memiliki perpustakaan yang tersedia, Anda harus menulis metode yang menangani semua kasus ini dan menggunakannya secara bebas dan lintas proyek.

Ini termasuk dalam kategori "jangan membuat asumsi" dan "gunakan alat yang membantu Anda."

jpmc26
sumber
2
.NET's Path.Combine tidak rusak. Hanya saja, jangan memberi makan pemisah. pastikan Anda membaca dokumentasi, jika argumen kedua adalah path root, ia memiliki hasil yang ditentukan. Anda mungkin tidak menyukainya tetapi itu tidak berarti itu rusak.
Erno
4
Pastikan Anda membaca dokumentasi untuk memastikan tidak mencoba menjadi terlalu pintar. Saya pernah menggunakan perpustakaan yang berhasil digabungkan C:\Documents and Settings\Admindengan my folder:document.txtsistem * nix untuk menghasilkan /home/admin/my folder/document.txt- trik yang lucu, tetapi di dunia nyata, heuristik yang terlibat memperkenalkan lebih banyak bug daripada yang mereka perbaiki.
Mark
1
Juga, untuk Java, Paths.get()hanya mengubah satu Stringmenjadi Pathobjek. Untuk bergabung dengan jalur, Anda akan menggunakan Path.resolve(), yang dapat mengambil yang lain Pathatau String. Ada metode lain di Pathkelas yang selanjutnya memungkinkan untuk bergabung jalur dengan berbagai cara.
Kat
1
Buruk saya, sepertinya saya tidak membaca dokumen Pathsdengan baik.
Kat
1
Pada PowerShell, sebuah alternatif untuk metode .NET [System.IO.Path]::Combine("abc", "\def")yang memiliki perilaku yang dijelaskan, adalah cmdlet Join-Path "abc" "\def"yang memberi "abc\def".
Jeppe Stig Nielsen
38

Di Jawa, jawabannya adalah "tak satu pun dari yang di atas". Praktik terbaik adalah merakit nama path menggunakan java.io.Filekelas; misalnya

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

The Filekelas juga menangani pemisah path platform tertentu.

Ada masalah terpisah apakah pathname Anda harus dimulai dengan garis miring atau tidak. Tapi itu lebih berkaitan dengan kebenaran daripada praktik terbaik. Pathname yang dimulai dengan garis miring berarti sesuatu yang berbeda dengan pathname yang tidak !!


Tidak ada dukungan eksplisit untuk penanganan pathname di perpustakaan Javascript inti (ECMA), tetapi (setidaknya) Node.js memberikan dukungan melalui modul Path.

Stephen C
sumber
4
Hal serupa juga berlaku untuk bahasa .Net Framework dan yang lainnya yang menawarkan kelas sistem file.
James Snell
3
Terima kasih! Ini sepertinya jawaban yang paling membantu, meskipun spesifik bahasa, pustaka harus ada untuk bahasa lain secara umum, seperti .NET dan C ++;
iiridescent
3
Sungguh, kode apa pun yang tidak menggunakan perpustakaan harus ditolak dalam ulasan kode. Dalam kesempatan langka tidak ada perpustakaan, jawabannya adalah menulis sendiri daripada menempelkan string mentah.
Gort the Robot
C ++ memiliki Boost :: Filesystem , dan C # memiliki System.IO.Path
Mooing Duck
Python memiliki os.path.join. PowerShell memiliki join-path. Saya akan menambahkan sesuatu untuk jawaban ini. Saya telah menemukan bahwa jika Anda memerlukan path file dalam beberapa bagian, itu membuat kode Anda sangat rapuh jika Anda membuat asumsi tentang salah satu dari mereka yang memiliki path file di tempat-tempat tertentu. Menggunakan kelas-kelas ini tidak hanya membantu dengan portabilitas, tetapi juga menangani semua kasus tepi yang mungkin (garis miring pada kedua ujungnya untuk digabungkan, garis miring pada satu sisi, tidak ada garis miring di antara semua). Fleksibilitas ini sangat berharga ketika Anda menjatuhkan jalur file dalam file konfigurasi.
jpmc26
21

Perhatikan bahwa dalam .NET Anda harus menggunakan metode Path.Combine.

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

Alasannya adalah karena 'mengetahui' karakter yang benar untuk digunakan saat membuat nama folder.

Ini menghilangkan 'masalah' sebelum atau sesudah memperbaiki.

Erno
sumber
4
os.path.join pada dasarnya juga melakukan hal yang sama untuk python
StarWeaver
Perhatikan bahwa path.combine tidak membuat Anda keluar dari bisnis untuk mengkhawatirkan
pemisah
1
@ jmoreno - Dalam contoh saya tidak ada pemisah. Pertanyaan yang Anda tautkan memiliki pemisah berkode keras dan jika secara fundamental salah karena jalur kedua adalah jalur absolut.
Erno
Berhati-hatilah dengan ini. Saya tidak yakin tentang NET, tapi os.path.join('src', '../../../your_secret_stuff') ini berlaku di Python; dengan kata lain, jangan gunakan metode ini secara membabi buta pada input pengguna.
sapi
@ Sapi - Tentu saja, input pengguna harus selalu disanitasi tetapi itu adalah tanggung jawab programmer, bukan dari API.
Erno
5

Saat membangun jalur, saya sering menggunakan fungsi yang menambahkan garis miring jika belum ada. Kemudian jalur dapat dibangun seperti:

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

di mana fs () menambahkan garis miring jika diperlukan.

GrandmasterB
sumber
5

Folder dan file berbeda hanya dalam satu aspek: folder berakhir dengan garis miring di mana file tidak. Lebih jauh lagi, jalur absolut dimulai dengan di /mana jalur relatif tidak. Jika Anda menggunakan jalur dan file yang digabungkan secara konsisten ini bersama-sama seharusnya tidak menjadi masalah.

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

Menggabungkan dua jalur absolut secara bersamaan tidak masuk akal, karena jalur kedua harus relatif terhadap jalur pertama. Menggabungkan dua jalur relatif bersama bukanlah masalah, tetapi mungkin mengarah pada perilaku yang tidak terdefinisi jika program tidak tahu di mana jalur relatif relatif terhadap.

Sumurai8
sumber
Ini mungkin menjawab pertanyaan asli saya yang terbaik, saya pikir saya memahami jalur file lebih baik, meskipun seperti kata Stephen C dan Erno, perpustakaan bahasa adalah taruhan pertama yang terbaik. Ini menjelaskan konvensi yang lebih baik. Terima kasih!
iiridescent
Jalur atau URL sistem file?
MrWhite
1
Untuk semua maksud dan tujuan, Anda dapat menerapkan ini pada uri juga. Sebuah uri absolut akan dimulai dengan sebuah protokol, tetapi selain itu saya pikir itu sama saja.
Sumurai8
Tidak yakin bagaimana hasil kerja Anda. Ketika saya melakukannya saya mendapatkan:var a = "/my/path" + "css/" + "test.css"; //Output: "/my/pathcss/test.css"
Damon
1
@Damon Saya mengedit. absolutepathseharusnya diakhiri dengan garis miring, karena itu adalah jalan. Entah bagaimana saya mengabaikan hal itu ketika saya menulis ini.
Sumurai8
4

Saya pikir tidak ada sihir atau "praktik umum" tentang cara menerapkan jalur, tetapi tentu saja rangkaian string bukanlah cara yang harus ditempuh. Anda dapat mengembangkan API Anda sendiri untuk menangani kasus-kasus, tetapi itu mungkin memerlukan beberapa upaya. Khususnya, Anda harus berhati-hati tentang platform yang berbeda. Sebagai contoh, di Windows \adalah pemisah sedangkan di sistem berbasis Unix /adalah pemisah.

Saya tidak terbiasa dengan perpustakaan Javascript, tapi saya yakin harus ada perpustakaan untuk menangani kasus ini. Di Java, misalnya, Anda dapat menggunakan API Jalur untuk menangani operasi jalur mandiri platform.

Wickoo
sumber
3
Windows sebenarnya mendukung /sebagai path nama file pembatas. Ini memang perlu quirks di baris perintah, tetapi file I / O API berfungsi dengan baik dengan forward slash.
Ruslan
en.wikipedia.org/wiki/… "API sistem Windows menerima slash, dan dengan demikian semua contoh Unix di atas akan berfungsi. Tetapi banyak aplikasi pada Windows menafsirkan slash untuk tujuan lain atau memperlakukannya sebagai karakter yang tidak valid, dan karenanya mengharuskan Anda untuk memasukkan backslash - terutama shell cmd.exe (sering disebut "terminal" karena biasanya berjalan di jendela terminal). "
Mooing Duck
0

Preferensi pribadi saya adalah ini:

var assets = "/images"

var sounds = assets+"/sounds"

Saya selalu menggunakan jalur absolut ( /images/...), rasanya kurang rentan terhadap kesalahan, bagi saya. Ini juga merupakan bukti yang lebih bodoh untuk digunakan var sounds = assets+"/sounds"karena meskipun assetsmemiliki garis miring dan Anda berakhir /images//sounds, itu masih akan menyelesaikan /images/sounds. Satu penafian adalah bahwa itu tergantung pada penangan permintaan Anda. Apache tampaknya menanganinya dengan baik (setidaknya versi / konfigurasi tertentu, lihat http://www.amazon.com//gp//site-directory//ref=nav_sad ). Dengan cara lain Anda akan berakhir dengan /imagessounds, bukan jadi bukti bodoh :) Ada juga pilihan untuk memeriksa tebasan ganda dan membersihkannya. Bukan pilihan dengan pendekatan lain.

rpaskett
sumber
11
Dalam semua konteks yang saya ketahui, jalur yang dimulai dengan garis miring ( /) adalah jalur absolut , bukan jalur relatif. Atau apakah maksud Anda hanya untuk bagian path selain yang pertama?
Bart van Ingen Schenau
@ BartvanIngenSchenau Saya sangat setuju dengan Anda dan saya telah memanggil mereka selama bertahun-tahun, tetapi setiap kali saya membaca artikel yang ditulis oleh pengembang front-end, mereka menyebutnya sebagai jalur relatif. Saya tidak ingin membuat asumsi jadi saya kira saya memilih yang lebih rendah dari dua kejahatan ...? Sekarang saya tahu ada beberapa orang di pihak saya, saya akan memperbarui jawaban saya :)
rpaskett
2
Untuk pengembang web, /somewhereadalah jalur relatif karena tidak menyertakan host, sehingga browser akan mencarinya berdasarkan host halaman saat ini ... Di dunia web, http://here/somewhereadalah URI absolut, dan /somewhereelserelatif terhadap itu. Dalam dunia sistem file, /somewhereadalah mutlak, berasal dari root /, dan "entah bagaimana" relatif terhadap direktori kerja saat ini.
Rob
3
@RobY, rpaskett: Going by RFC3986 (RFC yang mendefinisikan URI), http://here/somewhereadalah URI dengan jalur absolut, /somewhereadalah referensi relatif dengan jalur absolut dan somewhere/elsemerupakan referensi relatif dengan jalur relatif. Rupanya, di lingkaran itu "jalur relatif" digunakan untuk merujuk ke referensi relatif.
Bart van Ingen Schenau
1
@ BartvanIngenSchenau: di windows, jalur yang dimulai dengan garis miring adalah jalur relatif, dan relatif terhadap CWD. en.wikipedia.org/wiki/…
Mooing Duck
0

Dalam Smalltalk sangat mudah untuk mendefinisikan metode / di String sehingga berfungsi seperti ini:

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

Berikut ini adalah implementasi sederhana dari metode ini (Anda dapat membuatnya lebih baik):

/ 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

Catatan : Anda mungkin juga ingin memperhatikan lebih baik untuk kasus-kasus perbatasan seperti '' / '', 'x/' / '', dll, dalam rangka untuk menentukan perilaku yang tepat.

Leandro Caniglia
sumber