创建配置文件

  配置文件的作用
  在我们编写Java程序时,有很多参数是会经常改变的。比如环境的配置,我们开发的时候是一套环境,测试使用的可能又是另外一套环境,最后交付给用户的时候,用户用的又是另外一套环境,不能每次都重新编译,那样成本太高,所以对于这些参数往往不能直接写死在程序里,不然会非常麻烦,每次修改都需要重新运行一次程序,这时就需要借助配置文件来存储这些常变的参数,在程序中是读取配置文件中的变量的值,如果我们需要修改这些值,只需要修改配置文件即可。

  Java中比较常用的配置文件是properties文件,下面是properties文件的创建过程。

  配置文件创建流程
  在菜单栏中点击 File → New → Other → 在Wizards中输入File → 选中File点击Next → 在File name中输入文件名+.properties的后缀名的格式(如XXX.properties) → 点击Finish → 配置文件创建成功。

PS:配置文件可以直接放在src文件下,也可以放到src文件下的包中。

properties文件的使用

规则

  1. 允许使用 # 作为注释;
  2. 以键值对的形式存储变量,使用 =作为键值对的分隔符;
  3. 不需要使用分号(;)作为每条语句的结尾;
  4. 单引号和双引号会作为值的一部分;
  5. 可以使用 \ 作为转义符,用来转义空格、换行和 Unicode 编码。
  6. 属性名不得重复

配置文件是不会编译的,而是在程序运行过程中将其读入。
其好处是可以将一些变量值存储到这里,不需要在程序中将其写死

编码

  在刚创建的properties文件中使用中文,会显示为下面图片所示的\u开头的转义字符的样子,这是因为properties文件默认使用的是ISO-8859-1,该编码规则无法显示中文,所以需要在刚创建出来的properties文件中修改为utf-8的编码。

java生成配置文件 java创建配置文件_读取配置文件


  选中创建出来的properties文件 → 鼠标右键 → 选择properties会出现下面图片所示的界面 → 找到 Text file encoding,选择下面的Other,并选择utf-8编码 → 点击 Apply and Close。

java生成配置文件 java创建配置文件_配置文件_02


  回到文件中就可以看到刚才写的中文了。

java生成配置文件 java创建配置文件_配置文件_03

读取配置文件

  仅配置好了配置文件还不够,我们还需要在程序中将配置文件读取出来,下面的方法中,方法一必须要会,其他方法主要是介绍知识点,了解即可。

方法一

  方法一是最简单的,必须掌握。

String file = new String("s16jdbc.test");
ResourceBundle rb = ResourceBundle.getBundle(file);
String s = rb.getString("key1");
// 转码
s = new String(s.getBytes("ISO-8859-1"), "UTF-8");
System.out.println(s);

  在这里需要使用到一个新的类(ResourceBundle)来读取配置文件,ResourceBundle类将配置文件视为类,这要求配置文件必须放在包中,使用全包名+配置文件名作为路径读取(注意和后面的I/O流读取文件时的绝对路径和相对路径区别开)。
  使用ResourceBundle类的getBundle方法读取配置文件,然后使用getString()方法根据键值获取对应的value值,并将value值转换成String返回。

   PS:getString()方法的源码:

java生成配置文件 java创建配置文件_配置文件_04


  这里还要说一下后面的转码,如果配置文件中value有中文,需要写转码的那段代码,否则会输出乱码。

方法二

  说到读取文件,很自然会想到使用I/O流读取文件,方法二就是使用字节流读取配置文件。
  在我们读取配置文件之前,还需要了解一个知识点——Java中专门提供了一个properties配置文件的操作类(Properties类),其实之前在集合框架图中有看到过Properties类,这个类是Map接口下的一个实现类,所以Properties也是Map那种Key——Value结构。
   PS:(想了解一些Properties原理部分的知识,可以看下这篇文章:细数Java项目中用过的配置文件(properties篇))
  使用字节流读取配置文件,加载到Properties对象中,然后用get方法将Value取出。PS: Properties的get()返回的是Object类型,所以需要用toString()方法将其转换成字符串类型。

