`
hdwangyi
  • 浏览: 183255 次
社区版块
存档分类
最新评论

Java程序中的配置文件的存放和读取

    博客分类:
  • Java
阅读更多
大家可能经常会遇到在Java程序中存取程序配置文件的需求,比如,为了能够和不同的数据库连接,我们经常把数据库连接的信息存放到属性文件中,这些信息一般包括数据库驱动程序类名、数据库连接的URL,数据库的用户名和口令等等。为了便于程序的安装或部署,我们经常会把这些的配置文件存放到程序安装的根目录中。由于Java程序用包来分组类,有时候将这些配置文件放入到读取它们的类所在的包目录中会更好一些。比如,在下面的图示中,将数据库配置文件 database.properties放到数据库读取类所在的包目录就是一种比较清晰的存储方案:

                        /-----------其它包目录
                              |
                              |
                              -------edu.ec.database
                                                 |
                                                 |---------------ConnectionPool(数据库连接池类)
                                                 |
                                                 |---------------Dao(数据库访问对象类)
                                                 |
                                                 |---------------DaoFactory(Dao的工厂类)
                                                 |
                                                 |---------------database.properties(数据库配置属性文件)
                                                 |
                                                 |---------------RecordSet(记录集类)
   
在这种存储方案中,所有的与数据库相关的类和配置文件都在同一个包目录中;在开发过程中,配置文件和源文件也按采用这种方式进行组织,这样会使得程序的数据库访问维护变得相当清晰明了。

大部分开发工具在编译打包这样的源文件组织时,会自动将相关配置文件和类文件放到生成的目标文件夹中或JAR文件中。一般情况下,我们在发布自己的 Java程序时,都是以JAR或WAR形式将程序打包发布,而对应的配置文件也会按照上述的目录格式被放到了JAR或WAR文件中,这样,就实现了配置文件和程序文件打包在一起发布的目的。

现在的问题是,我们如何读取位于程序安装文件中的配置文件的信息?比如,在上面的图中, ConnectionPool是一个数据库连接池类,它需要在系统启动时自动读取存储在database.properties中的数据库连接和配置信息,以便设置相关的数据库连接。这样,我们 就需要在程序中测定目前程序安装或部署的位置,以便读取对应的属性文件。

       在很多其他语言编写的程序中,我们可以利用一些系统提供的API或一些全局对象获取目前应用程序运行所在的目录。比如VB,我们可以使用Application对象测定当前程序的安装位置,在Java程序中如何完成类似的任务呢?

Java程序并没有类似于VB那种全局对象,但如果我们观察位于上述目录结构中的database.properties文件,应该发现其处于应用程序的CLASSPATH中,这样,我们就可以使用Java中的类装载器中的相关的方法,读出这些配置文件的信息,该类名为ClassLoader。比如,在上例中,我们可以先得到ConnectinPool的类装载器,然后测定ConnectionPool类所在的包路径,然后利用 ConnectionPool所在的包目录读出database.properties文件的信息,对应的伪代码如下:

            ClassLoader loader=ConnectionPool.class.getClassLoader();
            得到ConnectionPool所在的包名;
            将包名转换为对应的目录名,存入一个名为path的字符串变量中;
           调用loader的getResourceAsStream(path+"database.properties"),得到输入流
          
          下面是一个可实际运行的样例代码片段,它可自动测定传入的类所在的包目录,返回传入的属性文件所代表的输入流。它还有一个附加的功能:如果属性文件直接放到了当前类所在的根目录(比如位于JAR文件的根目录或WAR文件的WEB-INF/classes目录中)、系统的用户目录系统、系统其他的类路径中时,它也可以找到;当然,如果还是找不到,它将返回null。具体的代码如下:


        public class PropHelper{
                      /**
                       *guessPropFile:
                       *@param cls:和要寻找的属性文件处于相同的包中的任意的类
                       *@param propFile:要寻找的属性文件名
                       */
                   public   static java.io.InputStream guessPropFile(Class cls,String propFile){
                                try{
                                      //得到类的类装载器
                                      ClassLoader loader=cls.getClassLoader();
                                     
                                      //先从当前类所处路径的根目录中寻找属性文件
                                      java.io.InputStream in=loader.getResourceAsStream(propFile);
                                      if(in!=null) return in;
                                     
                                      //没有找到,就从该类所处的包目录中查找属性文件
                                     Package pack=cls.getPackage();
                                     if(pack!=null){
                                              String packName=pack.getName();
                                              String path="";
                                              if(packName.indexOf(".") < 0 )
                                                 path=packName+"/";
                                              else{
                                                       int start=0,end=0;
                                                       end=packName.indexOf(".");
                                                       while(end!=-1){
                                                             path=path+packName.substring(start,end)+"/";
                                                             start=end+1;
                                                            end=packName.indexOf(".",start);
                                                        }
                                                       path=path+packName.substring(start)+"/";
                                              }
                                              in=loader.getResourceAsStream(path+propFile);
                                              if(in!=null) return in;
                                   }
                                  
                                  //如果没有找到,再从当前系统的用户目录中进行查找
                                  java.io.File f=null;
                                  String curDir=System.getProperty("user.dir");
                                  f=new java.io.File(curDir,propFile);
                                  if(f.exists()) return new java.io.FileInputStream(f);
                                 
                                  //如果还是没有找到,则从系统所有的类路径中查找
                                  String classpath=System.getProperty("java.class.path");
                                  String[] cps=classpath.split(System.getProperty("path.separator"));
                                 
                                  for(int i=0;i < cps.length; i++){
                                           f=new java.io.File(cps[i],propFile);
                                           if(f.exists()) break;
                                           f=null;
                                   }
                                  if(f!=null) return new java.io.FileInputStream(f);
                                  return null;
                            }catch(Exception e){throw new RuntimeException(e);}
                  
                     }
        }
        
使用举例:利用上述的方法,可在ConnectionPool中自动查找和ConnectionPool处于同一个包目录中的database.properties的输入流,并利用该输入流读入对应的属性值的代码如下:
       public class ConnectionPool{
            //静态初始化器,将在ConnectionPools加载时自动执行
           static{
               java.util.Properties dbProp=new java.util.Properties();
               java.io.InputStream in=PropHelper.guessPropFile(edu.ec.database.ConnectionPool.class,"database.properties");
               if(in!=null) dbProp.load(in);
               //利用dbProp,为相应的数据源对象设置相关的属性,比如C3P0........
            }
     }
分享到:
评论
3 楼 tvjody 2007-08-20  
deadcode 写道
这个道路是不是有些曲折?
要是程序被打包了,要改个配置还要重新打包?

配置文件多的话还是集中起来管理比较直观,而且很多可以在系统启动时先加载,一般也就一次.
程序打包成Jar发布后,应该将配置文件放在jar的当前同级目录,访问调用直接访问,如
java.util.Properties pro = new java.util.Properties();
InputStream inStream = new java.io.FileInputStream("database.properties");pro.load(inStream);
如果是打包成WAR发布,则放在适合LZ的方法
2 楼 deadcode 2007-08-14  
这个道路是不是有些曲折?
要是程序被打包了,要改个配置还要重新打包?

配置文件多的话还是集中起来管理比较直观,而且很多可以在系统启动时先加载,一般也就一次.
1 楼 hdwangyi 2007-07-26  
    现在,guessPropFile可以自动在如下位置中寻找属性文件:
   

       
  1. 在未打包的Java程序的类文件所在的根目录中寻找属性文件
  2.    
  3. 在打包的JAR程序的根目录中寻找属性文件
  4.    
  5. 在未打包的Java类文件所在的根目录中对应传入参数类所在的包目录中寻找属性文件
  6.    
  7. 在打包的JAR文件中对应传入参数类所在的包目录中寻找属性文件
  8.    
  9. 在未打包及打包的WAR文件夹中的WEB-INF/classes目录中寻找属性文件
  10.    
  11. 在未打包及打包的WAR文件中的WEB-INF/classes目录中对应传入参数类所在的包目录中寻找属性文件
  12.    
  13. 在操作系统中的当前登录用户的主目录中寻找属性文件
  14.    
  15. 在系统设定的环境变量CLASSPATH所指向的各个目录中寻找属性文件
  16.    

 
    其实,guessPropFile方法还可做的更加智能一些,比如在WAR文件的WEB-INF文件中寻找属性文件。如果要完成这个任务,ClassLoader是关键类,利用它的getResource方法,就可以获得相应程序中的资源的位置,我们可以在它的基础上稍加修改就可获得当前Java程序的运行位置信息,其伪代码如下:
  获得Class参数的所在的类名
  取得该类所在的包名
  将包名转换为路径
  利用getResource得到当前的类文件所在URL
  利用URL解析出当前Java程序所在的路径
具体代码如下:
   public class PropHelper{
    //其他方法的定义
    //.............

    /**
     *getAppPath需要一个当前程序使用的Java类的class属性参数,它可以返回打包过的
     *Java可执行文件(jar,war)所处的系统目录名或非打包Java程序所处的目录
     *@param cls为Class类型
     *@return 返回值为该类所在的Java程序运行的目录
     */
    public static String getAppPath(Class cls){
        ClassLoader loader=cls.getClassLoader();
        String clsName=cls.getName()+".class";
        Package pack=cls.getPackage();
        String path="";
        if(pack!=null){
            String packName=pack.getName();
            clsName=clsName.substring(packName.length()+1);
            if(packName.indexOf(".")<0) path=packName+"/";
            else{
                int start=0,end=0;
                end=packName.indexOf(".");
                while(end!=-1){
                    path=path+packName.substring(start,end)+"/";
                    start=end+1;
                    end=packName.indexOf(".",start);
                }
                path=path+packName.substring(start)+"/";
            }
        }
        java.net.URL url =loader.getResource(path+clsName);
        String realPath=url.getPath();
        int pos=realPath.indexOf("file:");
        if(pos>-1) realPath=realPath.substring(pos+5);
        pos=realPath.indexOf(path+clsName);
        realPath=realPath.substring(0,pos-1);
        if(realPath.endsWith("!"))
            realPath=realPath.substring(0,realPath.lastIndexOf("/"));
        return realPath;
    }//getAppPath定义结束

 }//PropHelper类定义结束


在getAppPath方法的帮助下,我们可以测定当前程序运行的路径是不是包含WEB-INF/classes路径信息,如果是,则当前程序就可能是运行在Web环境中,这样,就可以对guessPropFile中的代码进行增加,加入在WEB-INF文件夹寻找属性文件的方法。

   

相关推荐

    Java程序中的配置文件的存放和读取[文].pdf

    Java程序中的配置文件管理和读取是软件开发过程中的常见任务,尤其在涉及到数据库连接、环境配置等场景时,配置文件的正确存放和读取至关重要。本文主要探讨如何在Java程序中处理配置文件。 首先,配置文件通常包含...

    Java中XML配置文件的读取(sax).doc

    Java中XML配置文件的读取(SAX) XML配置文件是Java开发中常用的配置文件格式,特别是在J2EE项目中。XML文件可以存储配置信息,并且易于维护和修改。然而,在Java中读取XML配置文件成了一个需要解决的问题。本文将...

    spring读取jar中的配置文件

    当我们的应用程序被打包成JAR文件后,有时我们需要从JAR内部读取配置文件,例如application.properties或application.yml。本文将深入探讨如何在Spring框架中实现这一功能。 首先,理解Spring的资源配置。Spring...

    java读取项目中的文件(src目录下)

    - 通常,Java项目有一个标准的目录结构,如`src/main/java`用于存放Java源代码,`src/main/resources`用于存放资源文件,如配置文件、图片或文本文件等。如果你的文件直接放在`src`目录下,可能意味着它是在源代码...

    JAVA连接字符串到配置文件

    在Java开发中,将连接字符串存放在配置文件中是一种常见的最佳实践,这有助于提升代码的可维护性和灵活性。连接字符串通常用于数据库连接、API调用或者其他需要网络通信的服务。本篇将详细介绍如何在Java中实现这一...

    android项目中读取ini配置文件

    本文将详细介绍如何在Android项目中读取存放在`assets`文件夹中的`ini`配置文件。 1. **ini文件格式介绍** `ini`文件是一种轻量级的配置文件格式,主要用于存储键值对数据。通常,每个节(section)以方括号`[]`...

    读取properties配置文件

    综上所述,`PropertiesUtil`类是Java应用程序中读取和管理配置文件的关键工具,它提供了便捷的方法来获取配置信息,同时通过`BaseProperties`可能实现了环境和多语言的适配。理解并熟练使用这类工具对于提升Java应用...

    在web和j2se中两个不同环境下 读取配置文件 备忘

    本备忘主要关注在Web环境(如Tomcat、Jetty等)和J2SE(Java Standard Edition)环境中如何读取配置文件,以便于应用的正常运行。 首先,我们来看Web环境中的配置文件读取。在Web应用中,配置文件通常存放在`WEB-...

    各个Jar程序属性配置文件的说明

    在Java开发环境中,配置文件是项目管理中不可或缺的一部分,它们用于定义应用的运行时环境、数据库连接、系统参数等关键信息。以下是对给定文件中提及的四种不同配置文件的详细解析,包括模拟数据源段的配置属性文件...

    Java实现的文件读取工具类

    - ".classpath" 和 ".project" 是Eclipse IDE的工作空间配置文件,不包含源代码。 - "src" 目录通常存放源代码。 - ".settings" 存放项目的特定配置。 - "bin" 目录是编译后的字节码文件(class文件)的存放位置...

    java源码 java获取音频文件 播放时长AudioDemo 2018127

    在项目结构中,`AudioDemo.iml`是IntelliJ IDEA项目的配置文件,`src`目录存放源代码,`.idea`目录包含了IDE的项目设置,而`out`目录则包含了编译后的字节码文件和运行时生成的临时文件。 总的来说,`AudioDemo`...

    XML配置文件连接Oracle数据库

    5. **解析XML配置**:在应用程序中,你需要使用Java的DOM或SAX解析器来读取和解析XML配置文件。获取到连接信息后,可以使用`java.sql.DriverManager`类的`getConnection()`方法建立数据库连接。 6. **建立数据库...

    java中读取ORACLE中BLOB字段存储的图片

    本文将详细介绍如何在Java应用程序中读取存储在Oracle数据库BLOB字段中的图片数据。 #### 二、准备工作 为了实现读取Oracle数据库中的BLOB字段存储的图片,我们需要进行以下准备: 1. **环境搭建**: - Oracle...

    解析配置文件 工程源码

    在IT行业中,配置文件是应用程序的关键组成部分,它们存储着应用运行时所需的设置和参数。Java Maven工程中的配置文件解析是一项常见的任务,对于理解和调试代码至关重要。本篇文章将深入探讨如何利用Java来解析配置...

    读取webroot文件下的属性文件

    其中,属性文件(通常为.properties格式)是Java开发中常用的一种配置文件,用于存储程序的配置信息,如数据库连接、系统参数等。本篇将详细介绍如何在Java环境下读取webroot目录下的属性文件。 首先,确保属性文件...

    Java IO流:从xml文件中读取数据,在程序中创建对象

    XML(Extensible Markup Language)是一种结构化数据存储格式,广泛应用于配置文件、数据交换和文档存储。 首先,我们需要导入必要的库,包括`java.io`和`javax.xml.parsers`。这两个包提供了处理文件流和解析XML的...

    java版FTP文件管理程序

    4. **项目结构**:一个标准的Java项目通常包含源代码文件、资源文件、配置文件以及测试代码等。在这个FTP程序中,可能有专门的包或目录用于存放与FTP相关的类,如`FTPClient`、`FTPConnection`等。 5. **使用说明**...

    Java 读取资源文件

    在Java编程中,读取资源...以上就是Java中读取资源文件的基本方法和注意事项。在实际开发中,根据项目结构和需求,你可能需要选择最适合的方法来访问和处理资源文件。理解这些概念将有助于提升你的代码质量和可维护性。

    Java程序生成exe可执行文件详细教程(图文说明)

    首先在某盘符底下建立一个文件夹,然后将 jre 和程序所需的 Jar 包文件及 Java 程序所要读取的配置文件放入到文件夹。打开 exe4j 程序,选择第二项“JAR in EXE” mode,然后点击“next”选择类型。如果选择第一个,...

Global site tag (gtag.js) - Google Analytics