มีวิธีธรรมดาในการรวมสตริงพา ธ ไฟล์หรือไม่


34

ในตัวอย่าง:

var assets = "images/"

var sounds = assets+"sounds/"

มันเป็นเรื่องธรรมดามากขึ้นที่จะใส่เครื่องหมายทับที่ด้านหลังของพา ธ ไฟล์หรือไม่?

var assets = "/images"

var sounds = assets+"/sounds"

มีวิธีอื่นที่เป็นการปฏิบัติทั่วไปที่ดีหรือไม่?


Java มี Strings File.separator และ File.pathSeparator แบบคงที่ซึ่งฟังดูเกี่ยวข้อง วิธีนี้คุณจะปลอดภัยในทุกแพลตฟอร์ม
Evorlor

1
@Evorlor คุณแทบไม่จำเป็นต้องใช้File.separatorแม้ว่า, FileและPathAPI ยอมรับทั้ง/และ ``
kapex

2
คุณช่วยระบุภาษาที่คุณใช้ด้วยได้ไหม มันน่าจะเป็นการเพิ่มแท็กที่เกี่ยวข้อง
Christopher Creutzig

@ChristopherCreutzig ฉันใช้ Java - แม้ว่าฉันจะถามว่ามีการประชุมที่ใช้กันทั่วไปสำหรับการรวมไดเรกทอรีไฟล์ในสตริง เห็นได้ชัดว่ามีกฎระเบียบที่ยอมรับกันทั่วไปไม่กี่ข้อและมีสามัญสำนึกบางอย่างที่เกี่ยวข้อง แต่มันแตกต่างกันเล็กน้อยจากภาษาเป็นภาษา
iiridescent

1
สำหรับสิ่งที่มีค่าในโลกยูนิกซ์ (และใน URL) การฟอร์เวิร์ดสแลชหลายอันที่อยู่ตรงกลางของพา ธ จะได้รับการปฏิบัติเหมือนกันกับซิงเกิ้ลเดียวดังนั้นจะไม่มีอะไรเลวร้ายเกิดขึ้น เป็นส่วนหนึ่งของสเปค Unix เดี่ยว; ดูคำตอบนี้ - unix.stackexchange.com/a/1919/21161
yoniLavi

คำตอบ:


37

เกือบทุกภาษาการเขียนโปรแกรมที่สำคัญมีห้องสมุดเพื่อจัดการตัวคั่นไดเรกทอรีสำหรับคุณ คุณควรใช้ประโยชน์จากพวกเขา ซึ่งจะทำให้รหัสของคุณและป้องกันไม่ให้เกิดข้อผิดพลาด

จากประสบการณ์ของฉันเหตุผลที่ปกติสำหรับการรวมสตริงเช่นนี้คือพวกเขามาจากแหล่งที่แตกต่างกัน บางครั้งมันแตกต่างจากไฟล์กำหนดค่า บางครั้งมันคงเป็นการรวมกับอาร์กิวเมนต์ของฟังก์ชัน ในกรณีใด ๆ และทั้งหมดเมื่อพวกเขามาจากแหล่งที่แตกต่างกันคุณต้องพิจารณาหลายกรณีที่เป็นไปได้ที่แตกต่างกันเกี่ยวกับตัวคั่นที่ปลายรวมกัน:

  • ปลายทั้งสองอาจมีตัวคั่น: "images/"และ"/sounds"
  • มีเพียงคนเดียวเท่านั้นที่มีตัวคั่น: "images"และ"/sounds"หรือ"images/"และ"sounds"
  • ไม่มีตัวคั่น: "images"และ"sounds"

ความจริงแต่ละส่วนมาจากแหล่งข้อมูลที่แตกต่างกันหมายความว่าแต่ละแหล่งข้อมูลอาจมีแนวคิดของตนเองเกี่ยวกับการประชุมที่จะต้องปฏิบัติตามหากใครบางคนให้ความคิดใด ๆ กับมัน! ไม่ว่าจะเรียกรหัสของคุณไม่ควรจะต้องกังวลเกี่ยวกับเรื่องนี้ รหัสของคุณควรจะจัดการกับทุกกรณีเพราะใครบางคนจะถือเป็นการละเมิดการประชุมของคุณ ซึ่งจะส่งผลให้เสียเวลาตรวจสอบสาเหตุของข้อผิดพลาดและทำการแก้ไข ฉันมีโอกาสที่ไม่พึงประสงค์หลายครั้งที่ผู้ร่วมงานทำข้อสันนิษฐานเกี่ยวกับวิธีการจัดรูปแบบเส้นทางในไฟล์การกำหนดค่าซึ่งหมายความว่าฉันต้องไปตามรหัสและค้นหาสิ่งที่พวกเขาคาดหวัง (หรือแก้ไขรหัส)

