java.io
让我们用标准的读写操作来完成对不同设备的读写数据工作
-
java将IO按照方向划分为输入与输出,参照点是我们写的程序.
-
输入:用来读取数据的,是从外界到程序的方向,用于获取数据.
-
输出:用来写出数据的,是从程序到外界的方向,用于发送数据.
java 定义超类(抽象类)
java.io.InputStream:所有字节输入流的超类,其中定义了读取数据的方法
java.io.OutputStream:所有字节输出流的超类,其中定义了写出数据的方法
java将流分为两类:节点流与处理流
- 节点流:也称为低级流.节点流的另一端是明确的,是实际读写数据的流,读写一定是建立在节点流基础上进行的.
- 处理流:也称为高级流.处理流不能独立存在,必须连接在其他流上,目的对数据进行加工处理。
实际应用中,我们可以通过串联一组高级流到某个低级流上以流水线式的加工处理对某设备的数据进行读写,这个过程也成为流的连接。
文件流
文件流是一对低级流,用于读写文件数据的流.
文件输出流FileOutputStream
java.io.InputStream 输入流,这个类是所有字节输入流的超类,规定了所有字节输入
* 流读取数据的相关方法。
* java.io.OutputStream 输出流,这个类是所有字节输出流的超类,规定了所有字节输出
* 流写出数据的相关方法。
方法:void write(int d)
向文件中写入1个字节,写入的内容是给定的int值对应的2进制的"低八位"
文件输入流FileInputStream
方法:int read()
读取一个字节,并一int型返回。返回的整数中读取的字节部分在该整数2进制的最后8位上
如果返回值为整数-1,则表示流读取到了末尾。对于读取文件而言就是EOF(end of file
文件末尾)
文件的复制
long currentIimeMillis() 毫秒值
System.currentlimeMillis 系统时间毫秒值
块读写的文件复制操作
方法:
读: int read(byte[] data)
写: void write(byte[] data)
void write(byte[]data,int offset,int len)
一次性将给定的字节数组从下标offset处开始的连续len个字节写入文件
写文本数据
String提供方法: byte[] getBytes(String charsetName) 将当前字符串转换为一组字节
参数为字符集(charsetName)的名字,常用的是UTF-8。 其中中文字3字节表示1个,英文1字节表示1个
注:
支持中文的常见字符集有:
GBK:国标编码。英文每个字符占1个字节,中文每个字符占2个字节
UTF-8:内部是unicode编码,在这个基础上不同了少部分2进制信息作为长度描述
英文每个字符占1字节
中文每个字符占3字节
文件输出流追加模式
重载的构造方法可以将文件输出流创建为追加模式
- FileOutputStream(String path,boolean append)
- FileOutputStream(File file,boolean append)
- 当第二个参数传入true时,文件流为追加模式(默认模式:覆盖模式)
- 指定的文件若存在,则原有数据保留,新写入的数据会被顺序的追加到文件中
FileOutputStream fos = new FileOutputStream( "demo.txt",true)
String line = "super idol的笑容都没你的甜,八月正午的阳光都没你的耀眼";
byte[] data = line.getBytes(StandardCharsets.UTF_8);
fos.write(data);
System.out.println("写出完毕");
fos.close();
读取文本数据
String提供了将字节数组转换为字符串的构造方法:
String(byte[]data,String charsetName)
将给定的字节数组中所有字节按照指定的字符集转换为字符串
String(byte[]data,int offset,int len,String charsetName)
String line = new String(data,0,len,"UTF-8");
将给定的字节数组从下标offset处开始的连续len个字节按照指定的字符集转换为字符串
高级流
BufferedOutputStream和BufferedInputStream.
高级流 作用是提高读写数据的效率.
缓冲流内部有一个字节数组,默认长度是8K.缓冲流读写数据时一定是将数据的读写方式转换为块读写来保证读写效率.
缓冲输出流
通过缓冲流写出的数据会被临时存入缓冲流内部的字节数组,直到数组存满数据才会真实写出一次
缓冲流的flush方法用于强制将缓冲区中已经缓存的数据一次性写出
其他的流实现该方法的目的仅仅是为了在流连接过程中传递flush动作给缓冲输出流。
bos.flush();//冲
对象流
ObjectOutputStream和ObjectInputSteam
对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化。
对象序列化:将一个java对象按照其结构转换为一组字节的过程(java对象----一组字节)
对象反序列化:将一组字节还原为java对象(前提是这组字节是一个对象序列化得到的字节)(字节----java对象)
对象序列化的流连接操作
1.实现序列化接口后最好主动定义序列化版本号这个常量。 这样一来对象序列化时就不会根据类的结构生成一个版本号,而是使用该固定值。 那么反序列化时,只要还原的对象和当前类的版本号一致就可以进行还原。
public static final long serialVersionUID = 1L;
2.
当一个属性被关键字transient修饰后,那么当进行对象序列化时,该属性值会被忽略 忽略不必要的属性可以达到对象瘦身的目的,减少资源开销。
Person------ java对象
(版本号+成员变量+无参构造+有参构造+setter 和getter+重写toString方法)
流连接: 序列化 持久化 v v 对象---->对象流------->文件流-------->文件
对象序列化
(ObjiectOutputStream)对象输出流
方法:void writerObject(Object obj)
将给定的对象转换为一组字节
注意:对象所属的类必须实现接口java.io.Serializable
否则抛出异常java.io.NotSerializableException
对象反序列化
(ObjectInputStream) 对象输入流
字符流
- java将流划分为字节流与字符流(.按照读写单位)
- java.io.InputStream和OutputStream--------字节流的超类
- java.io.Reader和Writer则是所有字符流的超类
- Reader和Writer是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法.
- 字符流最小读写单位为字符(char),但是底层实际还是读写字节,只是字符与字节的转换工作由字符流完成.
转换流
java.io.InputStreamReader和OutputStreamWriter
转换输出流 :将字符转换为字节(按照字符集)
转换输入流: 将字节转换为字符(按照字符集)
字符流读一个字符的read方法定义:
int read()
读取一个字符,返回的int值实际上表示的是一个char(低16位有效).如果返回的
int值表示的是-1则说明EOF
int d = isr.read();
// char c = (char)d;
读取的字节----字符
转换流的意义:
其他的字符高级流不能直接连接在字节流上.
而实际操作设备的流都是低级流同时也都是字节流.因此不能直接在流连接中串联起来.
转换流是一对可以连接在字节流上的字符流,其他的高级字符流可以连接在转换流上
.在流连接中起到"转换器"的作用(负责字符与字节的实际转换)
缓冲字符流
缓冲字符输出流:java.io.PrintWriter
java.io.BufferedWriter和BufferedReader
缓冲字符流内部也有一个缓冲区,读写文本数据以块读写形式加快效率.
并且缓冲流有一个特别的功能:可以按行读写文本数据.
java.io.PrintWriter具有自动行刷新的缓冲字符输出流
如果实例化PW时第一个参数传入的是一个流,则此时可以再传入一个boolean型的参数,
此值为true时就打开了自动行刷新功能。
即: 每当我们用PW的println方法写出一行字符串后会自动flush.
PrintWriter pw = new PrintWriter(bw,true);
向文件中写入字符串
PrintWriter pw = new PrintWriter("pw.txt","UTF-8");
缓冲字符输入流:java.io.BufferedReader
字符流,特点是块读文本数据,并且可以按行读取字符串
BufferedReader提供了一个读取一行字符串的方法:
String readLine()
该方法会返回一行字符串,返回的字符串不含有最后的换行符。
当某一行是空行时(该行内容只有一个换行符)则返回值为空字符串。
如果流读取到了末尾,则返回值为null。