1、IO 流原理及流的分类
1.1、Java IO 流原理
(1)I/O是Input和Output的缩写,I/O技术是非常使用的技术,用于处理数据传输,如读写文件,网络通讯等
(2)Java程序中,对于数据的输入/输出操作以流(Stream)的方式进行
(3)java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并提供方法输入或输出数据
1.2、流的分类
(1)按操作数据单位不同分为:字节流(8bit),用来操作二进制文件、字符流(以字符为单位),用来操作文本文件
(2)按数据流的流向不同分为:输入流、输出流
(3)按流的角色不同分为:节点流、处理流(也叫包装流)
这四个基类都是abstract的,不能直接实例化,在使用时只能通过其子类来创建对象
1.3、文件和流的理解
流是文件传输的载体
2、InputStream 字节输入流
InputStream 抽象类是所有类字节输入流的超类,其常用的子类有
(1)FileInputStream :文件输入流
(2)BufferedInputStream :缓冲字节输入流
(3)ObjectInputStream :对象字节输入流
2.1、FileInputStream
package com.francis.inputstream;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @author Francis
* @create 2021-11-18 20:50
*/
public class FileInputStream_ {
//使用单个字符方式读取文件内容
@Test
public void readFile01(){
String filePath = "f:\\hello.txt";
int readData= 0;
StringBuffer stringBuffer = new StringBuffer();
FileInputStream fileInputStream=null;
try {
fileInputStream = new FileInputStream(filePath);
//read方法从输入流中读取一个字节的数据,如果没有输入可用,此方法将阻止,
//read方法的返回值为char字符对应的ascII码,如果返回-1,表示读取完毕
while ((readData=fileInputStream.read())!=-1){
//将ascII转成字符
char chr = ((char) readData);
stringBuffer.append(chr);
System.out.println(chr);
}
System.out.println(stringBuffer);
} catch (IOException e) {
e.printStackTrace();
}finally {
//输入流作为系统的资源,一定要记得关闭
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//使用byte数组方式读取文件内容read(byte[] b)
@Test
public void readFile02(){
String filePath = "f:\\hello.txt";
int readLen= 0;
//一次性读取8个字节
byte[] buff= new byte[8];
StringBuffer stringBuffer = new StringBuffer();
FileInputStream fileInputStream=null;
try {
fileInputStream = new FileInputStream(filePath);
//该方法一次性读取最多buff.length的数据,返回值为每次实际读取到的字节数,如果到达末尾,返回-1
while ((readLen=fileInputStream.read(buff))!=-1){
//这里需要注意,以后读取的时候有字符的话buff里的字符会依次被替换,如果没有字符,将保留上一次读取的字符
//所以不能用buff.length来构建String
String str = new String(buff, 0, readLen);
System.out.println(str);
stringBuffer.append(str);
}
System.out.println(stringBuffer);
} catch (IOException e) {
e.printStackTrace();
}finally {
//输入流作为系统的资源,一定要记得关闭
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3、OutputStream
3.1、FileOutputStream 字节输出流
package com.francis.outputstream;
import org.junit.jupiter.api.Test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author Francis
* @create 2021-11-18 21:51
*/
public class FileOutputStream_ {
/**
* 将数据写入文件
* 如果该文件不存在,则创建该文件
*/
@Test
public void fileWrite(){
String filePath = "f:\\write1.txt";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream= new FileOutputStream(filePath);
//写入一个字节
//fileOutputStream.write('F');
//写入字符串
String hello = "hello Beijing";
byte[] buff = hello.getBytes();
fileOutputStream.write(buff);
/*
write(byte[] b,int off,int len),方法,指定从byte数组中off位置开始,写入len长度个字节
*/
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 上面的方式写入到文件会覆盖原来文件的内容,如果想要对已存在文件进行追加操作
* 可以调用FileOutputStream的另外一个构造器来使该字节输出流完成该功能
*/
@Test
public void fileWriteAppend(){
String filePath = "f:\\write1.txt";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream= new FileOutputStream(filePath,true);
//写入一个字节
//fileOutputStream.write('F');
//写入字符串
String hello = "hello Beijing";
byte[] buff = hello.getBytes();
fileOutputStream.write(buff);
/*
write(byte[] b,int off,int len),方法,指定从byte数组中off位置开始,写入len长度个字节
*/
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
输入流输出流配合案例:文件拷贝
package com.francis.outputstream;
import org.junit.jupiter.api.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author Francis
* @create 2021-11-18 22:29
*/
public class FileCopy {
@Test
public void copyJpg(){
String srcFile="f:\\1.jpg";
String destFile="f:\\3.jpg";
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
byte[] buff = new byte[1024];
int dataLen = 0;
int times = 0;
try {
fileInputStream=new FileInputStream(srcFile);
fileOutputStream = new FileOutputStream(destFile,true);
while ((dataLen= fileInputStream.read(buff))!=-1){
times++;
System.out.println(times);
fileOutputStream.write(buff,0,dataLen);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
}
4、Reader
4.1、FileReader
相关方法
(1)构造器new FileReader(File/String)
(2)read,每次读取单个字符,返回该字符,如果到文件末尾,返回-1
(3)read(char[]) 批量读取多个字符数组,返回读取到的字符数,如果到达文件末尾,返回-1
相关API
(1)new String(char[]) 将char[]数组转成String
(2)new String (char[],off,len)将char[]的指定部分转成String
package com.francis.reader;
import org.junit.jupiter.api.Test;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* @author Francis
* @create 2021-11-19 21:10
*/
public class FileReader_ {
//每次读取一个字符
@Test
public void readFile1() {
String filePath = "f:\\story.txt";
FileReader fileReader = null;
int data =0;
try {
fileReader = new FileReader(filePath);
while((data=fileReader.read())!=-1){
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//每次读取一个字符数组
@Test
public void readFile2() {
String filePath = "f:\\story.txt";
FileReader fileReader = null;
char[] buff = new char[8];
int dataLen =0;
try {
fileReader = new FileReader(filePath);
System.out.println("使用char数组读取");
while((dataLen=fileReader.read(buff))!=-1){
System.out.print(new String(buff,0,dataLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5、Writer
5.1、FileWriter
相关方法
(1)new FileWriter(File/String),覆盖模式,相当于流的指针在首端
(2)new FileWriter(File/String,true)追加模式,相当于流的指针在末端
(3)write(),写入单个字符,
(4)write(char[] ) 写入指定字符数组
(5)write(char[],off,len)写入指定数组的指定部分
(6)write(String) 写入整个字符串
(7)write(String,off,len)写入字符串的指定部分
相关API
(1)String类:toCharArray(),将String转换成char[]
注意
FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定文件
package com.francis.writer;
import org.junit.jupiter.api.Test;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author Francis
* @create 2021-11-19 22:05
*/
public class FileWriter_ {
/**
* 单个字符写出
*/
@Test
public void writeFile1() {
String filePath = "f:\\note.txt";
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(filePath);
fileWriter.write('H');
fileWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 写入字符数组
*/
@Test
public void writeFile2() {
String filePath = "f:\\note.txt";
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(filePath);
char[] chars = "hello world2".toCharArray();
fileWriter.write(chars);
fileWriter.flush();
System.out.println("写入成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 写入字符数组的指定长度字符
*/
@Test
public void writeFile3() {
String filePath = "f:\\note.txt";
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(filePath);
char[] chars = "hello world3".toCharArray();
fileWriter.write(chars, 0, 5);
fileWriter.flush();
System.out.println("写入成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 写入整个字符串
*/
@Test
public void writeFile4() {
String filePath = "f:\\note.txt";
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(filePath);
String str = "hello world4";
fileWriter.write(str);
fileWriter.flush();
System.out.println("写入成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 写入指定字符串的指定长度
*/
@Test
public void writeFile5() {
String filePath = "f:\\note.txt";
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(filePath);
String str = "hello world5";
fileWriter.write(str, 0, 5);
fileWriter.flush();
System.out.println("写入成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 追加模式写入文件
*/
@Test
public void writeFile6() {
String filePath = "f:\\note.txt";
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(filePath, true);
String str = "hello world6";
fileWriter.write(str);
fileWriter.flush();
System.out.println("写入成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6、节点流和处理流
6.1、基本介绍
(1)节点流可以从一个特定的数据源读取数据,如FileReader、FileWriter
(2)处理流也叫包装流,是“连接”已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,也更加灵活,如BufferReader、BufferWriter
6.2、节点流和处理流的区别和联系
(1)节点流是底层流/低级流,直接跟数据源相接
(2)处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出
(3)处理流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连
处理流的功能主要提现在以下两个方面
(1)性能的提高:主要以增加缓冲的方式来提高输入输出的效率
(2)便捷的操作:处理流可能提供了便捷的方法来一次性输入输出大批量的数据,使用更加灵活便捷
6.3、处理流-BufferedReader 和 BufferedWriter
BufferedReader 和 BufferedWriter属于字符处理流,是按照字符来读取数据的,关闭处理流时,只需要关闭外层流即可。这是因为在关闭处理流时,底层会调用节点流的close方法。
package com.francis.writer;
import org.junit.jupiter.api.Test;
import java.io.*;
/**
* @author Francis
* @create 2021-11-23 23:12
*/
public class BufferedCopy {
@Test
public void copy(){
String srcFile = "f:\\story.txt";
String destFile = "f:\\story2.txt";
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
bufferedReader = new BufferedReader(new FileReader(srcFile));
bufferedWriter= new BufferedWriter(new FileWriter(destFile,true));
String line ;
while ((line=bufferedReader.readLine())!=null){
bufferedWriter.write(line);
System.out.println(line);
bufferedWriter.newLine();
}
//与fileWriter一样,需要flush或者close文件才会真正的被写入内容
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bufferedReader.close();
//bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6.4、处理流-BufferedInputStream 和 BufferedOutputStream
BufferedInputStream 是字节处理流,在创建BufferedInputStream 时,会创建一个内存缓冲区数组;BufferedOutputStream也是字节处理流,可以将多个字节写入到底层输出流中,而不必对每次字节写入调用底层系统。
package com.francis.outputstream;
import org.junit.jupiter.api.Test;
import java.io.*;
/**
* 拷贝二进制文件
*
* @author Francis
* @create 2021-11-23 23:42
*/
public class BufferedCopy {
@Test
public void copy() {
String srcFile = "f:\\1.avi";
String destFile = "f:\\2.avi";
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFile));
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(destFile));
byte[] buffer = new byte[1024];
int readLen= 0;
while ((readLen =bufferedInputStream.read(buffer))!=-1){
bufferedOutputStream.write(buffer, 0, readLen);
}
System.out.println("拷贝成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(bufferedInputStream!=null){
bufferedInputStream.close();
}
if(bufferedOutputStream!=null){
bufferedOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6.5、对象处理流-ObjectInputStream 和 ObjectOutputStream
当我们需要把一个数据及其类型保存到文件中,并且可以从文件中回复该数据及其类型,这时我们需要使用到对象流
序列化和反序列化
(1)序列化就是在保存数据时,不仅保存数据本身,还要保存数据的类型
(2)反序列化就是在恢复数据时,不仅要恢复数据的值,还要恢复数据的类型
(3)需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一
①Serializable,这是一个标记接口,没有方法需要实现
②Externalizable,该接口有一个方法需要实现,因此我们一般实现上面的Serializable接口
对象流介绍
功能:提供了对基本类型或对象类型的序列化和反序列化的方法
ObjectOutputStream 提供 序列化功能
package com.francis.outputstream;
import org.junit.jupiter.api.Test;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 演示ObjectOutputStream的使用
* @author Francis
* @create 2021-11-24 20:09
*/
public class ObjectOutputStream_ {
@Test
public void writeObject() throws IOException {
//这里的文件后缀名是随便写的,保存之后的文件并不是纯文本文件,而是有特殊的格式,就算写成txt也不是文本文件
//String filePath = "f:\\object.txt";
String filePath = "f:\\object.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//基本数据类型会自动装箱,并且根据方法的名字,就可以推测,保存的类型是什么
oos.writeInt(100);
oos.writeBoolean(true);
oos.writeChar('a');
oos.writeDouble(2.1);
oos.writeFloat(1.2f);
oos.writeUTF("我爱你中国");
Dog dog1 = new Dog("黄色","小黄",1,"中国");
Dog dog2 = new Dog("黑色","小黑",2,"中国");
//如果对象没有实现序列化接口,会抛异常
oos.writeObject(dog1);
oos.writeObject(dog2);
oos.close();
}
}
package com.francis.outputstream;
import java.io.Serializable;
/**
* @author Francis
* @create 2021-11-24 20:56
*/
public class Dog implements Serializable {
//提高兼容性,当某天新增了一个属性,jvm不会认为是新的类,而是升级版
private static final long serialVersionUID = 1L;
//这两个属性不会被序列化,可以在反序列化时输出验证
private static String nation ;
private transient String color;
private String name;
private int age;
public Dog(String color, String name, int age,String nation) {
this.color = color;
this.name = name;
this.age = age;
this.nation = nation;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"color='" + color + '\'' +
", name='" + name + '\'' +
", age=" + age +
", nation=" + nation +
'}';
}
}
ObjectInputStream 提供 反序列化功能
package com.francis.inputstream;
import com.francis.outputstream.Dog;
import org.junit.jupiter.api.Test;
import java.io.*;
/**
* @author Francis
* @create 2021-11-24 20:31
*/
public class ObjectInputStream_ {
@Test
public void parseObject() throws IOException, ClassNotFoundException {
String filePath = "f:\\object.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
//反序列化的顺序要跟序列化的顺序保持一致
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readFloat());
System.out.println(ois.readUTF());
//读取对象时可能存在类型转换异常
Dog dog1 =(Dog) ois.readObject();
Dog dog2 =(Dog) ois.readObject();
System.out.println(dog2.getName());
//如果我们需要调用dog的方法,我们就需要向下转型,得保证在反序列化的
//环境下也存在Dog类,并且包名也要相同,特别是客户端和服务端的时候,并不在同一个系统下时
//要注意,这里我们就直接引用output包下的即可
System.out.println(dog1);
System.out.println(dog2);
ois.close();
}
}
注意事项和细节说明
(1)在反序列化时,顺序要与序列化时保持一致
(2)要求反序列化和序列化的对象需要实现两个序列化接口的其中一个,一般我们实现Serializable
(3)序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性private static final long serialVersionUID = 1L;
(4)序列化对象时,默认将对象里的所有属性都进行序列化,但除了static或transient修饰的成员
(5)序列化对象时,要求里面属性的类型也需要实现序列化接口
(6)序列化具备可继承性,也就是某类已经实现了序列化,则它的所有子类也默认实现了序列化
6.6、标准输入输出流
System.in 标准输入流 默认设备时键盘
System.out 标准输出流 默认设备时显示器
package com.francis.standard;
import org.junit.jupiter.api.Test;
import java.util.Scanner;
/**
* @author Francis
* @create 2021-11-24 22:05
*/
public class InputAndOutput {
public static void main(String[] args) {
//System.in的编译类型是public final static InputStream in = null;
//System.ind的运行类型是BufferedInputStream,标准输入表示的就是键盘
System.out.println(System.in.getClass());
//System.out的编译类型是public final static PrintStream out = null;
//System.out的运行类型PrintStream,标准输出表示的就是输出到键盘上
System.out.println(System.out.getClass());
//scanner每次回去处理流bufferedInputStream的缓冲区中去获取数据
Scanner scanner = new Scanner(System.in);
System.out.println("请输入内容");
String next = scanner.next();
System.out.println(next);
}
}
6.7、转换流处理流-InputStreamReader 和 OutputStreamWriter
乱码问题
package com.francis.transformation;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/**
* @author Francis
* @create 2021-11-24 22:25
*/
public class CodeQuestion {
public static void main(String[] args) throws IOException {
//读取 f:\\a.txt 文件到程序
//1. 创建字符输入流 BufferedReader [处理流]
//2. 使用 BufferedReader 对象读取 a.txt
//3. 默认情况下,读取文件是按照 utf-8 编码
String filePath = "f:\\a.txt";
BufferedReader br = new BufferedReader(new FileReader(filePath));
String s = br.readLine();
//编码格式不统一,会出现中文乱码
System.out.println("读取到的内容: " + s);
br.close();
//InputStreamReader
//OutputStreamWriter
}
}
(1)InputStreamReader 是Reader的子类,可以将InputStream(字节流)转换成Reader(字符流)
(2)OutputStreamWriter是Writer的子类,可以将OutputStream(字节流)转换成Writer(字符流)
(3)当处理纯文本数据时,使用字符流效率更高,并且可以有效解决中文乱码问题,所以建议将字节流转换成字符流
(4)字符装换流可以在使用时指定编码格式(utf-8,gbk,gb2312,ISO8859-1)
package com.francis.transformation;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @author Francis
* @create 2021-11-24 22:52
*/
public class InputStreamReader_ {
public static void main(String[] args) throws IOException {
String filePath = "f:\\a.txt";
//1. 把 FileInputStream 转成 InputStreamReader
//2. 指定编码 UTF-8
//InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "UTF-8");
//3. 把 InputStreamReader 传入 BufferedReader
//BufferedReader br = new BufferedReader(isr);
//将 2 和 3 合在一起
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(filePath), "UTF-8"));
//4. 读取
String s = br.readLine();
System.out.println(s);
//5. 关闭外层流
br.close();
}
}
6.8、打印处理流-PrintStream 和 PrintWriter
package com.francis.printstream;
import java.io.PrintStream;
/**
* @author Francis
* @create 2021-11-25 22:35
*/
public class PrintStream_ {
public static void main(String[] args) throws Exception {
PrintStream out = System.out;
//在默认情况下,PrintStream 输出数据的位置是 标准输出,即显示器
/*
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
*/
out.print("hello,world");
//因为 print 底层使用的是 write , 所以我们可以直接调用 write 进行打印/输出
out.write("同一个世界,同一个梦想".getBytes());
out.close();
//我们可以去修改打印流输出的位置/设备
//1. 输出修改成到 "f:\\f1.txt"
//2. "hello, 韩顺平教育~" 就会输出到f:\f1.txt
//3. public static void setOut(PrintStream out) {
// checkIO();
// setOut0(out); // native 方法,修改了 out
// }
System.setOut(new PrintStream("f:\\f1.txt"));
System.out.println("北京欢迎你");
}
}
package com.francis.printstream;
import java.io.FileWriter;
import java.io.PrintWriter;
/**
* 演示PrintWriter的使用
*
* @author Francis
* @create 2021-11-25 22:58
*/
public class PrintWriter_ {
public static void main(String[] args) throws Exception{
//PrintWriter printWriter = new PrintWriter(System.out);
PrintWriter printWriter = new PrintWriter(new FileWriter("f:\\f2.txt"));
printWriter.print("hi, 北京你好~~~~");
printWriter.close();//flush + 关闭流, 才会将数据写入到文件..
}
}
7、Properties 类
7.1、基本介绍
(1)专门用于读取配置文件的集合类
配置文件的格式:
键=值
(2)注意,键值对不需要有空格,值不需要使用引号默认类型是String
(3)Properties的常见方法
①load加载配置文件的键值对到Properties对象
②将数据显示到指定设备
③getPRoperty(key)根据键获取值
④store将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果还有中文,保存的是unicode码
package com.francis.properties;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
/**
* @author Francis
* @create 2021-11-25 23:51
*/
public class Properties02 {
public static void main(String[] args) throws IOException {
//使用 Properties 类来读取 mysql.properties 文件
String filePath = "F:\\DevWorkspace\\code\\exercises\\JavaSE" +
"\\chapter19\\src\\mysql.properties";
//1. 创建 Properties 对象
Properties properties = new Properties();
//2. 加载指定配置文件
properties.load(new FileReader(filePath));
//3. 把 k-v 显示控制台
properties.list(System.out);
//4. 根据 key 获取对应的值
String user = properties.getProperty("username");
String pwd = properties.getProperty("password");
System.out.println("用户名=" + user);
System.out.println("密码是=" + pwd);
}
}
package com.francis.properties;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
/**
* @author Francis
* @create 2021-11-25 23:56
*/
public class Properties03 {
public static void main(String[] args) throws IOException {
//使用 Properties 类来创建 配置文件, 修改配置文件内容
Properties properties = new Properties();
//创建
//1.如果该文件没有 key 就是创建
//2.如果该文件有 key ,就是修改
/*
Properties 父类是 Hashtable , 底层就是 Hashtable 核心方法
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable. Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;//如果 key 存在,就替换
return old;
}
}
addEntry(hash, key, value, index);//如果是新 k, 就 addEntry
return null;
}
*/
properties.setProperty("charset", "utf8");
properties.setProperty("user", "汤姆");//注意保存时,是中文的 unicode 码值
properties.setProperty("pwd", "888888");
//将 k-v 存储文件中即可
properties.store(new FileOutputStream("F:\\DevWorkspace\\code\\exercises\\JavaSE" +
"\\chapter19\\src\\mysql.properties"),
null);
System.out.println("保存配置文件成功~");
}
}