创建配置文件
配置文件的作用:
在我们编写Java程序时,有很多参数是会经常改变的。比如环境的配置,我们开发的时候是一套环境,测试使用的可能又是另外一套环境,最后交付给用户的时候,用户用的又是另外一套环境,不能每次都重新编译,那样成本太高,所以对于这些参数往往不能直接写死在程序里,不然会非常麻烦,每次修改都需要重新运行一次程序,这时就需要借助配置文件来存储这些常变的参数,在程序中是读取配置文件中的变量的值,如果我们需要修改这些值,只需要修改配置文件即可。
Java中比较常用的配置文件是properties文件,下面是properties文件的创建过程。
配置文件创建流程:
在菜单栏中点击 File → New → Other → 在Wizards中输入File → 选中File点击Next → 在File name中输入文件名+.properties
的后缀名的格式(如XXX.properties) → 点击Finish → 配置文件创建成功。
PS:配置文件可以直接放在src文件下,也可以放到src文件下的包中。
properties文件的使用
规则
- 允许使用 # 作为注释;
- 以键值对的形式存储变量,使用 =作为键值对的分隔符;
- 不需要使用分号(;)作为每条语句的结尾;
- 单引号和双引号会作为值的一部分;
- 可以使用 \ 作为转义符,用来转义空格、换行和 Unicode 编码。
- 属性名不得重复
配置文件是不会编译的,而是在程序运行过程中将其读入。
其好处是可以将一些变量值存储到这里,不需要在程序中将其写死
编码
在刚创建的properties文件中使用中文,会显示为下面图片所示的\u开头的转义字符的样子,这是因为properties文件默认使用的是ISO-8859-1,该编码规则无法显示中文,所以需要在刚创建出来的properties文件中修改为utf-8的编码。
选中创建出来的properties文件 → 鼠标右键 → 选择properties会出现下面图片所示的界面 → 找到 Text file encoding,选择下面的Other,并选择utf-8编码 → 点击 Apply and Close。
回到文件中就可以看到刚才写的中文了。
读取配置文件
仅配置好了配置文件还不够,我们还需要在程序中将配置文件读取出来,下面的方法中,方法一必须要会,其他方法主要是介绍知识点,了解即可。
方法一
方法一是最简单的,必须掌握。
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()方法的源码:
这里还要说一下后面的转码,如果配置文件中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;
}