文章目录
IO
什么是流(Stream)?
- 内存与存储设备之间传输数据的通道。
- 数据借助流传播。
流的分类
按方向划分
- 输入流:将存储设备中的内容读入到内存中。
- 输出流:将内存中的内容写入到存储设备中。
按单位划分
- 字节流:以字节为单位,可以读写所有数据。
- 字符流:以字符为单位,只能读写文本数据。
按功能划分
- 节点流:具有实际传输数据的读写功能。
- 过滤流:在节点流的基础之上增强功能。
字节流抽象类
- 字节流的父类(抽象类)
- InputStream
- 字节输入流的所有类的超类。
- OutputStream
- 这个抽象类是表示字节输出流的所有类的超类。 输出流接收输出字节并将其发送到某个接收器。
FileInputStream
构造方法
- FileInputStream(File file)
通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。 - FileInputStream(FileDescriptor fdObj)
创建 FileInputStream通过使用文件描述符 fdObj ,其表示在文件系统中的现有连接到一个实际的文件。 - FileInputStream(String name)
通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
常用方法
read()
public int read()
功能:从输入流读取数据的下一个字节。若已经到达流的末尾,返回值是 -1 。
public static void main(String[] args) throws IOException {
System.out.println("----------单个字节读取-----------");
FileInputStream filIn = new FileInputStream("D:\\JavaCode\\JavaSE\\zz.txt");//括号内为文件的地址
int date = 0;
while ((date = filIn.read())!= -1){ //若已经到达流的末尾,返回值是 -1
System.out.print((char) date);
}
filIn.close();
----------单个字节读取-----------
xyzabcdef
Process finished with exit code 0
read(byte[] b)
public int read(byte b[])
功能:从输入流读取一些字节数,并将它们存储到缓冲区 b 。
public static void main(String[] args) throws IOException {
System.out.println("----------一次性多个字节读取-----------");
FileInputStream filIn = new FileInputStream("D:\\JavaCode\\JavaSE\\zz.txt");
byte[] b = new byte[6]; //byte的长度为缓存区
int count = filIn.read(b); //返回值为读取长度
System.out.println(new String (b)); //将 byte型数组b 转为 String型
System.out.println("读取的长度为:"+count);
int count2 = filIn.read(b);
System.out.println(new String (b));
System.out.println("读取的长度为:"+count2);
filIn.close();
----------一次性多个字节读取-----------
xyzabc
读取的长度为:6
defabc
读取的长度为:3
Process finished with exit code
- 通过输出可以发现结果是覆盖的,我们可以在转String的时候仅输出有效的部分,上可修改为
System.out.println(new String (b,0,count2));
read(byte[] b, int off, int len)
public int read(byte b[], int off, int len)
功能:从输入流在 off 位置开始读取最多 len字节的数据到一个字节数组。
public static void main(String[] args) throws IOException {
System.out.println("----------使用read(byte[] b, int off, int len) -----------");
FileInputStream filIn = new FileInputStream("D:\\JavaCode\\JavaSE\\zz.txt");
byte[] b = new byte[8];
int count = filIn.read(b,2,3);
System.out.println(new String(b)); //将 byte型数组b 转为 String型
System.out.println("读取的长度为:"+count);
filIn.close();
----------使用read(byte[] b, int off, int len) -----------
xyz
读取的长度为:3
Process finished with exit code 0
close()
public void close()
功能:关闭此输入流并释放与流相关联的任何系统资源。
FileOutputStream
构造方法
- FileOutputStream(File file)
以写入由指定的 File对象表示的文件。 - FileOutputStream(File file, boolean append)
以写入由指定的 File对象表示的文件。 - FileOutputStream(FileDescriptor fdObj)
以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。 - FileOutputStream(String name)
以指定的名称写入文件。 - FileOutputStream(String name, boolean append)
以指定的名称写入文件 append默认false 即覆盖原文件 为true则在文件内容后追加
常用方法
write(int b)
public void write(int b)
功能:将指定的字节写入此文件输出流。
public static void main(String[] args) throws Exception{
FileOutputStream fil = new FileOutputStream("D:\\JavaCode\\JavaSE\\zzz.txt");//不存在则会创建
int b = 97;
fil.write(b);
fil.close();
}
查看zzz.txt内容
a
write(byte[] b) & write(byte[] b, int off, int len)
public void write(byte b[])
public void write(byte b[], int off, int len)
功能:将 b.length个字节从指定的字节数组写入此文件输出流。
从下标 off 开始写入 len 个数据写入此文件输出流。
public static void main(String[] args) throws Exception{
FileOutputStream fil = new FileOutputStream("D:\\JavaCode\\JavaSE\\zzz.txt");//不存在则会创建
byte[] b = new byte[10];
b[0] = 13; //ascll码表 13为CR 回车
b[1] = 14;
b[2] = 15;
fil.write(b[1]);
fil.write(b,0,3);
fil.close();
}
查看zzz.txt内容
其他常用的write() 例子
public static void main(String[] args) throws Exception{
FileOutputStream fil = new FileOutputStream("D:\\JavaCode\\JavaSE\\zzz.txt");//不存在则会创建
fil.write("\r".getBytes());//写入换行 windows使用“\n”或者“\r” Linux "\n" Mac "\r"
String str = "HelloWorld";
fil.write(str.getBytes());
fil.write("\n".getBytes());
String str1 = "湖南长沙";
fil.write(str1.getBytes());
fil.close();
}
close()
public void close()
功能:关闭此文件输出流并释放与此流相关联的任何系统资源。
字节流复制文件
步骤
- 创建流,输入流,输出流。
- 创建 byte[ ] 缓存数据。
- 接收读取数量。
- 边读边写。
代码示例
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class TestCopy {
public static void main(String[] args) throws Exception{
//创建流
//输入流
FileInputStream fis = new FileInputStream("E:\\11.png");
//输出流
FileOutputStream fos = new FileOutputStream("E:\\22.png");
//创建缓冲区 1024 -->1K
byte[] b = new byte[1024];
//用count来接收读的数量
int count = 0;
//边读边写
while ((count = fis.read(b)) != -1){
fos.write(b,0,count); //从下标 off 开始写入 len 个数据写入此文件输出流
}
fis.close();
fos.close();
}
}
BufferedInputStream & BufferedOutputStream
- 字节缓冲流
- 提高IO效率,减少访问磁盘次数。内部定义了一个8K的缓冲区,具体查看源码。
- 数据存储在缓冲区中,flush是将缓存区的内容写入文件,也可以直接close。
- 方法与FileInputStream & FileOutputStream 相似。
BufferedInputStream构造方法
- BufferedInputStream(InputStream in)
创建一个 BufferedInputStream并保存其参数,输入流 in ,供以后使用。 - BufferedInputStream(InputStream in, int size)
创建 BufferedInputStream具有指定缓冲区大小,并保存其参数,输入流 in ,供以后使用。
代码示例
import java.io.BufferedInputStream;
import java.io.FileInputStream;
public class TestBufferedInputStream {
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("D:\\JavaCode\\JavaSE\\zz.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
int date = 0;
while ((date = bis.read()) != -1){
System.out.print((char)date);
}
bis.close();
}
}
BufferedOutputStream 构造方法
- BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 - BufferedOutputStream(OutputStream out, int size)
创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。
代码示例
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
public class TestBufferedOutputStream {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("D:\\JavaCode\\JavaSE\\Buffered.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("HelloWorld".getBytes());//写入8K缓冲区
bos.flush();//若不使用flush()方法来刷新硬盘 或者不关闭该字节缓冲流(close方法中执行了flush方法) 该写入仅写至缓冲区
bos.close();//内部调用了flush方法
}
}
注意事项:若不使用flush()方法来刷新硬盘 或者不关闭该字节缓冲流(close方法中执行了flush方法) 该写入仅写至缓冲区
对象流
- ObjectOutputStream(序列化) & ObjectInputStream(反序列化)
- 增强了缓冲区功能。
- 增强了读写8种基本数据类型和字符串的功能。
- 增强了读写对象的功能。
- readObject() 从流中读取一个对象。
- writeObject() 向流中写入一个对象。
- 使用流传输对象的过程称之为序列化和反序列化。
ObjectOutputStream(序列化)
- 将一个对象写入硬盘。
代码示例
先创建一个对象 序列化的对象需要实现Serializable
接口
import java.io.Serializable;
public class Student implements Serializable { //实现Serializable接口
public static final long serialVersionUID = 100;
private String name;
private int age;
private transient String country;//使用transient(瞬间)修饰的属性不能被序列化
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "name:"+ this.name +"\t"+"age:"+this.age;
}
}
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class TestObjectOutputStream {
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("D:\\JavaCode\\JavaSE\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Student stu1 = new Student("张三",18);
oos.writeObject(stu1);
oos.close();
}
}
注意事项
- 创建的bin文件只是一个类型,用txt打开会发现是乱码,因为他是一个对象。
ObjectInputStream(反序列化)
- 从流中读取对象。
代码示例
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class TestObjectInputStream {
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("D:\\JavaCode\\JavaSE\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
Student stu2 = (Student) ois.readObject();//返回的是一个Object类型 高到低 强制转换为Student类
ois.close();
System.out.println(stu2.toString());
}
}
name:张三 age:18
Process finished with exit code 0
序列化与反序列化的注意事项
- 序列化类必须实现
Serializable
接口。 - 序列化类中的对象属性也要求实现
Serializable
接口。 public static final long serialVersionUID = ***L
,序列化版本号ID,保证序列化的类和反序列化的类是同一个类。- 使用
transient
(瞬间)修饰的属性不能被序列化。 - 静态属性不能被序列化。
- 序列化多个对象,可以借助集合实现。
持续更新中…