1.流的分类
- 在Java中把不同的输入/输出源抽象表述为“流stream”,stream是从source到sink的有序数据;
- 按照输入的流向来分类:(输入输出的考量角度是程序所在的内存)
- 输入流:只能从中读取数据,而不能向其写入数据;
- 输出流:只能向其写入数据,不能读数据;
- 按照输入数据大小:
- 字节流:操作数据单元为8位字节;
- 字符流:操作数据单元为16位字节;
- 按照流的角色:
- 节点流:可以向一个特定设备读/写的流;
- 处理流:可以对已经存在的流进行封装;
2.流的概念模型
- Java的IO流涉及40多个类,都是从如下抽象基类派生的:
- InputStream/Reader:所有输入流的基类,前者是字节流,后者是字符流;
- OutputStream/Writer:所有输出流的基类,前者是字节流,后者是字符流;
3.字节流和字符流
1.InputStream和Reader(page686)
/*
在InputStream中包含三个公共方法:
1.int read():从输入流中读取单个字节,返回所读取的字节数据;
2.int read(byte[] b):从输入流中最多读b.length个字节,返回实际读取的字节数;
3.int read(byte[] b, int off, int len):从输入流中最多读取len个字节的数据,将其存储至b中,注意,是从b[off]位置开始存储;
在Reader中包含的三个方法:
1.int read():从输入流中读取单个字符,返回所读取的字节数据;
2.int read(char[] cbuf):从输入流中读取最多cbuf.length个字符的数据,存储在cbuf数组中,返回实际读取的字符数;
3.int read(char[] cbuf, int off, int length):同3,将字节换成字符;
*/
import java.io.*;
public class FileInputStreamTest
{
public static void main(String[] args) throws IOException
{
//用FileInputStream读取文件
var fis = new FileInputStream("FileInputStreamTest.java");
// 定义读取数据数组的大小
var bbuf = new byte[1024];
// 用于保存实际读取的字节数
var hasRead = 0;
while ((hasRead = fis.read(bbuf)) > 0)
{
// 将字节数据转换为字符串输出;
System.out.print(new String(bbuf, 0, hasRead));
}
//关闭文件流,
fis.close();
}
}
2.OutputStream和Writer(page687)
-
OutputStream和Writer在方法上与InputStream基本一致,只是输出方法有差异:write();
- 程序:
import java.io.*;
public class FileOutputStreamTest
{
public static void main(String[] args)
{
try (
var fis = new FileInputStream("FileOutputStreamTest.java");
var fos = new FileOutputStream("newFile.txt"))
{
var bbuf = new byte[32];
var hasRead = 0;
// 首先读取数据
while ((hasRead = fis.read(bbuf)) > 0)
{
// 将读到的数据写入fos中
fos.write(bbuf, 0, hasRead);
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}