ภาษาหลักส่วนใหญ่มีวิธีการทำเช่นนี้เพื่อคุณซึ่งจัดการหลายกรณี:

มีข้อแม้กับสิ่งเหล่านี้ ดูเหมือนว่าจำนวนของสิ่งเหล่านี้จะถือว่าสมมติว่าตัวคั่นไดเรกทอรีชั้นนำในอาร์กิวเมนต์ที่สองอ้างถึงรูทพา ธ และนั่นหมายความว่าอาร์กิวเมนต์แรกควรถูกดร็อปทั้งหมด ฉันไม่รู้ว่าทำไมสิ่งนี้จึงมีประโยชน์ สำหรับฉันมันแค่ทำให้เกิดปัญหา ฉันไม่เคยต้องการรวมสองส่วนของเส้นทางและท้ายด้วยส่วนแรกที่ถูกทิ้ง อ่านเอกสารอย่างละเอียดเพื่อหากรณีพิเศษและถ้าจำเป็นให้เขียนกระดาษห่อที่ทำสิ่งที่คุณต้องการด้วยสิ่งเหล่านี้แทนการจัดการแบบพิเศษ

นอกจากนี้ยังช่วยในกรณีที่คุณต้องการสนับสนุนระบบปฏิบัติการที่แตกต่างกัน คลาสเหล่านี้แทบทุกบัญชีใช้สำหรับเลือกตัวคั่นที่ถูกต้อง ไลบรารีมักจะมีวิธีในการทำให้เส้นทางเป็นปกติเพื่อให้สอดคล้องกับข้อกำหนดของระบบปฏิบัติการเช่นกัน

ในกรณีที่ภาษาการเขียนโปรแกรมของคุณไม่มีไลบรารี่ที่พร้อมใช้งานคุณควรเขียนวิธีการที่จัดการกรณีเหล่านี้ทั้งหมดและใช้อย่างอิสระและข้ามโปรเจ็กต์

สิ่งนี้อยู่ในหมวดหมู่ของ "อย่าตั้งสมมติฐาน" และ "ใช้เครื่องมือที่ช่วยคุณได้"


2
. Path ของ. NET ไม่แตกหัก เพียงไม่ป้อนแยกมัน ตรวจสอบให้แน่ใจว่าคุณอ่านเอกสารหากอาร์กิวเมนต์ที่สองเป็นรูทพา ธ จะมีผลลัพธ์ที่กำหนดไว้ คุณอาจไม่ชอบ แต่นั่นไม่ได้หมายความว่ามันจะพัง
Erno

4
ตรวจสอบให้แน่ใจว่าคุณอ่านเอกสารเพื่อให้แน่ใจว่าไม่ได้พยายามฉลาดเกินไป ฉันเคยใช้ห้องสมุดที่ประสบความสำเร็จในการรวมC:\Documents and Settings\Adminกับmy folder:document.txtระบบ * nix เพื่อผลิต/home/admin/my folder/document.txt- เคล็ดลับที่น่ารัก แต่ในโลกแห่งความจริงฮิวริสติกที่เกี่ยวข้องได้แนะนำข้อบกพร่องมากกว่าที่พวกเขาแก้ไข
Mark

1
นอกจากนี้สำหรับ Java Paths.get()เพียงแปลงหนึ่งStringเป็นPathวัตถุ ในการเข้าร่วมเส้นทางที่คุณต้องการใช้Path.resolve()ซึ่งอาจใช้เวลาอีกหรือPath Stringมีวิธีการอื่นในPathชั้นเรียนที่อนุญาตให้เพิ่มเติมสำหรับการเข้าร่วมเส้นทางในวิธีต่าง ๆ
Kat

1
ฉันไม่ดีดูเหมือนว่าฉันไม่ได้อ่านเอกสารเป็นPathsอย่างดี
Kat

1
บน PowerShell ให้ทางเลือกที่จะใช้วิธีการสุทธิ[System.IO.Path]::Combine("abc", "\def")ซึ่งมีอธิบายพฤติกรรมที่เป็น cmdlet ซึ่งจะช่วยให้Join-Path "abc" "\def" "abc\def"
Jeppe Stig Nielsen

38