public void reader1() throws IOException {
	// 使用字节流方式读取文件,这里使用的是绝对路径读取配置文件
	String filePath = "F:\\Process\\Java\\study\\src\\s16jdbc\\test.properties";
	InputStream in = new BufferedInputStream(new FileInputStream(filePath));
	
	Properties test = new Properties();
	// 将配置文件以流的形式读取到Properties对象中
	test.load(in);
	// 从Properties对象的使用方法和Map一样,不过其get方法返回的是Object对象
	String value = test.get("key1").toString();
	System.out.println(value);
	
	// 转码
	value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
	System.out.println(value);
	
	in.close();
	in=null;
}

方法三:

  方法三还是使用的ResourceBundle,这个方法了解即可,这里主要是介绍了ResourceBundle的遍历,这里用到了Enumeration,这是枚举的迭代,这个类现在用到也比较少了。

@Test
public void reader2() throws IOException {
	// 使用全包名+全类名的方式读配置文件
	ResourceBundle rb = ResourceBundle.getBundle("s16jdbc.test");
	Properties test = new Properties();
	Enumeration<String> e = rb.getKeys();
	while(e.hasMoreElements()) {
		String s = e.nextElement();
		test.put(s, rb.getObject(s));
	}
	String value = test.get("key1").toString();
	// 转码
	value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
	System.out.println(value);
}

方法四

  这个方法了解一下即可,是前面方法二和方法三的一个结合

public void reader3() throws IOException {
	String filePath = "F:\\Process\\Java\\study\\src\\s16jdbc\\test.properties";
	InputStream in = new BufferedInputStream(new FileInputStream(filePath));
	ResourceBundle rb = new PropertyResourceBundle(in);
	Properties test = new Properties();
	Enumeration<String> e = rb.getKeys();
	while(e.hasMoreElements()) {
		String s = e.nextElement();
		test.put(s, rb.getObject(s));
	}
	String value = test.get("key1").toString();
	// 转码
	value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
	System.out.println(value);
	in.close();
	in=null;
}

方法五

  使用了getResourceAsStream()这个方法,这个方法是中高级编程中比较常用的方法。
  PS:注意路径的书写!

@Test
public void reader4() throws IOException {
	String filePath = "./test.properties";
	InputStream in = ReaderProperties.class.getResourceAsStream(filePath);
	Properties test = new Properties();
	test.load(in);
	// 从Properties对象的使用方法和Map一样,不过其get方法返回的是Object对象
	String value = test.get("key1").toString();
	// 转码
	value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
	System.out.println(value);
	in.close();
	in=null;
}

方法六

  使用getClassLoader()这个方法,获取类加载器,类加载器在中高阶编程中基本都会使用到。
  注意路径的书写!

public void reader5() throws IOException {
	String filePath = "s16jdbc/test.properties";
	InputStream in = ReaderProperties.class.getClassLoader().getResourceAsStream(filePath);
	Properties test = new Properties();
	test.load(in);
	// 从Properties对象的使用方法和Map一样,不过其get方法返回的是Object对象
	String value = test.get("key1").toString();
	System.out.println(value);	
	// 转码
	value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
	System.out.println(value);	
	in.close();
	in=null;
}

方法七

  方法六是使用getClassLoader()方法获得一个类加载器,方法七这里直接使用类加载器中的静态方法ClassLoader.getSystemResourceAsStream(filePath)
  PS:注意路径的书写!

public void reader6() throws IOException {
	String filePath = "s16jdbc/test.properties";
	InputStream in = ClassLoader.getSystemResourceAsStream(filePath);
	Properties test = new Properties();
	test.load(in);
	// 从Properties对象的使用方法和Map一样,不过其get方法返回的是Object对象
	String value = test.get("key1").toString();
	// 转码
	value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
	System.out.println(value);	
	in.close();
	in=null;
}