วิธีรับพา ธ สัมบูรณ์ไปยังไฟล์ในโฟลเดอร์ / resources ของโครงการของคุณ


95

สมมติการตั้งค่า maven มาตรฐาน

abcกล่าวว่าในทรัพยากรของคุณโฟลเดอร์ที่คุณมีไฟล์

ใน Java ฉันจะขอพา ธ สัมบูรณ์ไปยังไฟล์ได้อย่างไร?


คุณต้องการเขียนปลั๊กอิน Maven หรือไม่? หรือคุณต้องการเข้าถึงไฟล์เมื่อโปรแกรมของคุณทำงาน?
Gyro Gearless

ที่เกี่ยวข้อง: stackoverflow.com/questions/8136891/…
Vadzim

วิธีแก้ปัญหามีสามแบบขึ้นอยู่กับสถานการณ์: stackoverflow.com/a/56327069/715269
Gangnus

คำตอบ:


73

คุณสามารถใช้ClassLoader.getResourceวิธีการเพื่อรับทรัพยากรที่ถูกต้อง

URL res = getClass().getClassLoader().getResource("abc.txt");
File file = Paths.get(res.toURI()).toFile();
String absolutePath = file.getAbsolutePath();

หรือ

แม้ว่าวิธีนี้อาจไม่ได้ผลตลอดเวลา แต่วิธีแก้ปัญหาที่ง่ายกว่า -

คุณสามารถสร้างFileวัตถุและใช้getAbsolutePathวิธีการ:

File file = new File("resources/abc.txt");
String absolutePath = file.getAbsolutePath();

8
คำแนะนำในการใช้งานแบบ จำกัด เนื่องจากขึ้นอยู่กับไดเร็กทอรีการทำงานเพื่อเป็น maven root และถึงอย่างนั้นคุณควรใช้target/classes/abc.txtเพื่ออ้างอิงไฟล์เนื่องจากนี่คือตำแหน่งที่เป็นที่ยอมรับที่ Maven วางไฟล์ทรัพยากรหลังจากการประมวลผล (ตัวอย่างเช่นปลั๊กอิน maven-resources อาจทำการแทนที่คุณสมบัติใน abc.txt) การใช้ abc.txt ผ่าน getResource () จาก classpath จะดีกว่ามาก
Gyro Gearless

2
จะเกิดอะไรขึ้นหากผู้ใช้ปลายทางเรียกใช้แอปพลิเคชันของคุณเป็น JAR ที่ปฏิบัติการได้ จากนั้นจะไม่มีไฟล์ทางกายภาพเลย นี่เป็นอีกเหตุผลหนึ่งที่คุณควรใช้ getResource () และเช่นเปิดอินพุตสตรีมขึ้นอยู่กับว่าคุณต้องการทำอะไรกับมัน
Matthew Wise

6
สามารถลบออกเป็นคำตอบที่ถูกต้องได้หรือไม่? @Karol S ตอบด้านล่าง - นั่นน่าจะเป็นคำตอบที่ถูกต้อง (ด้วยเหตุนี้ความคลาดเคลื่อนในการเพิ่มคะแนน)
DanGordon

3
คำตอบที่ไม่ถูกต้อง. โปรดดูคำตอบด้านล่างโดย @Karol
bhathiya-perera

168

วิธีที่เหมาะสมที่ใช้งานได้จริง:

URL resource = YourClass.class.getResource("abc");
Paths.get(resource.toURI()).toFile();

ไม่สำคัญว่าตอนนี้ไฟล์ใน classpath จะอยู่ที่ใดโดยจะพบได้ตราบใดที่ทรัพยากรนั้นเป็นไฟล์จริง ๆ และไม่ใช่รายการ JAR

(เห็นได้ชัดว่าใช้new File(resource.getPath())ไม่ได้กับทุกเส้นทางเส้นทางนี้ยังเข้ารหัส URL อยู่!)


5
หรือสันนิษฐานว่าคุณสามารถทำได้: new File(resource.toURI()).getAbsolutePath();(เช่นฉันไม่คิดว่าคุณต้องการวัตถุ Path?)
Dan King

1
เคล็ดลับดีๆเกี่ยวกับ toURI () วิธีนี้จะช่วยหลีกเลี่ยงช่องว่างในเส้นทางของคุณในรูปแบบ% 20!
Matthew Wise

29
ขอบคุณ! เกือบจะได้ผลสำหรับฉัน แต่ฉันต้องทำการเปลี่ยนแปลงอย่างใดอย่างหนึ่ง: YourClass.class.getClassLoader (). getResource ("abc");
yngwietiger