ใน Java คำตอบคือ "ไม่ตรงกับข้างต้น" วิธีปฏิบัติที่ดีที่สุดคือการรวบรวมชื่อพา ธ โดยใช้java.io.Fileคลาส เช่น

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

Fileชั้นยังดูแลตัวคั่นชื่อพา ธ เฉพาะแพลตฟอร์ม

มีปัญหาแยกกันว่าชื่อพา ธ ของคุณควรเริ่มต้นด้วยเครื่องหมายทับหรือไม่ แต่นั่นเป็นการกระทำที่ถูกต้องมากกว่าการปฏิบัติที่ดีที่สุด ชื่อพา ธ ที่ขึ้นต้นด้วยเครื่องหมายสแลชหมายถึงสิ่งที่แตกต่างจากชื่อพา ธ ที่ไม่ได้ !!


ไม่มีการสนับสนุนที่ชัดเจนสำหรับการจัดการชื่อพา ธ ในไลบรารี Javascript core (ECMA) แต่ (อย่างน้อย) Node.js ให้การสนับสนุนผ่านโมดูล Path


4
สิ่งที่คล้ายกันนั้นเป็นกรณีสำหรับภาษา. Net Framework และอื่น ๆ ที่มีคลาสระบบไฟล์
James Snell

3
ขอขอบคุณ! ดูเหมือนว่าคำตอบที่มีประโยชน์ที่สุดแม้ว่าจะมีเฉพาะภาษา แต่ไลบรารีควรมีอยู่สำหรับภาษาอื่นโดยทั่วไปเช่น. NET และ C ++;
iiridescent

3
จริงๆรหัสใด ๆ ที่ไม่ได้ใช้ห้องสมุดควรถูกปฏิเสธในการตรวจสอบรหัส ในโอกาสที่หายากไม่มีห้องสมุดคำตอบคือการเขียนด้วยตัวคุณเองแทนที่จะวางสายอักขระดิบ
Gort the Robot


os.path.joinงูหลามมี PowerShell join-pathมี ฉันจะเพิ่มสิ่งที่คำตอบนี้ ฉันพบว่าหากคุณต้องการพา ธ ไฟล์ในหลาย ๆ ชิ้นมันจะทำให้โค้ดของคุณบอบบางมากหากคุณตั้งสมมติฐานว่าพวกเขามีพา ธ ไฟล์ในบางที่ การใช้คลาสเหล่านี้ไม่เพียง แต่ช่วยในการพกพา แต่ยังจัดการกับเคสขอบที่เป็นไปได้ทั้งหมด (สแลชที่ปลายทั้งสองด้านเพื่อเข้าร่วม, สแลชที่ด้านเดียวเท่านั้น, ไม่มีสแลชระหว่างเลย) ความยืดหยุ่นนี้เป็นสิ่งที่ประเมินค่าไม่ได้เมื่อคุณปล่อยเส้นทางไฟล์ในไฟล์กำหนดค่า
jpmc26

21

โปรดทราบว่าใน. NET คุณควรใช้วิธี Path.Combine

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

เหตุผลนี้คือ 'รู้' ถึงตัวอักษรที่ถูกต้องที่จะใช้เมื่อสร้างชื่อโฟลเดอร์

สิ่งนี้จะนำ 'ปัญหา' ของการแก้ไขก่อนหรือหลังการโพสต์


4
os.path.join ทำสิ่งเดียวกันกับงูเหลือมเช่นกัน
StarWeaver

โปรดทราบว่า path.combine ไม่ได้ช่วยให้คุณต้องกังวลเกี่ยวกับ seperator: stackoverflow.com/questions/53102/…
jmoreno

1
@jmoreno - ในตัวอย่างของฉันไม่มีตัวคั่น คำถามที่คุณเชื่อมโยงกับมีตัวคั่นที่กำหนดรหัสยากและหากผิดขั้นพื้นฐานเพราะเส้นทางที่สองเป็นเส้นทางที่แน่นอน
Erno

ระวังด้วยนะ ฉันไม่แน่ใจเกี่ยวกับ .NET แต่os.path.join('src', '../../../your_secret_stuff') เป็นที่ถูกต้องในหลาม; กล่าวอีกนัยหนึ่งอย่าใช้วิธีการเหล่านี้ในการป้อนข้อมูลผู้ใช้
sapi

@sapi - แน่นอนว่าการป้อนข้อมูลผู้ใช้ควรถูกทำให้สะอาดอยู่เสมอ แต่นั่นเป็นความรับผิดชอบของโปรแกรมเมอร์ไม่ใช่ของ API
Erno

5

