文章目录
一、Java IO流基础
1、流式输入/输出原理
在java程序中,对于数据的输入/输出操作以"流"(stream)方式进行;J2SDK提供了各种各样的"流"类,用以获取不同种类的数据:程序中通过标准的方法输入或输出数据
2、输入流/输出流
3、节点流/处理流
3.1 节点流
节点流就是一根管道直接插到数据源上面,直接读数据源里面的数据,或者是直接往数据源里面写入数据。典型的节点流是文件流:文件的字节输入流(FileInputStream
),文件的字节输出流(FileOutputStream
),文件的字符输入流(FileReader
),文件的字符输出流(FileWriter
)
3.2 处理流
处理流是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。
如BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
;处理流的构造方法总是要带一个其他的流对象做参数,一个流对象经过其他流的多次包装,称为流的链接
二、节点流讲解
1、InputStream(输入流)
//读取一个字节并以整数的形式返回(0~255)
//如果返回-1就说明已经到了输入流的末尾
int read() throws IOException
//读取一系列字节并存储到一个数组buffer
//返回实际读取的字节数,如果读取前己到输入流的末尾,则返回-1
int read(byte[] buffer) throws IOException
//读取1ength个字节
//并存储到一个字节数组buffer,从1ength位置开始
//返回实际读取的字节数,如果读取前以到输入流的末尾返回-1.
int read(byte[]buffer, int offset, int length) throws IOException
//关闭流释放内存资源
void close() throws IOException
//跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException
2、OutputStream(输出流)
//向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException
//将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException
//将一个字节类型的数组中的从指定位置(off)开始的1en个字节写入到输出流
void write(byte[] b, int off, int len) throws IOException
//关闭流释放内存资源
void close() throws IOException
//将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException
注意:FilelnputStream和FileOutputStream这两个流都是字节流,都是以一个字节为单位进行输入和输出的。所以对于占用2个字节存储空间的字符来说读取出来时就会显示成乱码
3、Reader流
//读取一个字节并以整数的形式返回(0~255)
//如果返回-1就说明已经到了输入流的末尾
int read() throws IOException
//读取一系列字节并存储到一个数组buffer
//返回实际读取的字节数,如果读取前己到输入流的末尾,则返回-1
int read(byte[] buffer) throws IOException
//读取1ength个字节
//并存储到一个字节数组buffer,从1ength位置开始
//返回实际读取的字节数,如果读取前以到输入流的末尾返回-1.
int read(byte[]buffer, int offset, int length) throws IOException
//关闭流释放内存资源
void close() throws IOException
//跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException
4、Writer流
//向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException
//将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException
//将一个字节类型的数组中的从指定位置(off)开始的1en个字节写入到输出流
void write(byte[] b, int off, int len) throws IOException
//关闭流释放内存资源
void close() throws IOException
//将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException
注意:FileReader和FileWriter这两个流都是字符流,都是以一个字符为单位进行输入和输出的,所以读取和写入占用2个字节的字符时都可以正常地显示出来
三、 处理流讲解
1、缓冲流(Buffering)
缓冲流要“套接在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法
BufferedReader(Reader in)
BufferedReader(Reader in, int sz)//sz为自定义缓冲区的大小Bufferedwriter(writer out)
Bufferedwriter(Writer out, int sz)
BufferedInputstream(Inputstream in)
BufferedInputstream(Inputstream in, int size)
Bufferedoutputstream(Inputstream in)
Bufferedoutputstream(Inputstream in int size)
- 缓冲输入流支持其父类的mark和reset方法
- BufferedReader提供了readLine方法用于读取一行字符串
- BufferedWriter提供了newLine用于写入一个行分隔符
- 对于输出的缓冲流,写出的数据会现在内存中缓存,使用flush方法将会使内存中的数据立刻写出
2、转换流
- InputstreamReader 和OutputStreamwriter 用于字节数据到字符数据之间的转换
- InputstreamReader 需要和Inputstream“套接"。
- OutputstreamWriter 需要和Outputstream“套接"。
- 转换流在构造时可以指定其编码集合
Inputstream isr=new InputstreamReader(System.in, "ISO8859-1")
3、数据流
- DatalnputStream 和DataOutputStream 分别继承自InputStream和 OutputStream,它属于处理流,需要分别“套接"在Inputstream和OutputStream类型的节点流上
- Datalnputstream 和DataOutputStream 提供了可以存取与机器无关的Java原始类型数据(int,double等)的方法
- DatalnputStream 和DataOutputStream的构造方法
DataInputstream(InputStream in)
DataoutputStream(OutputStream out)
举例
public static void main(String args[]){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//在调用构造方法时,首先会在内存里面创建一个ByteArray字节数组
DataOutputStream dos = new DataOutputStream(baos);
//在输出流的外面套上一层数据流,用来处理int,double类型的数
try{
dos.writeDouble(Math.random());//把产生的随机数直接写入到字节数组ByteArray中
dos.writeBoolean(true);//布尔类型的数据在内存中就只占一个字节
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
// 9,九个字节
System.out.println(bais.available());
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readDouble());//先写进去的就先读出来,调用readDouble()方法读取出写入的随机数
System.out.println(dis.readBoolean());//后写进去的就后读出来,这里面的读取顺序不能更改位置,否则会打印出不正确的结果
dos.close();
bais.close();
}catch(Exception e){
e.printStackTrace();
}
}
4、打印流(Print)
- PrintWriter 和PrintStream都属于输出流,分别针对与字符和字节
- PrintWriter 和PrintStream 提供了重载的print
- Println方法用于多种数据类型的输出
- PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
- PrintWriter 和PrintStream有自动flush功能
Printwriter(Writer out)
Printwriter(Writer out,boolean autoFlush)
Printwriter(OutputStream out)
Printwriter(OutputStream out,boolean autoFlush)
Printstream(OutputStream out)
Printstream(OutputStream out,boolean autoFlush)
5、对象流(Object)
直接将Object写入或读出,直接实现Serializable接口的类是JDK自动把这个类的对象序列化,而如果实现public interface Externalizable extends Serializable的类则可以自己控制对象的序列化,建议能让JDK自己控制序列化的就不要让自己去控制
import java.io.*;
/**
* @author Shawn
* @version 1.0
* @description: TODO
* @date 2022/1/29 21:01
*/
public class DemoTest{
public static void main(String args[]) {
T t = new T();
t.k = 8;// 把k的值修改为8
try {
FileOutputStream fos = new FileOutputStream(
"D:/logs/TestObjectIo.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
// ObjectOutputStream流专门用来处理Object的,在fos流的外面套接ObjectOutputStream流就可以直接把一个Object写进去
oos.writeObject(t);// 直接把一个t对象写入到指定的文件里面
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream(
"D:/logs/TestObjectIo.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
// ObjectInputStream专门用来读一个Object的
T tRead = (T) ois.readObject();
// 直接把文件里面的内容全部读取出来然后分解成一个Object对象,并使用强制转换成指定类型T
System.out.print(tRead.i + "\t" + tRead.j + "\t" + tRead.d + "\t"
+ tRead.k);
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*
* 凡是要将一个类的对象序列化成一个字节流就必须实现Serializable接口
* Serializable接口中没有定义方法,Serializable接口是一个标记性接口,用来给类作标记,只是起到一个标记作用。
* 这个标记是给编译器看的,编译器看到这个标记之后就可以知道这个类可以被序列化 如果想把某个类的对象序列化,就必须得实现Serializable接口
*/
class T implements Serializable {
// Serializable的意思是可以被序列化的
int i = 10;
int j = 9;
double d = 2.3;
int k = 15;
// transient int k = 15;
// 在声明变量时如果加上transient关键字,那么这个变量就会被当作是透明的,即不存在。
}
四、总结
参考文章