คุณสามารถทำสลับกันได้new File(YourClass.class.getResource("abc").toURI().getPath())หากต้องการ
Mike Rylander

2
ฉันไม่เข้าใจว่าสิ่งนี้ได้ผลกับคนจำนวนมากอย่างไรโดยไม่ต้องใช้เครื่องหมายทับ:.getResource("/abc")
cahen

28

คุณต้องระบุเส้นทางเริ่มต้นจาก /

URL resource = YourClass.class.getResource("/abc");
Paths.get(resource.toURI()).toFile();

12

สร้างอินสแตนซ์ classLoader ของคลาสที่คุณต้องการจากนั้นคุณสามารถเข้าถึงไฟล์หรือทรัพยากรได้อย่างง่ายดาย ตอนนี้คุณเข้าถึงเส้นทางโดยใช้getPath()วิธีการของคลาสนั้น

 ClassLoader classLoader = getClass().getClassLoader();
 String path  = classLoader.getResource("chromedriver.exe").getPath();
 System.out.println(path);


0

มีปัญหาสองประการระหว่างทางไปสู่เส้นทางสัมบูรณ์:

  1. ตำแหน่งที่พบจะไม่ใช่ตำแหน่งที่ไฟล์ต้นฉบับอยู่ แต่จะบันทึกคลาสไว้ที่ไหน และโฟลเดอร์ทรัพยากรเกือบจะอยู่ที่ไหนสักแห่งในโฟลเดอร์ต้นทางของโครงการ
  2. ฟังก์ชันเดียวกันสำหรับการดึงทรัพยากรจะทำงานแตกต่างกันหากคลาสทำงานในปลั๊กอินหรือในแพ็กเกจโดยตรงในพื้นที่ทำงาน

รหัสต่อไปนี้จะให้เส้นทางที่เป็นประโยชน์ทั้งหมดแก่เรา:

    URL localPackage = this.getClass().getResource("");
    URL urlLoader = YourClassName.class.getProtectionDomain().getCodeSource().getLocation();
    String localDir = localPackage.getPath();
    String loaderDir = urlLoader.getPath();
    System.out.printf("loaderDir = %s\n localDir = %s\n", loaderDir, localDir);

ทั้งสองฟังก์ชันที่สามารถใช้สำหรับการแปลโฟลเดอร์ทรัพยากรได้รับการค้นคว้า สำหรับclassมันสามารถทำได้ทั้งแบบคงที่หรือแบบไดนามิก


หากโปรเจ็กต์ไม่ได้อยู่ในปลั๊กอินโค้ดหากรันใน JUnit จะพิมพ์:

loaderDir = /C:.../ws/source.dir/target/test-classes/
 localDir = /C:.../ws/source.dir/target/test-classes/package/

ดังนั้นในการไปที่ src / rest / resources เราควรขึ้นและลงโครงสร้างไฟล์ สามารถใช้ได้ทั้งสองวิธี สังเกตุเราใช้ไม่ได้getResource(resourceFolderName)เพราะโฟลเดอร์นั้นไม่ได้อยู่ในโฟลเดอร์เป้าหมาย ไม่มีใครใส่ทรัพยากรในโฟลเดอร์ที่สร้างขึ้นฉันหวังว่า


หากคลาสอยู่ในแพ็คเกจที่อยู่ในปลั๊กอินผลลัพธ์ของการทดสอบเดียวกันจะเป็น:

loaderDir = /C:.../ws/plugin/bin/
 localDir = /C:.../ws/plugin/bin/package/

ดังนั้นเราควรขึ้นและลงโครงสร้างโฟลเดอร์อีกครั้ง


สิ่งที่น่าสนใจที่สุดคือกรณีเมื่อเปิดตัวแพคเกจในปลั๊กอิน จากการทดสอบปลั๊กอิน JUnit สำหรับตัวอย่างของเรา ผลลัพธ์คือ:

loaderDir = /C:.../ws/plugin/
 localDir = /package/

ที่นี่เราจะได้พา ธ สัมบูรณ์เฉพาะการรวมผลลัพธ์ของทั้งสองฟังก์ชัน และมันยังไม่เพียงพอ ระหว่างนั้นเราควรวางเส้นทางท้องถิ่นของสถานที่ที่แพ็กเกจคลาสอยู่ในโฟลเดอร์ปลั๊กอิน เป็นไปได้ว่าคุณจะต้องแทรกบางอย่างเป็นsrcหรือsrc/test/resourceที่นี่

คุณสามารถแทรกรหัสลงในของคุณและดูเส้นทางที่คุณมี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.