เมื่อสร้างเส้นทางฉันมักจะใช้ฟังก์ชั่นที่เพิ่มเครื่องหมายทับหากไม่ได้อยู่ที่นั่น จากนั้นสามารถสร้างเส้นทางได้เช่น:

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

โดยที่ fs () เพิ่มเครื่องหมายสแลชต่อท้ายหากต้องการ


5

โฟลเดอร์และไฟล์ต่างกันเพียงด้านเดียว: โฟลเดอร์ลงท้ายด้วยเครื่องหมายสแลชที่ไฟล์ไม่ นอกจากนี้พา ธ สัมบูรณ์เริ่มต้นด้วย/เส้นทางที่สัมพัทธ์ไม่ หากคุณใช้พา ธ และไฟล์ที่ต่อเนื่องกันนี้อย่างสม่ำเสมอจะไม่มีปัญหา

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

การต่อสองเส้นทางสัมบูรณ์เข้าด้วยกันไม่สมเหตุสมผลเนื่องจากเส้นทางที่สองควรสัมพันธ์กับเส้นทางแรก การเชื่อมสองเส้นทางสัมพัทธ์เข้าด้วยกันนั้นไม่มีปัญหา แต่อาจนำไปสู่พฤติกรรมที่ไม่ได้กำหนดหากโปรแกรมไม่ทราบว่าเส้นทางสัมพัทธ์สัมพันธ์กันอย่างไร


สิ่งนี้อาจตอบคำถามเดิมของฉันได้ดีที่สุดฉันคิดว่าฉันเข้าใจเส้นทางไฟล์ดีกว่าแม้ว่า Stephen C และ Erno กล่าวว่าห้องสมุดภาษาเป็นทางออกที่ดีที่สุด สิ่งนี้อธิบายการประชุมได้ดีกว่า ขอขอบคุณ!
iiridescent

เส้นทางของระบบไฟล์หรือ URL?
MrWhite

1
สำหรับความตั้งใจและวัตถุประสงค์ทั้งหมดคุณสามารถใช้สิ่งนี้กับ uri's เช่นกัน uri แบบสัมบูรณ์จะเริ่มต้นด้วยโปรโตคอล แต่นอกเหนือจากนั้นจะเป็นเช่นเดียวกันฉันคิดว่า
Sumurai8

ไม่แน่ใจว่าเอาต์พุตของคุณทำงานอย่างไร เมื่อฉันทำฉันได้รับ:var a = "/my/path" + "css/" + "test.css"; //Output: "/my/pathcss/test.css"
Damon

1
@Damon ฉันทำการแก้ไข absolutepathควรจะจบลงด้วยการทับเพราะมันเป็นเส้นทาง อย่างใดฉันก็มองข้ามว่าเมื่อฉันเขียนนี้
Sumurai8

4

ฉันคิดว่าไม่มีเวทย์มนตร์หรือ "วิธีปฏิบัติทั่วไป" ในการใช้เส้นทาง แต่แน่นอนว่าการต่อสตริงนั้นไม่ใช่วิธีที่จะไป คุณสามารถพัฒนา API ของคุณเองเพื่อจัดการกับกรณีและปัญหา แต่อาจต้องใช้ความพยายามบ้าง โดยเฉพาะอย่างยิ่งคุณควรระมัดระวังเกี่ยวกับแพลตฟอร์มที่แตกต่างกัน ตัวอย่างเช่นใน Windows \เป็นตัวคั่นขณะที่อยู่ในระบบที่ใช้ Unix /คือตัวแยก

ฉันไม่คุ้นเคยกับห้องสมุด Javascript แต่ฉันแน่ใจว่าควรมีห้องสมุดสำหรับจัดการกรณีเหล่านี้ ตัวอย่างเช่นใน Java คุณสามารถใช้Path API เพื่อจัดการกับการดำเนินงานของพา ธ ที่ไม่ขึ้นกับแพลตฟอร์ม


3
Windows รองรับการใช้งานจริง/เป็นตัวคั่นชื่อไฟล์พา ธ สิ่งนี้ต้องการความแปลกในบรรทัดคำสั่ง แต่ไฟล์ I / O APIs ทำงานได้ดีกับฟอร์เวิร์ดสแลช
Ruslan

