一、字节输入输出流、字符输入输出流
FileInputStream:文件字节输入流、FileOutputStream:文件字节输出流、FileReader:文本字符输入流、FileWriter:文件字符输出流。
读写非文本文件(图片、视频等),用字节输入输出流;读写文本文件,用字符输入输出流。如果使用字节流处理中文字符文件,输出到控制台可能会出现乱码,此时可以用转换流解决。
复制图片,从图片a.jpg读出字节放入字节数组中,再把字节数组写入图片b.jpg。
(FileOutputStream会立即writer写入磁盘;FileWriter有缓冲区,会先写入缓冲区)
/**
* 复制图片
* 文件字节输入流FileInputStream、文件字节输出流FileOutputStream
*/
public void testFileStream() throws IOException {
// 字节输入流
FileInputStream fis = new FileInputStream("JavaBIO/a.jpg");
// 字节输出流
FileOutputStream fos = new FileOutputStream("JavaBIO/b.jpg");
// 将字节放入byte数组内
byte[] bs = new byte[5];
int len;
// 调用read方法,返回读取的长度,如果到达文件末尾,返回-1
while ((len = fis.read(bs)) != -1){
fos.write(bs, 0, len);
}
// 关闭流
fos.close();
fis.close();
}
复制文本内容,从文本a.txt读出字符放入字符数组中,再把字符数组写入文本b.txt。
/**
* 复制文本文件
* 文件字符输入流FileRead、文件字符输出流FileWriter
*/
public void testFileRW() throws IOException, InterruptedException {
// 字符输入流
FileReader fr = new FileReader("JavaBIO/a.txt");
// 字符输出流,第二个参数表示是否追加,默认false,即覆盖
FileWriter fw = new FileWriter("JavaBIO/b.txt", false);
// 把字符放入char数组中
char[] cs = new char[5];
int len;
while ((len = fr.read(cs)) != -1){
// 内容打印到控制台
// System.out.println(cs);
// 内容写到b.txt
fw.write(cs, 0, len);
}
// 关闭流
fw.close();
fr.close();
}
二、缓冲流
BufferedInputStream:字节输入缓冲流、BufferedOutputStream:字节输出缓冲流、BufferedRead:字符输入缓冲流、BufferedWriter:字符输出缓冲流。
FileInputStream每次会从磁盘读指定大小的数据,每调用一次read,就是读取一次磁盘。
(FileOutputStream会立即writer写入磁盘;FileWriter有缓冲区,会先写入缓冲区)
BufferedInputStream默认缓冲区大小为8192字节,一次会从文件读取8192个字节到缓冲区,其read(byte[] b)方法先查看缓冲区是否有数据,如果没有数据会从磁盘读取8192个字节到缓冲区,然后从缓冲区读取b.length字节到字符数组。
BufferedOutStream默认缓冲区大小也是8192个字节,把内容写到缓冲区中,当缓冲区写满,再把内容写到磁盘;也可以调用flush()方法,不等缓冲区写满,直接把缓冲区内容写到磁盘,并清空缓冲区。
BufferedWriter提供有readLine()方法,一次读取一行。
/**
* 复制图片
* 文件字节输入流FileInputStream、文件字节输出流FileOutputStream
* 缓冲输入流BufferedInputStream、缓冲输出流BufferedOutputStream
*/
public void testBufferedStream() throws IOException {
// 字节输入流
FileInputStream fis = new FileInputStream("JavaBIO/a.jpg");
// 字节输出流
FileOutputStream fos = new FileOutputStream("JavaBIO/b.jpg");
// 缓冲输入流(处理流)
BufferedInputStream bis = new BufferedInputStream(fis);
// 缓冲输出流(处理流)
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 方式一:将字节放入byte数组内
byte[] bs = new byte[5];
int len;
// 调用read方法,返回读取的长度,如果到达文件末尾,返回-1
// 看上去读了5个字节,实际第一次执行时,已经从文件读取了8192个字节到缓冲区,从缓冲区读5个字节
while ((len = bis.read(bs)) != -1){
// 会先写到缓冲区,默认缓冲区8192字节,缓冲区满了,才会写到文件中
bos.write(bs, 0, len);
}
// 关闭处理流,处理流会关闭字节流
bos.close();
bis.close();
}
三、转换流
InputStreamRead:字节输入流->字符输入流;OutputStreamWriter:字符输出流->字节输出流。
转换流作用在字节流上。如果使用字节流处理中文字符文件,输出到控制台可能会出现乱码,此时可以用转换流解决,把字节转换为字符。
/**
* InputStreamRead:字节输入流->字符输入流 相当于解码
* OutputStreadWriter:字符输出流 -> 字节输出流 相当于编码
*/
public void testStreamRW() throws IOException {
// 字节输入流
FileInputStream fis = new FileInputStream("JavaBIO/a.txt");
// 字节输出流,第二个参数表示是否追加,默认false,即覆盖
FileOutputStream fos = new FileOutputStream("JavaBIO/b.txt", false);
// 转换流,输入输出编码不一样,中文内容会出现乱码
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
// 把字符放入char数组中
char[] cs = new char[5];
int len;
while ((len = isr.read(cs)) != -1){
// 内容打印到控制台
// System.out.println(cs);
// 内容写到b.txt
osw.write(cs, 0, len);
}
// 关闭流,关闭处理流时,处理流会关闭字节流
osw.close();
isr.close();
}
四、标准输入、输出流
System.in 标准的输入流,默认从键盘输入;System.out 标准的输出流,默认从控制台输出。
public void systenIO1() throws IOException {
InputStream is = System.in; //System.in标准的输入流
PrintStream ps = System.out; //System.out标准的输出流
char c = (char)is.read();
ps.print(c);
ps.close();
is.close();
}
setIn()指定输入流,改变默认从键盘输入,此时指定文件,则从指定文件输入;setOut()指定输出流,改变默认从控制台输出,此时指定文件,输出到指定文件。
public void systenIO2() throws IOException {
System.setIn(new FileInputStream("JavaBIO/a.txt"));
System.setOut(new PrintStream("JavaBIO/b.txt"));
InputStream is = System.in; //System.in标准的输入流
PrintStream ps = System.out; //System.out标准的输出流
int d;
System.out.println(is.read());
while ((d = is.read()) != -1){
ps.print((char)d);
}
ps.close();
is.close();
}
五、打印流
PrintStream 字节打印流;PrintWriter 字符打印流。打印到指定的文件。
public void print() throws FileNotFoundException {
PrintStream ps = new PrintStream("JavaBIO/b.txt");
ps.println("abcd中国");
ps.close();
PrintWriter pw = new PrintWriter("JavaBIO/c.txt");
pw.println("abcd中国");
pw.close();
}
六、数据流
DataInputStream:数据输入流;DataOutputStream:数据输出流。数据流方便操作基本类型和字符串。
读文件的数据类型(int、String)的顺序,与写入文件时的类型(int、String)的顺序要保持一致。
public void testDataStream() throws IOException {
// 数据输出流
DataOutputStream dos = new DataOutputStream(new FileOutputStream("JavaBIO/b.txt"));
// 写一个数字
dos.writeInt(11);
// 写一个字符串
dos.writeUTF("abcd");
// 关闭数据输出流
dos.close();
// 数据输入流
DataInputStream dis = new DataInputStream(new FileInputStream("JavaBIO/b.txt"));
// 读一个数字
int num = dis.readInt();
// 读一个字符串
String str = dis.readUTF();
// 打印
System.out.println(num);
System.out.println(str);
// 关闭数据输入流
dis.close();
}
七、对象流
ObjectInputStream:对象输入流、ObjectOutputStream:对象输出流。
定义一个Person类,需要继承序列化接口。用ObjectOutputStream把对象存入b.txt文件中,因为存入的是对象,所以打开是乱码;用ObjectInputStream从文件中读取对象。
public class ObjectStreamTest {
public void testObjectStream() throws IOException, ClassNotFoundException {
// 对象输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("JavaBIO/b.txt"));
Person p1 = new Person(18,"zz");
// 写对象
oos.writeObject(p1);
oos.close();
// 对象输入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("JavaBIO/b.txt"));
// 读对象
Person p2 = (Person) ois.readObject();
ois.close();
System.out.println(p2.getAge() + " " + p2.getName());
}
}
//实现序列化接口
class Person implements Serializable {
private static final long serialVersionUID = 6495153350280013035L;
private int age;
private String name;
public Person() {
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
八、随机存取文件流
RandomAccessFile:随机存取文件流。既可以作为输入流,又可以作为输出流,作为输入流,不是对原有文件的覆盖,是对原有文件内容的覆盖,可以调用seek方法,指定指针的位置(开始覆盖内容的位置)。
public void testRandomAccessFile() throws IOException {
// 第二个参数数mode:r、rw、rwd、rws
RandomAccessFile raf1 = new RandomAccessFile("JAVABIO/a.txt", "r");
RandomAccessFile raf2 = new RandomAccessFile("JAVABIO/b.txt", "rw");
// 指定指针的位置,从指定的位置开始覆盖内容
// raf2.seek(3);
byte[] buffer = new byte[1024];
int len;
while ((len = raf1.read(buffer)) != -1){
raf2.write(buffer, 0, len);
}
raf2.close();
raf1.close();
}
九、字节数组流
ByteArrayOutputStream:字节数组流,相当于StringBuilder。
public void testByteArrayOutputStreamT() throws IOException {
// 默认32字节的缓冲区
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write("abcd".getBytes());
System.out.println(bos.toString());
bos.close();
}
十、管道流
PipedInputStream 和 PipedOutputStream 设计用来解决跨线程的字节数据传输。它们总是成对出现的。
public void testPipeStream() throws IOException {
// 创建 PipedInputStream 对象
final PipedInputStream in = new PipedInputStream();
final PipedOutputStream out = new PipedOutputStream();
// 两个类进行连接
in.connect(out);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write("Hello");
writer.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String str = reader.readLine();
reader.close();
System.out.println(str);
}