Java IO流

一、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关键字,那么这个变量就会被当作是透明的,即不存在。
}

四、总结

在这里插入图片描述


参考文章

https://www.cnblogs.com/xdp-gacl/p/3634409.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值