java加載文件的三種方式


一般我們加載文件都是以下3種方式進行加載,之前一直困擾我很久的關於文件加載的路徑問題,今天我想自己寫一個wiki page來記錄下,總結下:

1,通過類加載器

   這種方式是通過java自己的類加載器來加載文件,根目錄爲java類的打包出來後的根目錄。相對目錄就是當前類所在的包位置。如果你希望加載的文件是保存在類加載器能訪問到的目錄,推薦使用此加載方式(web應用中web-inf下的文件出於安全機制的考慮是不能通過web-inf進行加載的)
Java代碼 複製代碼 收藏代碼
  1. InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filePath);  
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filePath);



2,通過文件系統加載
    這種方式是通過系統的文件系統機制進行加載,它接受的參數(文件路徑)是一個絕對路徑地址,你可能會覺得這樣的話文件路徑會在代碼中hard coding,不優雅,當然你可以選擇用很多種方式獲得項目的路徑再進行相應的相對路徑拼裝,至少我是這麼做的。
Java代碼 複製代碼 收藏代碼
  1. InputStream inputStream = new FileInputStream(file);  
InputStream inputStream = new FileInputStream(file);

    但是有個很重要的問題需要說明,看下面的例子(在weblogic應用服務器中):
    其中使用到了Log4J作爲日誌輸出工具,Log4J的配置文件log4j.propertes放在 DefaultWebApp\WEB-INF目錄下。Log4J通過一個自動加載的Servlet進行初始化,初始化代碼如下: 
   
Java代碼 複製代碼 收藏代碼
  1. ServletContext context = getServletContext();     
  2. org.apache.log4j.PropertyConfigurator.    
  3. configure(context.getRealPath("/")    
  4. "/WEB-INF/log4j.properties");    
 ServletContext context = getServletContext();   
 org.apache.log4j.PropertyConfigurator.  
 configure(context.getRealPath("/")  
 + "/WEB-INF/log4j.properties");  

     其中,context.getRealPath("/")得到當前Web應用的真實根目錄,比如,如果你的WebLogic安裝在D:\bea下,在Windows下context.getRealPath("/")通常會返回:D:\bea\wlserver6.1\config\mydomain\applications\DefaultWebApp。這樣,和 "/ WEB-INF /log4j.properties"拼接後,就得到了log4j.properties文件的真實路徑。現在一切正常!測試通過後,將DefaultWebApp下的所有文件打爲一個.war包,進行部署時,發現系統報告找不到“D:\bea \wlserver6.1\null\ WEB-INF \log4j.properties”文件!如果你的應用中還需要讀取其它已經被打包到war包中的文件,都會報告找不到文件。並且,系統並不會到D:\bea\wlserver6.1\config\mydomain\applications\DefaultWebApp 目錄下尋找,而會到D:\bea\wlserver6.1\null下尋找。這是因爲context.getRealPath("/")返回了null。
     查看ServletContext的API文檔,原來,對一個打包的應用來說,是沒有RealPath的概念的,調用getRealPath 只會簡單地返回null。其實,也很好理解,一個文件被打包入了.war文件,就不存在目錄結構了(雖然包中仍然存在目錄結構,但這不等同於文件系統中的目錄結構)。所以,對war包中的資源是無法得到RealPath的。這樣也就無從通過文件IO進行讀取了。那麼,如何讀取war包中的資源呢?答案是使用ServletContext.getResourceAsStream(String)方法。那麼,現在對於war應用可以成功運行,但如果現在不通過war部署,直接通過目錄結構部署應用會不會又出現找不到資源的錯誤呢?請來看看 ServletContext.getResourceAsStream的API文檔,
Java代碼 複製代碼 收藏代碼
  1. # Returns a URL to the resource that is     
  2. # mapped to a specified path. The path     
  3. # must begin with a "/" and is interpreted    
  4. # as relative to the current context root.     
  5. # This method allows the servlet container     
  6. # to make a resource available to servlets    
  7. # from any source. Resources can be located     
  8. # on a local or remote file system,    
  9. # in a database, or in a .war file.    
  10. #     
# Returns a URL to the resource that is   
# mapped to a specified path. The path   
# must begin with a "/" and is interpreted  
# as relative to the current context root.   
# This method allows the servlet container   
# to make a resource available to servlets  
# from any source. Resources can be located   
# on a local or remote file system,  
# in a database, or in a .war file.  
#   

     可見,通過getResourceAsStream可以獲取包括本地文件系統、遠程文件系統、war包等資源。不會出現上面擔心的問題。
     結論:在開發J2EE Web應用時,如果需要讀取本應用中的文件,儘量使用ServletContext.getResourceAsStream進行,而不要使用文件IO。getRealPath在不同的服務器中獲得的參數是不一樣的,有些會返回空,有些會返回正常數據,這就要看服務器是否解包文件了,而且有些服務器中getRealPath是本身就以"/"結尾的,這裏是最好進行下判斷:
Java代碼 複製代碼 收藏代碼
  1. realPath.endsWith("/")?realPath:(realPath+"/")  
realPath.endsWith("/")?realPath:(realPath+"/")

  


3,web程序可以通過ServletContext進行加載
    一個特定資源的URL可以通過調用ServletContext.getResource(String path)得到,這兒的path參數必須以“/”開始,將被解析爲相對於當前Servlet背景的根的相對路徑。這個方法有別於基於類加載器的 java.lang.Class.getResource方法。假如你通過ServletContext.getResource方法請求了一個.jsp 頁面,你得到的將是JSP的源碼,要得到執行結果,可以使用RequestDispatcher對象的include方法。你也可以直接以輸入流的形式得到資源,
  
Java代碼 複製代碼 收藏代碼
  1. public InputStream getResourceAsStream(String path);  
public InputStream getResourceAsStream(String path);

    上個例子已經很好的聯合文件io來對2者進行了比較了。



   
Java代碼 複製代碼 收藏代碼
  1. inputStream = sc.getResourceAsStream(EnumConstants.SERVER_CONFIGURATION_FILEPATH.toString());  
  2.   /** 
  3.     *"SERVER_CONFIGURATION_FILEPATH"  server configuration reflection class properties file path  <b>"/config/server-config.properites"  
  4.     */  
  5.     public static final EnumConstants SERVER_CONFIGURATION_FILEPATH                                 = new EnumConstants("/config/server-config.properites");  
inputStream = sc.getResourceAsStream(EnumConstants.SERVER_CONFIGURATION_FILEPATH.toString());
  /**
	*"SERVER_CONFIGURATION_FILEPATH"  server configuration reflection class properties file path  <b>"/config/server-config.properites" 
	*/
	public static final EnumConstants SERVER_CONFIGURATION_FILEPATH					        		= new EnumConstants("/config/server-config.properites");



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章