หมายเหตุ: ผมเขียน Java ด้วย Eclipse IDE เป็นหลัก ฉะนั้นจะอธิบายโดยอ้างอิง Eclipse เป็นหลักและรูปที่แสดงในโพสต์นี้ view โปรเจกต์แบบ Package Explorer นะครับ
ปัญหาน่าปวดหัวอย่างหนึ่งของการทำงานกับ Java Project นอกจากเรื่อง encoding แล้วก็มีเรื่อง path ของไฟล์ เคยไหมครับเวลาที่เราทำโปรเจกต์ที่ต้อง export เป็น JAR หรือ WAR และต้องการอ่านไฟล์ที่ถูกแพ็ครวมไว้ (resource file) ตอนรันใน IDE ก็ใช้งานได้ดีอยู่หรอกแต่พอแพ็คเป็น JAR หรือ WAR แล้วตอนรันดันบอกว่า File not found
จากที่ลองผิดลองถูกก็เจอวิธีแก้ปัญหาเลยอยากบันทึกไว้หน่อย

การอ่าน resource file เมื่อแพ็คเป็นไฟล์ JAR

Java Archive (JAR) ใครเขียน Java ไม่เคยเจอไฟล์นามสกุล *.jar แสดงว่าไม่ได้ใช้ Java ทำงานแน่ๆ :p
ไฟล์ *.jar ส่วนมากจะเป็น library บางครั้งก็เป็น Executable JAR คือเป็นโปรแกรมรันผ่าน command line ได้เลย ตัวมันเองเป็นเป็นไฟล์บีบอัดไฟล์หนึ่งครับถ้าใช้โปรแกรมแตกไฟล์เช่น unzip จะได้โฟลเดอร์ซึ่งข้างในมีโครงสร้างของไฟล์และโฟลเดอร์คล้าย Java project ใน Eclipse
เริ่มแรกต้องสร้าง resource folder ขึ้นมาก่อน โดยคลิกขวาที่โฟลเดอร์ src แล้วเลือก New -> Source Folder
ตั้งชื่อโฟลเดอร์ซะเสร็จแล้วจะได้คล้ายๆ รูปข้างล่างนี้

เวลาจะเรียกใช้งานก็อ้างอิงจาก “/” (root ของโปรเจกต์ไม่ใช่ root ของ file system) และสำคัญมากๆๆๆ ต้องอ่านเป็น stream โดยใช้ getResourceAsStream()  ไม่งั้นเวลา export เป็น JAR แล้วไปรันจะเจอ File not found
ข้างล่างนี่เป็นตัวอย่างโค้ดของผมครับ

การอ่าน resource file เมื่อแพ็คเป็นไฟล์ WAR

สำหรับ Java programmer ที่ทำเว็บด้วย JSP และ/หรือ Servlet  น่าจะคุ้นเคยกับ Web Archive (WAR) เป็นอย่างดีเพราะเวลาจะ deploy บน Web server เช่น Tomcat ต้อง export เป็น WAR ก่อน เสร็จแล้วก็อัปโหลดไปที่ Root directory ของ Web server ก็จะถูก deploy และแตกไฟล์ออกมาเป็นโฟลเดอร์โดยอัตโนมัติ (บาง Web server อาจจะไม่ auto deploy)
การอ่าน resource file ของ WAR ก็ทำเหมือน JAR สร้าง folder ด้วยการคลิกขวาที่ชื่อโปรเจกต์แล้วเลือก New -> Source Folder เหมือนกันแต่ระดับชั้นของ folder ใน Java Web Project จะเป็นชั้นเดียวกันกับ folder src ตัวอย่างที่ผมยกมาให้ดูข้างล่างเป็นการใช้งาน Hibernate ครับผมสร้าง Source Folder ชื่อ resource ซึ่งเก็บไฟล์ config ของ Hibernate
เวลาจะอ่าน resource file ของ WAR จะง่ายกว่า JAR เพราะไม่จำเป็นต้องอ่านเป็น stream ก็ได้แต่ต้องเริ่มจาก “/” เหมือนกัน