- IO 流主要用来处理设备之间的数据传输
- Java 对数据的操作主要通过流的方式
- Java 用于操作流的对象都在 IO 包中
- 流按操作数据的不同分为: 字节流和字符流
- 流按流向分为: 输入流和输出流
- 将外部设备中的数据读取到内存中: 输入
- 将内存中的数据写入到外部设备中: 输出
字符流
- 字符流的由来:
字节流读取文本字节数据后, 不直接操作而是先查指定的编码表, 获取对应的文字,
然后再对文字进行操作, 简单说: 字符流 = 字节流 + 编码表. - 字符流的抽象基类(顶层父类): Reader, Writer
// 需求一: 将一些文字存储到硬盘的一个文件中
/*
* 思路:
* 如果要操作文字数据, 建议优先考虑字符流.
* 而且需要将数据从内存中写入到硬盘上, 要使用字符流中的输出流: Writer
* 硬盘的数据基本体现是文件, 希望找到一个可以操作文件的 Writer
* 通过查阅 API , 找到了操作文件的 FileWriter 子类
* 注意: 该子类没有空参的构造函数.
* 原因: 既然是往一个文件中写入文本数据, 那么创建对象时, 就必须明确存储数据的目的地
* (即构造函数中的参数为 File 对象或者为文件名)
*/
// 创建一个可以往文件中写入字符数据的字符输出对象
// 如果文件不存在, 则会自动创建
// 如果文件存在, 则会覆盖
// 如果构造函数中加入 true, 可以实现对文件进行续写. 否则, 是覆盖
FileWriter fw = new FileWriter("demo.md", true);
// 获取系统默认的行分隔符
final String LINE_SEPARATOR = System.getProperty("line.separator");
// 调用 Writer 对象的 write(string) 方法,写入数据
// 其实数据写入到临时缓冲区中
fw.write("abcd"+LINE_SEPARATOR+"hahaha");
// 进行刷新, 将数据直接写入到目的地中
fw.flush();
// 关闭流, 关闭资源
// 关闭之前, 默认会先调用 flush() 刷新缓冲区中的数据到目的地
// 关闭之后, 在调用 write() 或 flush() 将导致抛出 IOException 异常
fw.close();
// 需求二: 读取一个文本文件, 将读取到的字符打印到控制台
// FileReader 类
public static void main(String[] args) throws IOException {
// 创建读取字符数据的流对象
// 在创建读取流对象时, 必须要明确被读取的文件, 一定要确定该文件是存在的
// 即用一个读取流关联一个已存在文件
FileReader fr = new FileReader("demo.md");
// 第一种方式: 读取单个字符
// 用 Reader 中的 read 方法读取单个字符
// 返回值为字符对应的整数,范围在: 0 到 65535 之间. 如果已达到流的末尾, 返回 -1
// int ch = fr.read();
int ch = 0;
while((ch=fr.read()) != -1){
System.out.println((char)ch);
}
// 方式二: 读取数组
// int read(char[] buf), 返回的是读取的字符数
// 读取之前,先创建字符数组
// 数组的长度一般为 1024 的整数倍
char[] buf = new char[3];
// int num = fr.read(buf); // 将一次读取到的字符存储到数组中
// System.out.println(new String(buf)); // 将本次读取到的数组变成字符串,打印
int len = 0;
while((len=fr.read()) != -1){
System.out.println(new String(buf,0,len));
}
fr.close(); // 关闭流资源
}
// 需求三: 将 C 盘的一个文本文件复制到 D 盘
// 分析:
// 读取 C 盘文件中的数据
// 将这些数据写入到 D 盘中
// 连读带写
// 思路:
// 1. 需要读取源
// 2. 将读到的源数据写入到目的地
// 3. 既然是操作文本数据, 使用字符流
public class CopyTextTest{
public static void main(String[] args) throws IOException {
// 1, 读取一个已有的文本文件, 使用字符读取流和文件关联
FileReader fr = new FileReader("demo.txt");
// 2. 创建一个目的, 用于存储读到的数据
FileWriter fw = new FileWriter("copytext_1.txt");
// 3. 频繁的读写操作, 每次读取一个字符
int ch = 0;
while((ch=fr.read())!=-1){
fw.write(ch);
}
// 4. 关闭流资源
fw.close();
fr.close();
}
}
// 第二种复制方式:
public class CopyTextTest_2 {
private static final int BUFF_SIZE = 1024;
public static void main(String[] args){
FileReader fr = null;
FileWriter fw = null;
try{
fr = new FileReader("demo.txt");
fw = new FileWriter("copytext_2.txt");
char[] ch = new char(BUFF_SIZE);
int len=0;
while((len=fr.read(ch)) != -1){
fw.write(ch,0,len);
}
} catch(IOException e){
throw new RuntimeException("读写失败");
} finally{
if(fr != null)
try{
fr.close();
} catch(IOException e){
e.printStackTrace();
}
if(fw != null)
try{
fw.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
_参考资料_ - [JavaSE 基础视频(毕向东)](https://www.bilibili.com/video/av3124795/index_11.html#page=1) - [JDK 1.6 中文文档](http://tool.oschina.net/apidocs/apidoc?api=jdk-zh)