共计 5337 个字符,预计需要花费 14 分钟才能阅读完成。
1、IO 流概述
IO 流用来处理设备之间的数据传输。例如:上传文件和下载文件
Java 对数据的操作是通过流的方式
Java 用于操作流的对象都在 IO 包中
2、IO 流分类
按照数据流向
输入流 读入数据
输出流 写出数据
按照数据类型
字节流
字符流
3、IO 流基类
字节流的抽象基类:
InputStream
OutputStream
字符流的抽象基类:
Reader
Writer
注意 :由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
如:InputStream 的子类 FileInputStream。
如:Reader 的子类 FileReader。
4、字节流写数据
OutputStream
FileOutputStream
往一个文本文件中写一句话:”helloworld”
分析发现其实更适合用字符流,但是由于字节流先出现,所以,我们考虑先使用字节流后面再讲会什么出现字符流。
FileOutputStream 的构造方法
FileOutputStream(File file)
FileOutputStream(String name)
5、字节流写数据的方式
public void write(int b)
public void write(byte[] b)
public void write(byte[] b,int off,int len)
案例一:
/*
步骤:A: 创建字节输出流对象
B: 写数据
C: 释放资源
*/
public static void main(String[] args) throws IOException {// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
/*
* 创建字节输出流对象了做了几件事情?* A: 调用系统功能去创建文件
* B: 创建 fos 对象
* C: 把 fos 对象指向这个文件
*/
// 写数据
fos.write("hello,IO".getBytes());
fos.write("java".getBytes());
// 释放资源
// 关闭此文件输出流并释放与此流有关的所有系统资源。
fos.close();
/*
* 为什么一定要 close() 呢?
* A: 让流对象变成垃圾,这样就可以被垃圾回收器回收了
* B: 通知系统去释放跟该文件相关的资源
*/
//fos.write("java".getBytes());
//java.io.IOException: Stream Closed
}
案例二
public static void main(String[] args) throws IOException {// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream("fos2.txt");
// 调用 write() 方法
//fos.write(97);
//97 -- 底层二进制数据 -- 通过记事本打开 -- 找 97 对应的字符值 -- a
// fos.write(57);
// fos.write(55);
//public void write(byte[] b): 写一个字节数组
byte[] bys={97,98,99,100,101};
fos.write(bys);
//public void write(byte[] b,int off,int len): 写一个字节数组的一部分
fos.write(bys,1,3);
// 释放资源
fos.close();}
实现数据换行
/*
不同的系统针对不同的换行符号识别是不一样的?
windows:\r\n
linux:\n
Mac:\r
*/
public static void main(String[] args) throws IOException {// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream("fos3.txt");
// 写数据
for (int x = 0; x < 10; x++) {fos.write(("hello" + x).getBytes());
fos.write("\r\n".getBytes());// 换行
}
// 释放资源
fos.close();}
实现数据的追加
public static void main(String[] args) throws IOException {// 创建一个向具有指定 name 的文件中写入数据的输出文件流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。
FileOutputStream fos = new FileOutputStream("fos3.txt", true);
// 写数据
for (int x = 0; x < 10; x++) {fos.write(("hello" + x).getBytes());
fos.write("\r\n".getBytes());
}
// 释放资源
fos.close();}
6、字节流写数据常见问题
创建字节输出流到底做了哪些事情?
数据写成功后,为什么要 close()?
如何实现数据的换行?
如何实现数据的追加写入?
7、字节流写数据加入异常处理
加入异常处理的 IO 流操作
public static void main(String[] args) {// 分开做异常处理
FileOutputStream fos = null;
try {fos = new FileOutputStream("fos4.txt");
} catch (FileNotFoundException e) {e.printStackTrace();
}
try {fos.write("java".getBytes());
} catch (IOException e) {e.printStackTrace();
}
try {fos.close();
} catch (IOException e) {e.printStackTrace();
}
}
public static void main(String[] args) {// 一起做异常处理
try {FileOutputStream fos = new FileOutputStream("fos4.txt");
fos.write("java".getBytes());
fos.close();} catch (FileNotFoundException e) {e.printStackTrace();
} catch (IOException e) {e.printStackTrace();
}
}
public static void main(String[] args) {// 改进版
// 为了在 finally 里面能够看到该对象就必须定义到外面,为了访问不出问题,还必须给初始化值
FileOutputStream fos = null;
try {fos = new FileOutputStream("fos4.txt");
fos.write("java".getBytes());
} catch (FileNotFoundException e) {e.printStackTrace();
} catch (IOException e) {e.printStackTrace();
} finally {// 如果 fos 不是 null,才需要 close()
if (fos != null) {// 为了保证 close() 一定会执行,就放到这里了
try {fos.close();
} catch (IOException e) {e.printStackTrace();
}
}
}
}
8、字节流读取数据
InputStream
FileInputStream
把写的数据读取出来显示在控制台
FileInputStream 的构造方法
FileInputStream(File file)
FileInputStream(String name)
FileInputStream 的成员方法
public int read()
public int read(byte[] b)
9、字节流读取数据的两种方式
一次读取一个字节
一次读取一个字节数组(每次可以读取多个数据,提高了操作效率)
一次读取一个字节
public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java");
// 调用 read() 方法读取数据,并把数据显示在控制台
// 第一次读取
int by = fis.read();
System.out.println(by);
System.out.println((char) by);
// 第二次读取
by = fis.read();
System.out.println(by);
System.out.println((char) by);
// 第三次读取
by = fis.read();
System.out.println(by);
System.out.println((char) by);
// 第四次读取
by = fis.read();
System.out.println(by);
// 第五次读取
by = fis.read();
System.out.println(by);
// 通过测试,我们知道如果你读取的数据是 -1,就说明已经读取到文件的末尾了
// 释放资源
fis.close();}
一次读取一个字节用循环改进
public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java");
// 调用 read() 方法读取数据,并把数据显示在控制台
// 用循环改进
int by = 0;
// 读取,赋值,判断
while ((by = fis.read()) != -1) {System.out.print((char) by);
}
// 释放资源
fis.close();}
一次读取一个字节数组
public static void main(String[] args) throws IOException {// 创建字节输入流对象
FileInputStream fis =
new FileInputStream("FileOutputStreamDemo.java");
// 读取数据
// 定义一个字节数组
// 第一次读取
byte[] bys = new byte[5];
int len = fis.read(bys);
System.out.print(new String(bys, 0, len));
// 第二次读取
len = fis.read(bys);
System.out.print(new String(bys, 0, len));
// 第三次读取
len = fis.read(bys);
System.out.print(new String(bys, 0, len));
// 第四次读取
len = fis.read(bys);
System.out.print(new String(bys, 0, len));
// 代码重复了,用循环改进
// 但是,我不知道结束条件
len = fis.read(bys);
System.out.println(len);
len = fis.read(bys);
System.out.println(len);
// 如果读取到的实际长度是 -1,就说明没有数据了
// 数组的长度一般是 1024 或者 1024 的整数倍
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {System.out.print(new String(bys, 0, len));
}
// 释放资源
fis.close();}
一次读取一个字节数组最终版
public static void main(String[] args) throws IOException {// 创建字节输入流对象
FileInputStream fis =
new FileInputStream("FileOutputStreamDemo.java");
// 数组的长度一般是 1024 或者 1024 的整数倍
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {System.out.print(new String(bys, 0, len));
}
// 释放资源
fis.close();}
10、字节流复制数据练习
把当前项目目录下的 a.txt 内容复制到当前项目目录下的 b.txt 中
步骤:
1、封装数据源
2、封装目的地
3、复制数据
4、关闭资源
public static void main(String[] args) throws IOException {// 封装数据源
FileInputStream fis = new FileInputStream("a.txt");
// 封装目的地
FileOutputStream fos = new FileOutputStream("b.txt");
// 复制数据
int by = 0;
while ((by = fis.read()) != -1) {fos.write(by);
}
// 释放资源 (先关谁都行)
fos.close();
fis.close();}