IO流
*目前程序中数据存储在哪?
存储在JVM内存中
*目前数据存储存在问题?
临时存储,JVM一旦关闭,数据丢失
*持久化:数据从jvm内存中往其他存储设备中存储过程。
- 概念:流就是内存和存储设备之间传输数据的通道或是管道
- IO流的分类:
(1) 按照方向:[以JVM内存为参照物] 【重点】
a. 输入流:将<存储设备>中数据读取到< jvm内存>中->读操作(read)
b. 输出流:将< jvm内存>中数据写入到< 存储设备>中->写操作(write)
(2) 按照单位:
a. 字节流:以字节为单位,可以操作任意类型的文件。
b. 字符流:以字符为单位,可以操作文本类型的文件。
注意:文本类型的文件:能以记事本打开而且不乱码的文件
例如:.java / .txt / .c / .html 等文件都是文本文件
.class / .world / .ppt / .map4等非文本文件
(3) 按照功能:
a. 节点流:只具有基本的读写功能。
b. 过滤流:在节点流的基础上增强功能。
字节流
1 . 字节流父类:(抽象类)
(1) InputStream:字节输入流,对应的读操作(read)
(2) OutputStream:字节输出流,对应的操作写操作(write)
2. 字节节点流: 【重点】
(1) FileOutputStream:文件字节输出流
常见的构造方法:
① FileOutputStream fos = new FileOutputStream(“E:/test/a.txt”);
a. 参数代表:文件的路径及文件名
例如: E:/test/a.txt或是 E:\test\a.txt
如果指定文件不存在,则JVM会自动的创建文件,但是如果指定文件夹不存在,则jvm报错,错误信息为: java.io.FileNotFoundException: (系统找不到指定的路径)
b. 绝对路径:带有盘符的路径,盘符:/文件夹/文件
② FileOutputStream fos = new FileOutputStream(“a.txt”);
相对路径:默认在当前项目的根目录下查找所需要的的文件,如果有,直接使用,如果没有则jvm自动创建此文件
③ FileOutputStream fos = new FileOutputStream(“file/a.txt”);
开发时,通常在项目的根目录下创建一个文件夹,用于存储项目中操作的文件,便于管理。
④ FileOutputStream fos = new FileOutputStream(“file/a.txt”,true);
参数说明:
第一个参数:指定操作的文件路径及文件名
第二个参数:boolean,是否在原有内容进行追加 true - 不覆盖原有内容,直接追加 false - 覆盖原有内容
常用方法:
① void write(int n):将一个字节的内容写入到文件中
public class TestFileOutputStream {
public static void main(String[] args) throws IOException{
// 将 jvm数据写入 指定文件
// 1. 创建文件字节输出流对象
FileOutputStream fos = new FileOutputStream("file/a.txt");
// 2. 写操作
int a = 66;
fos.write(a);// B
fos.write(69);//E
// 3.关闭流
fos.close();
}
}
(2) FileInputStream:文件字节输入流
常用构造方法
① FileInputStream fis = new FileInputStream(“E:\Java2003\a.txt”);
参数代表:操作文件的路径及文件名,指定的文件夹及文件必须存在,否则运行报错,报错信息为: java.io.FileNotFoundException: (系 统找不到指定的文件。)
常用的方法
int read():一次性读取一个字节的内容,读取到的内容作为返回值返回,如果达到文件的尾部,则返回-1.
public class TestFileInputStream {
public static void main(String[] args) throws IOException {
// 1. 创建文件字节输入流对象
FileInputStream fis = new FileInputStream("file/a.txt");
// 读取文件中所有的内容
while(true) {
int r = fis.read();
if(r==-1) break;
System.out.println((char)r);
}
// 3. 关闭流
fis.close();
}
}
开发应用重点:文件拷贝。(文件上传与下载的实现原理)
public class TestFileCopy {
public static void main(String[] args) throws IOException {
//开始时间
long start = System.currentTimeMillis();
// 创建文件字节输入流
FileInputStream fis = new FileInputStream("file/a.txt");
// 创建文件字节输出流
FileOutputStream fos = new FileOutputStream("file/a_copy.txt");
// 读一个字节 ,写入一个字节
while(true) {
int r = fis.read();
if(r==-1) break;
fos.write(r);
}
//关闭流
fis.close();
fos.close();
//结束时间
long end = System.currentTimeMillis();
System.out.println(end-start);// ms
}
}
字节过滤流
(1) BufferedOutputStream/BufferedInputStream
a. 缓冲流,提高IO的读写效率,减少访问磁盘次数
b. 数据存储存储在缓冲区,可以通过flush方法或是close方法将缓冲区内容一次性写入到文件中,并清空缓冲区。
I. flush方法只是清空缓冲同将缓冲区的内容一次性写入到文件中, 但是流还是继续可以使用;
II. close方法关闭流的同时清空缓冲区,将缓冲区的内容一次 性的写 入到文件中,流一旦关闭不能再继续使用
注意:缓冲满的时候,将缓冲区的内容一次性写入到文件中,同时清空缓冲区。
public class TestBufferedOutputStream {
public static void main(String[] args) throws IOException {
// 1. 创建文件字节节点流(输出流) --》基础流
FileOutputStream fos = new
FileOutputStream("file/c.txt");
// 2.包装过滤流
BufferedOutputStream bos = new
BufferedOutputStream(fos);
// 3. 写操作
bos.write(65);
bos.flush();// 清空缓冲区
// 4. 关闭流
bos.close();
}
}
(2) PrintStream (输出流)
a. 缓冲流,提高IO的写的效率
b. 增强了操作基本数据类型的方法,同时还可以操作字符串
print(int n)/print(long l)/print(boolean b)/print(double d)/ print(String str) —> 不自动换行
println(int n)/println(long l)/println(boolean b)/println(double d)/ println(String str) --> 自动换行
public class TestPrintStream2 {
public static void main(String[] args) throws FileNotFoundException {
// 1. 包装过滤流:自动创建基础流
PrintStream ps = new PrintStream("file/f.txt");
// 2. 写操作
ps.println("hello");
ps.println("world");
// 3. 关闭流:外层
ps.close();
}
}
(3) ObjectOutputStream/ObjectInputStream(过滤流)
a. 增强缓冲区,提高IO读写效率
b. 增强了 操作8中基本数据类型方法
c. 对象序列化:
I. 概念:对象放在流上进行传输的过程。
II. 参与对象序列化的要求:参与对象序列化的对象对应的类必须实现 java.io.Serializable接口
III. 对象的读写操作:
void writeObject(Object obj):将指定的对象写入到文件
Object readObject():从文件中读取对象
IV. 文件达到尾部的标记:java.io.EOFException
V. 如果对象的某一个属性不想参与对象序列化,则属性前面用 transient修饰
VI. 如果参与对象序列的对象中有自定类型的属性,该属性也必须实现 java.io.Serializable接口,否则运行报错,错误信息为: java.io.NotSerializableException(不可序列化的异常)
VII. 如果参与对象序列化的是集合对象,集合对应类在JDK提供时已经实现java.io.Serializable接口,但是如果集合中存储的是自定义类型的对象,则该对应对应类必须实现 java.io.Serializable 接口。
// 对象序列化
public class TestObjectOutputStream {
public static void main(String[] args) throws IOException {
// 将创建的 Student对象写入到 file/stu.txt文件中(ObjectOutputStream)
// 1. 创建字节节点基础流
FileOutputStream fos = new FileOutputStream("file/stu.txt");
// 2. 包装过滤流
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 3.写操作
Student s = new Student("张三",38,99.0);
oos.writeObject(s);
// 4. 关闭流(关闭外层)
oos.close();
// 将文件中 对象读取并打印输出
// 1. 创建文件字节输入流
FileInputStream fis = new FileInputStream("file/stu.txt");
// 2. 包装过滤流
ObjectInputStream ois = new ObjectInputStream(fis);
// 3. 读操作
Object obj = ois.readObject();
System.out.println(obj);
// 4. 关闭流
ois.close();
}
}
public class Student implements Serializable{
private String name;
private transient Integer age;
private Double scoer;
private Address address = new Address();
public Student() {
super();
}
public Student(String name, Integer age, Double scoer) {
super();
this.name = name;
this.age = age;
this.scoer = scoer;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getScoer() {
return scoer;
}
public void setScoer(Double scoer) {
this.scoer = scoer;
}
public String toString() {
return "name=" + name + ", age=" + age + ", scoer=" + scoer ;
}
}
class Address implements Serializable{}
总结:IO流异常处理的方式
1 . 消极处理异常
外抛异常
2 . 积极处理:try…catch…finally
public class Test_01 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
String str = "helloworld";
// 文件字节输出流
fos = new FileOutputStream("file2/test.txt");
for(int i=0;i<str.length();i++) {
char c = str.charAt(i);
fos.write(c);
}
}catch(IOException e) {
e.printStackTrace();
}finally {
if(fos!=null) {
try {
fos.close();// null.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3 .积极处理:try-with-resources(自动的关闭 try() 中的资源)
public class Test_02 {
public static void main(String[] args) {
try(
FileOutputStream fos = new FileOutputStream("file/test.txt");
FileInputStream fis = new FileInputStream("file/test.txt");
) {
String str = "helloworld";
// 文件字节输出流
for(int i=0;i<str.length();i++) {
char c = str.charAt(i);
fos.write(c);
}
System.out.println("文件字节输入流将内 容读入");
while(true) {
int r = fis.read();
if(r==-1) break;
System.out.println((char)r);
}
}catch(IOException e) {
e.printStackTrace();
}
}
}