IO流是什么?
一句话:IO流就是程序中数据的管道,可以做数据传输
举例一:
指挥Java程序读取文件中的数据,还可以将数据写出到文件(上传\下载)(学习到网络编程后,就可以实现了)
举例二:
服务端用Java程序读取客户端发送的消息,再回写数据
客户端用Java程序读取服务端发送的消息,再回写数据
画图理解
IO流的分类
流向分为:
- 输入流 \ input(读取)
- 输出流 \ output(写出)
类型分为:
字节流:可以操作任意类型文件,因为文件存储的时候就是字节,但是操作纯文本文件的时候,有可能会乱码
一个识别小技巧:用windows系统的记事本打开,如果不是乱码,就是纯文本文件,如果是乱码,就不是纯文本文件
字符流:只能操作纯文本文件,解决字节流读取文件的乱码问题
IO流的体系结构
识别流的思路
流对象以Stream为结尾,肯定是字节流
流对象以Reader \ Writer 为结尾的,肯定是字符流
字节流和字符流的使用场景
- 如果操作的是纯文本文件,优先使用字符流
- 如果操作的是图片、视频、音频等二进制文件,优先使用字节流
- 如果不确定文件类型,优先使用字节流,字节流是万能的流
IO流程序书写流程
- 在操作之前,要导包,java.io包
- 在操作流对象的时候,要处理解决异常(IOException)
- 在操作完流对象之后,必须关闭资源, 所有流资源的关闭 close( );
字节流写出数据
作用
可以将字节数据写出到指定的文件中
FileOutputStream类
构造方法和描述:
|
|
|
|
|
所有方法:
返回值类型 |
方法和描述 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
字节流常见的两个问题
换行:
- Windows:
\r\n
举例:输出流对象.write("需要写入的数据\r\n".getBytes());
- Mac:
\r
- Linux:
\n
追加:
FileOutputStream(String name, boolean append)
:第二个参数为true
,表示追加写入的数据- 注意:如果构造方法没有打开追加写入的开关,执行构造方法会把文件中内容清空
案例小练习
需求:键盘录入用户输入的消息,将接收到的消息保存在当前模块下 info.txt,直到用户输入 886 结束程序
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class StreamTest1 {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
FileOutputStream fos = new FileOutputStream("day11-code\\info.txt", true);
while (true) {
System.out.println("请输入您要输入的数据:");
String msg = sc.nextLine();
if ("886".equals(msg)) {
fos.close();
break;
}
fos.write(msg.getBytes());
fos.write("\r\n".getBytes());
}
}
}
IO流异常处理-标准的关流代码
IO流异常处理代码(JDK7标准):
被finally修饰的程序,一定会执行
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("day11-code\\c.txt");
fos.write("你好".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
IO流异常处理代码(JDK8标准):
try (需要关流的对象) {
IO流的逻辑代码
} catch (异常类 对象名) {
异常的处理方案
}
只需要将关流的对象,放在try()中,就会自动关流了
细节:try()中的对象,需要实现AutoCloseable接口
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("day11-code\\c.txt");) {
fos.write("你好".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
字节流读取数据
作用:
可以将文件中的字节数据读取出来
FileInputStream类:
构造方法和描述
|
|
|
所有方法
返回值类型 |
方法和描述 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
读取方式:
一次读取一个数据
public static void main(String[] args) throws IOException {
// 创建字节输入流对象
FileInputStream fis = new FileInputStream(new File("day11-code\\a.txt"));
// 循环的读取, 一次读取一个字节
int i;
while ((i = fis.read()) != -1) {
System.out.println((char) i);
}
// 关流释放资源
fis.close();
}
一次读取一个字节数组
public static void main(String[] args) throws IOException {
// 创建字节输入流对象
FileInputStream fis = new FileInputStream("day11-code\\a.txt");
byte[] bys = new byte[2];
int len;
// 循环的读取, 一次读取一个字节
while ((len = fis.read(bys)) != -1) {
String s = new String(bys, 0, len);
System.out.print(s);
}
// 关流释放资源
fis.close();
}
案例 : 字节流拷贝文件
需求:使用字节流实现文件拷贝
分析:
- 创建输入流关联要拷贝的文件
- 创建输出流关联数据目的
- 读写操作
- 关闭流释放资源(要求实现自动关流)
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyTest1 {
public static void main(String[] args) {
// 1.创建输入流关联要拷贝的文件
// 2.创建输出流关联数据目的
try (FileInputStream fis = new FileInputStream("D:\\a.flv");
FileOutputStream fos = new FileOutputStream("E:\\a.flv");) {
// 3.读取操作
int i;
byte[] bys = new byte[1024];
while ((i = fis.read(bys)) != -1) {
fos.write(bys, 0, i);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节缓冲流
介绍:提高读写效率
字节缓冲流构造方法
输入:public BufferedInputStream(InputStream in)
:创建一个缓冲输入流对象,参数是基本的字节输入流
输出:public BufferedOutputStream(OutputStream out)
:创建一个缓冲输出流对象,参数是基本的字节输出流
注意:缓冲流不具备读写功能,只提供缓冲区,读写操作,还是需要依赖于基本的流
代码演示
public class BufferedStreamDemo {
public static void main(String[] args) throws IOException {
// 创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day11-code\\a.txt"))
// 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStram("day11-code\\copy.txt"))
byte[] bys = new byte[1024];
int len;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bis.close();
bos.close();
}
}
四种文件流的拷贝方式
普通字节流(单个字节拷贝):每次读写一个字节,效率很差
普通字节流 + 自定义数组拷贝(314M 耗时 : 2404毫秒,数组设置为 8192个大小后 314M 耗时 : 436 毫秒)
缓冲流(单个字节拷贝)(314M 耗时 : 8407毫秒)
缓冲流 + 自定义数组拷贝(314M 耗时 : 406毫秒)
过渡知识-字符集
字符集
字符集:说的就是编码表
编码表:计算机中,字符到字节的一套对应关系
ASCII 码表
思考 : 字节再往下是什么 ?
二进制
所以, 计算机存储任何数据, 都是以二进制的形式进行存储
需要记住的结论
我们在文件中存储的字符, 实际上都有一份数值的表示形式 !
常见的编码表 :
ASCII : 所有码表都囊括了 ASCII 码表
GBK : 中国的码表, 每个中文, 占用2个字节
Unicode – UTF-8:万国码, 每个中文, 占用3个字节
编码-解码
概念介绍 :
编码 : 将看得懂的, 变成看不懂的 (字符转字节)
解码 : 将看不懂的, 变成看得懂的 (字节转字符)
编码 :
解码 :
字符串类 String 的编码解码 :
图解
需要重点记住的 :
如果今后出现了乱码 : 查看编码和解码的方式是否一致
- GBK : 每个中文占用2个字节
- UTF-8 : 每个中文占用3个字节
- 英文, 数字, 标点符号, 都占用1个字节
中文的字节表示形式, 第一个肯定是负数
IO流-字符流
字符流应用
如果操作的文件是纯文本文件,想要避免中文乱码问题,就可以使用字符流
字符流组成
字节流 + 编码表
字符流方法
读数据方法:
public int read()
:一次读取一个字符
public int read(char[] cbuf)
:一次读取一个字符数组
分类 :
FileReader(字符输入流) :
构造方法:
public FileReader(String fileName)
:据给定的文件名构造一个FileReader对象
概述 : 用来读取字符文件的便捷类
FileWriter(字符输出流):
使用FileWriter写出数据:字符输出流,如果写出数据后,没有调用close方法,数据将无法写入文件
解决方案:
close()
:主要的职责是关闭流释放资源,只不过关闭之前,顺手将缓冲区的数据,刷出到文件中
flush()
:专门刷出数据的方法
区别:close方法关闭流之后,不能继续写出数据了
构造方法:
public FileWriter(String fileName)
:使用字符输出流对象关联文件,文件路径以字符串形式给出
public FileWriter(File file)
:使用字符输出流对象关联文件,文件路径以File对象形式给出
暂无评论内容