IO流
IO流概述
- IO 输入/输出(Input/Output)
- 流:是一种抽象概念,是对数据传输的总称,也就是说数据在设备间的传输称之为“流”。流的本质是传输数据
- IO流就是用来处理设备间数据传输的问题
- 按数据的流向:
- 输入流:读数据
- 输出流:写数据
- 按数据类型:一般情况下按数据类型分类
- 字节流
- 字节输入流
- 字节输出流
- 字符流
- 字符输入流
- 字符输出流
- 字节流
- 如果将一个文件以txt方式打开,没有出现乱码就用字节流,如果出现乱码或者不知道该用什么就用字符流
File
File类的概述
File:它是文件和目录路径名的抽象表示
- 文件和目录是可以被File封装成对象的
- 对于File而言,其封装的并不是一个真正存在的文件,仅仅只是一个路径而已,它可以是存在的,也可以是不存在的,将来要是通过具体的操作把这个路径内容转换为具体的存在
File类的构造方法
File类的创建方法
File类的判断和获取方法
File的删除方法
递归
**概述:**以编程的角度来看,递归指的是方法定义中调用方法本身的现象
递归解决问题思路:
把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解决问题过程所需要的多次重复计算
具体代码实现:
/*
求第20个月的兔子对数
每个月的兔子对数:1,1,2,3,5,8
*/
public class FileDemo03 {
public static void main(String[] args) {
System.out.println(f(20));
}
//分析:第3个月开始兔子对数是前2个月对数的相加
//先定义一个方法f(n) n表示第n个月的兔子对数
//n = (n-1) + (n - 2);
public static int f(int n){
if (n == 1 || n == 2){
return 1;
} else {
return f(n - 1) + f(n - 2);
}
}
}
字节流
字节流抽象基类
- InputStream:这个抽象类是表示所有输入流的超类
- OutputStream:这个抽象类是表示所有输出流的超类
字节流写数据
FileOutputStream 文件输出流用于将数据写入File
- FileOutputStream(String name) 创建文件输出流以指定的名称写入文件
使用字节输出流写数据的步骤
- 创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流指向文件)
- 调用字节数出流写数据的方法
- 释放资源
public class FileOutputStreamDemo01 {
public static void main(String[] args) throws IOException {
//1.创建字节输出流的对象指向文件
FileOutputStream f = new FileOutputStream("D:\\123.txt");
//2.添加数据
f.write(97);
//3.释放资源
f.close();
}
}
字节流写数据的三种方法:
public class FileOutputStreamDemo02 {
public static void main(String[] args) throws IOException {
FileOutputStream f = new FileOutputStream("IO\\FileOutputStreamDemo02.txt");
f.write(97);
f.write(98);
f.write(99);
f.write(100);
f.write(101);
byte[] bytes = "神圣兽国游尾郡窝窝乡独行族妖侠".getBytes();
f.write(bytes);
f.write(bytes,0,3);
}
}
字节流写数据的两个小问题
- 字节流写数据如何实现换行呢?
window:\r\n
linux:\r
max:\n - 字节流写数据如何实现追加写入呢?
FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。
如果第二个参数为true,那么将会在文件的末尾加入
字节流读数据(一次读一个字节数据)
需求:把文件中的内容读取出来,在控制台输出
FileInputStream:从文件系统中的文件获取输入字节
FileInputStream(String name) :通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
使用字节输入流读取数据的步骤:
①创建字节输入流对象
②调用字节输入流对象的读数据方法
③释放资源
public class FileInputStreamDemo01 {
public static void main(String[] args) throws IOException {
FileInputStream f = new FileInputStream("IO\\FileOutputStreamDemo02.txt");
int r;
while ((r = f.read()) != -1){
System.out.print((char)r);
}
f.close();
}
字节流读数据(一次读一个字节数组的数据)
public static void main(String[] args) throws IOException {
FileInputStream f = new FileInputStream("IO\\春风.txt");
byte [] bys = new byte[1024];//长度一般为1024级其整数倍
int len;
while ((len = f.read(bys)) != -1){
System.out.println(new String(bys,0,len));
}
f.close();
}
}
字符流
为什么会出现字符流
由于字节流操作中文不是特别的方便,所有java就提供了字符流
字符流 = 字节流 + 编码表
字符串中的编码解码问题
- 编码
- byte[] getBytes():使用平台默认的字符集将String编码为一系列字节
- byte[] getBytes(String charsetName):使用指定的字符集将String编码为一系列字节
- 解码
- String(byte[] bytes):通过平台默认的字符集解码指定的字节数组来构造新的String
- String(byte[] bytes,String charsetName):通过指定的字符集解码指定的字节数组来构造新的String
字符流中的编码解码问题
- 字符流抽象基类
- Reader:字符输入流的抽象类
- Writer:字符输出流的抽象类
- 字符流中的编码解码问题的两个相关实现类
- InputStreamReader:读数据
- OutputStreamWriter:写数据
字符流写数据的方法
字符流读数据的方法
特殊操作流
字节缓冲流
- 字节缓冲流、
- BufferedOutputStream:该类实现缓冲输出流,通过设置这样的输出流,应用可以向底层输入流写入字节,而不必为了写入每个字节都导致底层系统的调用
- BufferedInputStream:创建一个内部缓冲区数组。当从流中读取或掉过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节。
- 构造方法
- 字节缓冲输出流:BufferedOutputStream(OutputStream out)
- 字节缓冲输入流:BufferedInputStream(InputStream)
- 为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?
- 字节缓冲流仅仅提供缓冲区,而真正的读写数据害的依靠基本的字节流对象进行操作
字符缓冲流
- 字符缓冲流
- BufferedWriter:将文本写入字符输出流,缓冲字符。以提供单个字符,将数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小,默认值足够大,可用于大多数用途
- BufferedReader:将文本写入字符输入流,缓冲字符。以提供字符,将数组和行的高效读取,可以指定缓冲区大小,或者可以接受默认大小,默认值足够大,可用于大多数用途
字符缓冲流的特有功能:
- BufferedWriter:
- void newLine():写一行行分隔符,行分割符字符串由系统属性定义
- BufferedReader:
- public String readLine():读一行文字。结果包含行的内容的字符串,不包括任何行为终止字符,如果流的结尾已到达,则为null
标准输入输出流
System 类中有两个静态的成员常量
- public static final inputStream in:标准输入流,通常该流用于键盘输入或主机环境或用户指定的一个输入源
- public static final inputStream in:标准输出流,通常该流用于显示输出或主机环境或用户指定的一个输出目标
打印流
打印流分类:
- 字节打印流:PrintStream
- 字符打印流:PrintWriter
打印流的特点:
- 只负责输出数据,不负责读取数据
- 有自己独特的方法
字节打印流:
- PrintStream(String fileName):使用指定的文件名创建新的打印流
- 使用继承父类的方法写数据,查看的时候会转码;使用字节的特有方法写数据,查看的数据原样输出
字符打印流:
- PrintWriter(Writer out, boolean autoFlush) :创建新 PrintWriter自动刷新
对象序列化流
对象序列化流:ObjectOutputStream
- 将Java对象的原始化数据类型和图形写入OutputStream,可以使用ObjectInputStream读取(重构)对象,可以通过使用流的文件来实现对象的持久储存,如果是网络套接字流,则可以在另一个主机或另一个进程中重构对象
构造方法:
- ObjectOutputStream(OutputStream out):创建一个写入指定OutputStream的ObjectOutputStream
序列化对象的方法:
- void writeObject(Object obj):将指定的对象写入ObjectOutputStream
ps:实例化对象的类要继承SeriaLizable接口
对象反序列化流
对象反序列化流:ObjectInputStream
- ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
构造方法:
- ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
反序列化对象的方法:
- Object readObject():从ObjectInputStream读取一个对象
对象序列化流常见问题
- 用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
- 会出问题,会抛出InvalidClassException异常
- 如果出问题了,如何给对象解决呢?
- 给对象所属的类加一个serialVersionUID,如:private static final long serialVersionUID = 42L;
- 如果一个对象中的某个成员遍历的值不想被序列化,又该如何实现呢?
- 给改成员遍历家transient关键字修饰,该关键字标记的成员变量不参与序列化过程
Properties
概述:Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
Properties的特有方法:
Properties和IO流相结合的方法: