目录
4.2 ObjectOutputStream (提供反序列化功能)
(一)文件流
文件在程序中是以流的形式来操作的
流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流:数据从数据源(文件)到程序(内存)的路径
输出流:数据从程序(内存)到数据源(文件)的路径
1.1:常用的文件操作
newFile(String pathName)//根据路径构建一个File对象
newFile(File parent,String child)//根据父目录文件+子路径构建
newFile(String parent,String child)//根据父目录+子路径构建
createNewFile创建新文件
//1;根据路径构建一个File对象
String filePath="d:\\demo02.txt";
File file=new File(filePath);
try {
file.createNewFile();
System.out.println(filePath+"创建成功");
}catch (IOException e){
e.printStackTrace();
}
//2;根据父目录文件+子路径构建
File parentFile=new File("c:\\");
String filePath2="demo01.txt";
File file2=new File(parentFile,filePath2);
file2.createNewFile();
System.out.println(filePath+"创建成功");
//3,根据父目录+子路径构建
String filePath3="c:\\";
String fileName="demo01.txt";
File file3=new File(filePath3,fileName);
file3.createNewFile();
System.out.println(filePath+"创建成功");
1.2目录的操作和文件的删除
mkdir创建一级目录
mkdirs创建多级目录
delete删除空目录或文件
//删除文件
String fileName="D:\\demo01.txt";
File file = new File(fileName);
if (file.exists()){
if (file.delete());
System.out.println("文件删除成功");
}else {
System.out.println("文件不存在");
}
//删除目录,如果目录中只有一个文件,则可以直接删除,如果目录中有多个文件,要把文件全部删除才能删除目录
String filePath="D:\\demo02";
File file1 = new File(filePath);
if (file1.exists()){
if (file1.delete()){
System.out.println("文件删除成功");
}else {
System.out.println("文件不存在");
}
}
//判断多级目录c:\\demo04\\a\\b\\c是否存在,如果存在就提示存在,否则就创建
//.mkdirs()创建多级目录,.mkdir()创建单个目录
String filePath2="D:\\demo04\\a\\b\\c";
File file2 = new File(filePath2);
if (file2.exists()) {
System.out.println(filePath2 + "存在");
}else{
if(file2.mkdirs()){
System.out.println(filePath2+"文件创建成功");
}else {
System.out.println("文件创建失败");
}
}
(二)IO流
按操作数据单位不同分为:字节流(8bit),字符流(字符流)
字节输入流:InputStream 字符输入流:Reader
字节输出流:OutputStream 字符输出流:Writer
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为:节点流,处理流/包装流
2.1 FileInputStream
String filePath="D:\\demo02.txt";
FileInputStream fileInputStream=null;
//创建fileInputStream对象用于读取文件
fileInputStream=new FileInputStream(filePath);
//字节数组
byte[] buffer = new byte[1024];
int length=0;
//如果返回-1则表示读取完毕,如果读取正常,返回实际读取的字节数
while((length=fileInputStream.read(buffer))!=-1){
System.out.println(new String(buffer,0,length));
}
fileInputStream.close();
2.2 FileOutputStream
String filePath="D:\\demo02.txt";
FileOutputStream fileOutputStream=null;
//创建fileInputStream对象用于读取文件
//new FileOutputStream(filePath)创建方式:会覆盖原先的内容
//new FileOutputStream(filePath,true)创建方式:写入的内容会追加到文件后面
fileOutputStream=new FileOutputStream(filePath,true);
String str="hello world!";
//str.getBytes()可以把字符串转成字节数组
fileOutputStream.write(str.getBytes());
System.out.println("文件读写成功!");
//write(byte[] buffer,int off,int len);将len字节从位于偏移量off的指定字节数组写入此文件输出流
//fileOutputStream.write(str.getBytes(),0,3);
fileOutputStream.close();
2.3 文件拷贝
FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;
String filePath01="D:\\demo02.txt";
String filePath02="D:\\demo03.txt";
fileInputStream=new FileInputStream(filePath01);
fileInputStream.read();
fileOutputStream=new FileOutputStream(filePath02);
int length=0;
byte[] buffer = new byte[8];
while((length=fileInputStream.read(buffer))!=-1){
fileOutputStream.write(buffer,0,length);
}
System.out.println("文件拷贝成功!");
if(fileInputStream!=null){
fileInputStream.close();
}
if(fileOutputStream!=null){
fileOutputStream.close();
}
2.4 FileReader
FileReader和FileWriter是字符流,即按照字符来操作io
FileReader相关方法:
(1)new FileReader(File/String)
(2)read:每次读取单个字符,返回该字符,如果到文件末尾返回-1
(3)read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1
(4)new String(char[]):将char[]转换成String
(5)new String(char[],off,len):将char[]指定部分转换成String
String filePath="D:\\demo02.txt";
FileReader fileReader=null;
fileReader=new FileReader(filePath);
int length=0;
char[] buffer = new char[1024];
while((length=fileReader.read(buffer))!=-1){
System.out.println(new String(buffer,0,length));
}
fileReader.close();
2.5 FileWriter
FileWirter常用方法:
(1)new FileWriter(File/String):覆盖模式,相当于流的指针在顶端
(2)new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
(3)write(int):写入单个字符
(4)write(char[]):写入指定数组
(5)write(char[],off,len):写入指定数组的指定部分
(6)write(String):写入整个字符串
(7)write(string,off,len):写入字符串的指定部分
(8)toCharArray:将String转换成char[]
注意:FileWriter使用后,必须要关闭(close)或者刷新(flush),否则写入不到指定文件
String filePath="D:\\demo03.txt";
FileWriter fileWriter=null;
fileWriter=new FileWriter(filePath);
// write(int):写入单个字符
fileWriter.write("H");
// write(char[]):写入指定数组
char[] c={'A','B','C'};
fileWriter.write(c);
// write(char[],off,len):写入指定数组的指定部分
fileWriter.write("卞文正".toCharArray(),0,5);
// write(String):写入整个字符串
fileWriter.write("卞文正");
// write(string,off,len):写入字符串的指定部分
fileWriter.write("北京欢迎你",0,3);
fileWriter.close();
(三)节点流和处理流
1:节点流可以从一个特定的数据源读写数据,如FileReader,FileWriter
2:处理流也叫包装流,是连接在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader,BufferedWriter
节点流和处理流的区别和联系
1:节点流是底层流,直接跟数据源相接。
2:处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出
3:处理流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连
处理流的功能主要体现在以下两个方面:
1:性能的提高:主要以增加缓冲的方式来提高输入输出效率。
2:操作的便捷:处理流提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便。
3.1 BufferedReader
String filePath="E:\\依赖包.txt";
//按行读取readLine()
String line;
BufferedReader bufferedReader=new BufferedReader(new FileReader(filePath));
while ((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
bufferedReader.close();
3.2 BufferedWriter
String filePath="E:\\依赖包Demo.txt";
BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter(filePath));
bufferedWriter.write("Hello World!");
bufferedWriter.newLine();//插入一个换行
bufferedWriter.write("Hello World!22222");//这里没有覆盖的原因是:
// 第一次写入是创建该文家不会覆盖,在写入同名文件就会覆盖
bufferedWriter.close();
3.3 文本文件拷贝
Buffered字符处理流拷贝文本文件
String srcPath="E:\\依赖包Demo.txt";
String desPath="D:\\Demo.txt";
BufferedWriter bufferedWriter=null;
BufferedReader bufferedReader=null;
bufferedWriter=new BufferedWriter(new FileWriter(desPath));
bufferedReader=new BufferedReader(new FileReader(srcPath));
String line;
//说明:readLine读取一行内容,但是没有换行
while ((line=bufferedReader.readLine())!=null){
//每读取一行就写入
bufferedWriter.write(line);
//每读取一行就换行
bufferedWriter.newLine();
}
System.out.println("拷贝完毕");
if (bufferedReader!=null){
bufferedReader.close();
}
if (bufferedWriter!=null){
bufferedWriter.close();
}
}
Buffered字节处理流,拷贝二进制文件,也能拷贝文本文件
BufferedInputStream bufferedInputStream=null;
BufferedOutputStream bufferedOutputStream=null;
String srcFile="D:\\saber.jpg.jfif";
String desFile="D:\\saber2.jpg.jfif";
bufferedInputStream=new BufferedInputStream(new FileInputStream(srcFile));
bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(desFile));
int len=0;
byte[] buffer=new byte[1024];
while ((len=bufferedInputStream.read(buffer))!=-1){
bufferedOutputStream.write(buffer,0,len);
}
System.out.println("图片拷贝完成");
if (bufferedInputStream!=null){
bufferedInputStream.close();
}
if (bufferedOutputStream!=null){
bufferedOutputStream.close();
}
}
(四)对象处理流
序列化和反序列化
1:序列化就是在保存数据的时候,保存数据的值和数据类型
2:反序列化就是在恢复数据时,恢复数据的值和数据类型
3:需要让某个对象支持序列化,则必须让其类是可序列化的,为了让某个类可序列化,该类必须实现以下两个接口
Serializable(标记接口,没有方法) Externalizable(该接口有方法实现)
4:读写顺序要一致
5:序列化对象时,要求里面属性的类型都进行序列化,除了static或transient修饰的成员
6:序列化具有可继承性,如果某类已经实现了序列化,则他的所有子类已经默认实现了序列化
7:序列化对象时,要求里面的属性的类型也需要实现序列化接口
4.1ObjectInputStream(提供序列化功能)
public class Animal implements Serializable {
private String name;
private int age;
private String type;
public Animal(String name, int age, String type) {
this.name = name;
this.age = age;
this.type = type;
}
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;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
", type='" + type + '\'' +
'}';
}
}
public class TestObjectOutputStream_ extends Animal {
public TestObjectOutputStream_(String name, int age, String type) {
super(name, age, type);
}
public static void main(String[] args) throws IOException {
String filePath="E:\\demo.dat";
ObjectOutputStream output=new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据到"E:\\demo.dat",这些数据都自动实现Serializable接口
output.writeInt(100);//int--->Integer(实现了Serializable接口)
output.writeBoolean(true);
output.writeDouble(2.3333);
output.writeChar('a');//char---->Character
output.writeUTF("hello world");//String类型字符串
output.writeByte(8);
output.writeObject(new Animal("花花",20,"猫"));
output.writeObject(new Animal("阿黄",10,"狗狗"));
System.out.println("序列化完毕");
output.close();
}
}
4.2 ObjectOutputStream (提供反序列化功能)
public class TestObjectInputStream_ extends Animal {
public TestObjectInputStream_(String name, int age, String type) {
super(name, age, type);
}
//序列化顺序一定要和反序列化顺序一致,否则会出异常
public static void main(String[] args) throws IOException, ClassNotFoundException {
String filePath="E:\\demo.dat";
ObjectInputStream input=new ObjectInputStream(new FileInputStream(filePath));
System.out.println(input.readInt());
System.out.println(input.readBoolean());
System.out.println(input.readDouble());
System.out.println(input.readChar());
System.out.println(input.readUTF());
System.out.println(input.readByte());
Object animal=input.readObject();
System.out.println("运行类型="+animal.getClass());
System.out.println("动物信息="+animal);
//如果希望调用animal方法,需要向下转型
//需要我们将animal类的定义,拷贝到其他可以引用的位置
Animal animal1=(Animal) animal;
System.out.println(animal1.getName());
//关闭外层流即可,底层会关闭FileInputStream
input.close();
}
}
(五)转化流(解决乱码问题)
转化流InputStreamReader和OutputStreamWriter
1:InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成Reader(字符流)
2:OutputStreamWriter:wirter的子类,可以将OutputStream(字节流)包装成Writer(字符流)
3:当处理纯文本数据时,使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转化成字符流
4:可以在使用指定编码格式(utf-8,gbk,gb2312,ISO8859-1等)
5.1 InputStreamReader
//1,把FileInputStream转成InputStreamReader
//2,指定编码gbk
InputStreamReader reader=new InputStreamReader(new FileInputStream("E:\\依赖包2.txt"),"utf-8");
//3,把InputStreamReader传入BufferedReader
BufferedReader bufferedReader=new BufferedReader(reader);
//读取
//String str=bufferedReader.readLine();
//System.out.println(str);
String line;
while ((line=bufferedReader.readLine())!=null){
System.out.println(line );
}
if (bufferedReader!=null){
bufferedReader.close();
}
}
5.2 OutputStreamWriter
String charset="utf-8";
OutputStreamWriter writer=new OutputStreamWriter(new FileOutputStream(new File("E:\\依赖包3.txt")),charset);
BufferedWriter bufferedWriter=new BufferedWriter(writer);
bufferedWriter.write("hello 问问");
bufferedWriter.close();
System.out.println("按照"+charset+"文件保存成功");
(六)打印流
打印流只有输出流,没有输入流
6.1PrintStream(字节流)
PrintStream继承FilterOutputStream,FilterOutputStream继承OutputStream(字节流)
public static void main(String[] args) throws IOException {
PrintStream printStream=System.out;
//默认情况下,printStream输出数据的位置是标准输出即显示器
printStream.println("steven");
//可以使用我们写入方法,写入到标准输出,即显示器,效果一样
//write按照字节打印,而我们传入的是字符,因此调用getBytes()方法转化成字节
printStream.write("steven hello".getBytes());
//重定向输出设备到文件
//"Steven"就会输出到"D:\\demo03.txt"这个文件
System.setOut(new PrintStream("D:\\demo03.txt"));
//写入内容
System.out.println("Steven");
}
6.2PrintWriter(字符流)
public static void main(String[] args) throws IOException {
PrintWriter printWriter1=new PrintWriter(new FileWriter("D:\\demo04.txt",true));
// PrintWriter printWriter2 = new PrintWriter(new FileWriter("D:demo0.txt"));
//如果写的是System.out就是打印(输出)到默认设备显示器
printWriter1.println("hello steven");//打印(输出)到文件
printWriter1.write("hi steven");//打印(输出)到文件
//如果不关闭流close或者刷新流flush,数据就不会写进文件中
printWriter1.close();
}
(七)Properties
7.1
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new FileReader("src/com/example/xml/mysql.properties"));
String line="";
while ((line=bufferedReader.readLine())!=null) {
// System.out.println(line);
String[] split = line.split("=");
//如果我们要要求指定的ip值
// if ("ip".equals(split[0])) {
System.out.println(split[0] + "值是:" + split[1]);
// }
}
bufferedReader.close();
}
7.2Properties常用方法
load:加载配置文件的键值对到Properties对象
list:将数据显示到指定设备
getProperty(key):根据键获取值
setProperty(key,value):设置键值对到Properties对象
store将Properties中的键值对存储到配置文件,在idea中保存信息到配置文件,如果含有中文,则会存储为unicode码
@Test
public void properties02_() throws IOException {
//1:创建Properties对象
Properties properties = new Properties();
//2:加载指定配置文件
properties.load(new FileReader("src/com/example/xml/mysql.properties"));
//3:把key-value显示到控制台
properties.list(System.out);
//4:根据key获得相应的值
String user = properties.getProperty("user");
String pwd = properties.getProperty("pwd");
System.out.println("用户名=" + user);
System.out.println("密码=" + pwd);
}
1: 使用Properties类完成对properties配置的读取
2:使用Properties类添加key-value到新配置文件中
3:使用Properties类完成对Properties配置文件的读取,并修改某个key-value
@Test
public void properties03_() throws IOException {
Properties properties = new Properties();
//setProperty()方法:
//1:如果该文件没有key就是创建
//2:如果该文件有key就是修改
properties.setProperty("charset","utf-8");
properties.setProperty("user","steven");
properties.setProperty("pwd","123456");
properties.setProperty("pwd","88888888");
//将key-value存储到文件中
//store()方法的第二个参数表示注释,写在配置文件开头
properties.store(new FileOutputStream("src/com/example/xml/mysql2.properties"),null);
System.out.println("配置文件保存成功!");
}