en.wikipedia.org/wiki/… "API ระบบ Windows ยอมรับการทับดังนั้นตัวอย่าง Unix ข้างต้นทั้งหมดควรใช้งานได้ แต่แอปพลิเคชั่นจำนวนมากบน Windows ตีความเครื่องหมายทับเพื่อจุดประสงค์อื่นหรือใช้เป็นอักขระที่ไม่ถูกต้อง เพื่อเข้าสู่แบ็กสแลชโดยเฉพาะเชลล์ cmd.exe (มักเรียกว่า "เทอร์มินัล" ซึ่งโดยทั่วไปแล้วจะทำงานในหน้าต่างเทอร์มินัล)
Mooing Duck

0

ความชอบส่วนตัวของฉันคือ:

var assets = "/images"

var sounds = assets+"/sounds"

ฉันมักจะใช้เส้นทางที่แน่นอน (/images/... ) มันทำให้ฉันรู้สึกผิดพลาดน้อยลง นอกจากนี้ยังเป็นข้อพิสูจน์ที่โง่กว่าที่จะใช้var sounds = assets+"/sounds"เพราะแม้ว่าจะassetsมีเครื่องหมายทับท้ายและคุณก็จบลงด้วย/images//soundsก็จะยังคงแก้ไข/images/soundsได้ ข้อจำกัดความรับผิดชอบหนึ่งข้อขึ้นอยู่กับตัวจัดการคำขอของคุณ Apache ดูเหมือนว่าจะจัดการได้ดี (อย่างน้อยรุ่น / การกำหนดค่าบางอย่างดูที่http://www.amazon.com//gp//site-directory//ref=nav_sad ) ด้วยวิธีอื่น ๆ ที่คุณจะได้/imagessoundsไม่ใช่ข้อพิสูจน์ที่โง่เขลา :) นอกจากนี้ยังมีตัวเลือกในการตรวจสอบเครื่องหมายทับสองชั้นและทำความสะอาด ไม่ใช่ตัวเลือกด้วยวิธีการอื่น


11
ในบริบททั้งหมดที่ฉันรู้เส้นทางที่เริ่มต้นด้วยเครื่องหมายทับ ( /) เป็นเส้นทางสัมบูรณ์ไม่ใช่เส้นทางสัมพัทธ์ หรือคุณหมายถึงเฉพาะส่วนของเส้นทางที่ไม่ใช่ส่วนแรกเท่านั้น
Bart van Ingen Schenau

@BartvanIngenSchenau ฉันเห็นด้วยกับคุณโดยสิ้นเชิงและฉันได้รับการเรียกพวกเขาว่ามานานหลายปี แต่ทุกครั้งที่ฉันอ่านบทความที่เขียนโดยนักพัฒนาส่วนหน้าพวกเขาอ้างถึงพวกเขาเป็นเส้นทางญาติ ฉันไม่ต้องการตั้งสมมติฐานดังนั้นฉันคิดว่าฉันเลือกความชั่วร้ายที่น้อยกว่าสองอย่าง ... ? ตอนนี้ที่ผมรู้ว่าฉันมีคนบางคนในด้านของฉันฉันจะปรับปรุงคำตอบของฉัน :)
rpaskett

2
สำหรับนักพัฒนาเว็บ/somewhereเป็นเส้นทางสัมพัทธ์เพราะมันไม่รวมโฮสต์ดังนั้นเบราว์เซอร์จะค้นหาตามโฮสต์ของหน้าปัจจุบัน ... ในโลกเว็บhttp://here/somewhereเป็น URI ที่สมบูรณ์และ/somewhereelseสัมพันธ์กับสิ่งนั้น ในโลกของระบบไฟล์/somewhereเป็นสิ่งที่แน่นอนมาจากรู/ทและ "วางตำแหน่ง" สัมพันธ์กับไดเรกทอรีทำงานปัจจุบัน
Rob

3
@RobY, rpaskett: ดำเนินการโดยRFC3986 (RFC ที่กำหนด URIs) http://here/somewhereคือ URI ที่มีพา ธ สัมบูรณ์/somewhereคือการอ้างอิงแบบสัมพัทธ์กับพา ธ สัมบูรณ์และsomewhere/elseเป็นการอ้างอิงแบบสัมพัทธ์กับพา ธ สัมพัทธ์ เห็นได้ชัดว่าใน "เส้นทางสัมพัทธ์" ในวงกลมเหล่านั้นถูกใช้เพื่ออ้างถึงข้อมูลอ้างอิงแบบสัมพัทธ์
Bart van Ingen Schenau

1
@BartvanIngenSchenau: ใน windows พา ธ ที่ขึ้นต้นด้วย slash เป็นพา ธ แบบสัมพัทธ์และสัมพันธ์กับ CWD en.wikipedia.org/wiki/…
Mooing Duck

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.