简介
文件,对我们并不陌生,文件是保存数据的地方,比如大家经常使用的word文档,txt文
件,excel文件 ... 都是文件。它既可以保存一张图片,也可以保持视频,声音 ….
文件流
常用的文件操作
创建文件的对象相关构造器和方法
示范
方式一:
方式二:
老师演示:
获取文件的相关信息的方法
示范
老师演示
目录的操作以及文件的删除
示范
老师示范
创建多级目录
IO流原理及流的分类
原理
- I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等。
- Java程序中,对于数据的输入/输出操作以”流(stream)”的方式进行。
- java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
- 输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
- 输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中
流的分类
- 按操作数据单位不同分为:字节流(8 bit),字符流(按字符)
- 按数据流的流向不同分为:输入流,输出流
- 按流的角色的不同分为:节点流,处理流/包装流
- Java的IO流共涉及40多个类,实际上非常规则,都是从如上4个抽象基类派生的。
由这四个类派生出来的子类名称都是以其父类名作为子类名后缀
IO流体系图-常用的类
InputStream:字节输入流
InputStream抽象类是所有类字节输入流的超类
InputStream 常用的子类:
关系图:
FilelnputStream:文件输入流
FilelnputStream构造器以及方法摘要
read()方法详解
//字母占一个字节,但是一个汉字占三个字节。这样一个字节一个字节的读取会导致汉字乱码
一个一个字节读效率太低,所以就要用到read(byte[]b),自己指定一次读取几个字节,输出时,新建一个String其目的是将其转换成一个字符串打印出来,调用了这个构造器是代表通过使用平台的默认字符集对指定的字节子数组进行解码,构造一个新的字符串。新字符串的长度是字符集的函数,因此可能不等于子数组的长度。如果不用readata就会超过我们所有的字节数。
read(byte[]b)方法详解
该方法的返回值
老师示范
BufferedlnputStream:缓冲字节输入流
ObjectlnputStream:对象字节输入流
OutputStream:字节输出流
OutputStream 常用的子类:
FileOutputStream构造器以及方法摘要:
关系图:
常用的write方法
示范
构造器详解
示范
老师示范
文件拷贝
示范
老师示范
字符流
FileReader和 FileWriter 是字符流,即按照字符来操作io
FileReader相关方法:
- new FileReader(File/String)
- read:每次读取单个字符,返回该字符,如果到文件末尾返回-1
- read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1
- 相关API:
- new String(char[]):将char[]转换成String
- new String(char[],off,len):将char[]的指定部分转换成String
关系图:
示范:
老师示范:
FileWriter常用方法
- new FileWriter(File/String):覆盖模式,相当于流的指针在首端
- new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
- write(int):写入单个字符
- write(char[]):写入指定数组
- write(char[],off,len):写入指定数组的指定部分
- write(string):写入整个字符串
- write(string,off,len):写入字符串的指定部分
相关API:String类:toCharArray:将String转换成char[]
注意::
FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文生爱相
关系图:
示范:
追加添加
节点流和处理流
基本介绍
节点流和处理流一览图
关系图:
代表BufferWriter也是可以封装writer的子类
节点流和处理流的区别以及联系
处理流-BufferedReader和BufferedWriter(字符流)
关系图:
示范
处理流BufferredInputStream(字节流)
BufferedInputStream是字节流,在创建 BufferedlnputStream时,会创建一个内部缓冲区数组.
构造器以及方法摘要
关系图:
父类及自己有的方法和属性,可以看到,BufferredInputStream的直接父类构造器有可传BufferredInputStream的直接父类的父类。并且BufferredInputStream自身也有,这代表他们都可以接收父类InputStream对象
输出的也是如此
示范:
老师示范:
对象流Object Input Stream和ObjectOutputStream
序列化和反序列化
- 序列化就是在保存数据时,保存数据的值和数据类型
- 反序列化就是在恢复数据时,恢复数据的值和数据类型
- 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的
- 类必须实现如下两个接口之一:
- >Serializable //这是一个标记接口,没有方法,
- >Externalizable//该接口有方法需要实现,因此我们一般实现上面的 Serializable接口
图解:
基本介绍
- ObjectInputStream提供序列化功能
- ObjectOutputStream提供反序列化功能
关系图:
都有相应的参数为outputstream/Inputstream这个父类的类型参数的构造器,而FileOutputStream/FileInputStream也为outputstream/Inputstream的子类,所以,ObjectInputStream和InputStream构造器也可以接收FileOutputStream/FileInputStream对象
抽象类
Integer类也是实现了
- >Serializable //这是一个标记接口,没有方法,
- >Externalizable//该接口有方法需要实现,因此我们一般实现上面的 Serializable接口
这两接口其中的Serializable,所以也是可以被序列化
当我们没有给dog类应用Serializable和Externalizable其中一个串口,则运行后会报错,无法去实例化。
注意:每个类型的实例化write方法都不一样,创建的一个类是
writeObject(),Bloolean类的是writeBoolean(),Char的是writeChar(),小数点的是writeDouble(),字符串的是writeUtF()等等
老师示范:
这个类型一定也要实现这两个其中一个接口
示范:
同样,反序列化的read各个类型也有所不同,规律跟序列化一样,如图:
注意事项和细节说明
- 读写顺序要一致
- 要求实现序列化或反序列化对象,需要 实现 Serializable
- 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
- 序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
- 序列化对象时,要求里面属性的类型也需要实现序列化接口
- 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化
详解1:
序列化时,是先序列化dog类的,当反序列化时,不是先反序列化dog类则直接报错
其他详解
你加了版本号,那么就算你更改了Dog类比如,新增属性,也只会觉得是该类的升级版本。
当属性有Static和transient修饰时,序列化时,有这两属性的就不会被序列化,也就是说无法得到这两信息
这个类没有实现接口。那么就无法实现序列化,就导致整个dog类都无法实现从而报错
标准输入流输出流
转换流
InputStreamReader 和 OutputStreamWriter
介绍
- InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成Reader(字符流)
- OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)
- 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流
- 可以在使用时指定编码格式(比如 utf-8,gbk,gb2312,ISO8859-1等)
字节流可以转换成字符流,在转换之前可以改变编码
关系图:
值得一提的是,
FileInputStream/FileOutputStream为InputStream/OutputStream的子类,也就是说,可以指定要处理的编码,又FileInputStream/FileOutputStream为字节流,且BufferedReader和BufferedWriter与InputStreamReader 和 OutputStreamWriter同为Reader和Writer的子类,BufferedReader和BufferedWriter有构造器的参数为Reader/Writer,所以可以将通过InputStreamReader/OutputStreamWriter转换好编码的字节类数据包装成BufferedReader和BufferedWriter字符类,也就是说下列样式成立。
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("需要转码的文件路径","需要转的编码类型");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
注意:虽然InputStreamReader/OutputStreamWriter本来就为字符类,但是他没有BufferedReader和BufferedWriter的一些便捷的方法,比如readLine(),newLine(),所以如果需要实现类似功能,可以包装成BufferedReader和BufferedWriter
示例:
老师示例
也可融合一句话写
打印流-PrintStream和PrintWriter(只有输入流无输出流)
关系图:
示范:
老师示范:
getBytes是将一个String类型的字符串中包含的字符转换成byte类型并且存入一个byte[]数组中
因为,Print Writer的构造器有接收Writer类的构造器,而FileWriter又为Writer的子类,所以可以创建个显示打印的文件。
Properties类
引入
传统方法读取:如果数据多了就很麻烦,如果指定得到一个值,还要加判断
基本介绍
示例:
在实现此过程遇到小插曲,地址怎么也不对,可以使用
// InputStream inputStream = 该.java文件名.class.getClassLoader().getResourceAsStream("需要获取的文件名及其后缀"); // properties.load(inputStream);来获取地址,在debug的时候可以查看到具体地址是什么
修改内容
代表注解注释,当加了注释,非null时
就会在开头加一句传入的注释
package com.File.test01;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
在判断d盘下是否有文件夹mytemp,如果没有就创建mytemp
在d:\\mytemp 目录下,创建文件 hello.txt
如果hello.txt 已经存在,提示该文件已经存在,就不要再重复创建了
*/public class Tets01 {
public static void main(String[] args) throws IOException {
String pathname="d:\\mytemp";
File file = new File(pathname);
if (file.exists())
System.out.println("已存在");
else
{
file.mkdir();
String file02="d:\\mytemp\\hello.txt";
File file1 = new File(file02);
if (file1.exists())
System.out.println("已存在");
else
file1.createNewFile();
BufferedWriter writer = new BufferedWriter(new FileWriter(file1));
writer.write("hello world!");
writer.close();
}
}
}
package com.File.test01;
import java.io.*;
/*
@author:我与java相爱相杀---c语言梦开始的地方
今天又是努力学习的一天!!!!
要求:使用BufferedReader读取一个文本文件,为每行加上行号,
再连同内容一并输出到屏幕上。
*/public class Test03 {
public static void main(String[] args) throws IOException {
// BufferedReader bufferedReader = new BufferedReader(new FileReader("d:\\mytemp\\hello.txt"));
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("d:\\mytemp\\hello.txt"), "gbk");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String Link;
int count=0;
while ((Link=bufferedReader.readLine())!=null) {
System.out.println(++count+Link);
}
bufferedReader.close();
}
}