【笔记】Java——流(Stream)

本文详细介绍了Java中的流(Stream),包括输入/输出流、字节流与字符流、节点流与处理流的区别,以及FileInputStream、FileOutputStream、Reader、Writer等具体流的使用方法。还涉及缓冲流、数据流、转换流、Print流和Object流,特别是数据的序列化与反序列化概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 在Java程序中,对于数据的输入/输出操作以“流”(stream)方式进行;J2SDK提供了各式各样的“流”类,用以获取不同种类的数据;程序中通过标准的方法输入或输出数据
1.Java流类的分类
  • java.io包中定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同的角度对其进行分类:
    • 按数据流的方向不同可以分为输入流输出流 【站在程序的角度】
    • 按处理数据单位不同可以分为字节流字符流
    • 按照功能不同可以分为节点流处理流

2.输入/输出流类
  • 位于java.io内的所有流类型都分别继承自以下四种抽象流类型
字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter
1)InputStream
  • 继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8bit)。【深色为节点流,浅色为处理流】

*InputStream的基本方法
  • int read() throws IOException:读取一个字节并以整数的形式返回(0~255),如果返回-1即已到输入流的末尾
  • int read(byte[] buffer) throws IOException:从输入流读取一些字节数,并将它们存储到缓冲区 buffer,返回实际读取的字节数,如果读取前已到输入流的末尾返回-1
  • int read(byte[] buffer,int offset,int length) throws IOException:从输入流读取最多length字节的数据到一个字节数组buffer中。返回实际读取的字节数,如果读取前已到输入流的末尾返回-1
  • void close() throws IOException:关闭流释放内存资源
  • long skip(long n) throws IOException:跳过n个字节不读,返回实际跳过的字节数
2)OutputStream
  • 继承自OutputStream的流是用于程序中输出数据,且数据的单位为字节(8bit)。【深色为节点流,浅色为处理流】

*OutputStream的基本方法
  • void write(int b) throws IOException:向输出流中写入一个字节数据,该字节数据为参数b的第8位
  • void write(byte[] b) throws IOException:将一个字节类型的数组中的数据写入输出流
  • void write (byte[] buffer,int offset,int length) throws IOException:将一个字节类型的数组buffer中从指定位置offset开始的length个字节写入到输出流
  • void close() throws IOException:关闭流释放内存资源
  • void flush() throws IOException:将输出流中缓冲的数据全部写出到目的地【先写flush再写close】
3)Reader
  • 继承自Reader的流都是用于向程序中输入数据,且数据的单位为字符(16bit)。【深色为节点流,浅色为处理流】

*Reader的基本方法
  • int read() throws IOException:读取一个字符并以整数的形式返回(0~255),如果返回-1即已到输入流的末尾
  • int read(char[] cbuf) throws IOException:读取一系列字符并存储到一个输出cbuf中,返回实际读取的字符数,如果读取前已到输入流的末尾返回-1
  • int read(char[] cbuf,int offset,int length) throws IOException:从输入流读取最多length字符的数据到一个字节数组cbuf中。返回实际读取的字符数,如果读取前已到输入流的末尾返回-1
  • void close() throws IOException:关闭流释放内存资源
  • long skip(long n) throws IOException:跳过n个字符不读,返回实际跳过的字符数
4)Writer
  • 继承自Writer的流都是用于向程序中输出数据,且数据的单位为字符(16bit)。【深色为节点流,浅色为处理流】

*Writer的基本方法
  • void write(int c) throws IOException:向输出流中写入一个字符数据,该字符数据为参数c的第16位
  • void write(char[] cbuf) throws IOException:将一个字符类型的数组中的数据写入输出流
  • void write (char[] cbuf,int offset,int length) throws IOException:将一个字符类型的数组cbuf中从指定位置offset开始的length个字符写入到输出流
  • void write(String str) throws IOException:讲一个字符串中的字符写入到输出流
  • void write(String str,int offset,int length) throws IOException:将一个字符串从offset开始的length个字符写入到输出流
  • void close() throws IOException:关闭流释放内存资源
  • void flush() throws IOException:将输出流中缓冲的数据全部写出到目的地【先写flush再写close】

3.节点流和处理流
1)节点流
  • 节点流为可以从一个特定的数据源(节点)读写数据(如:文件,内存)
类型字符流字节流
File(文件)FileReader;FileWriterFileInputStream;FileOutputStream
Memory ArrayCharArrayReader;CharArrayWriterByteArrayInputStream;ByteArrayOutputStream
Memory StringStringReader;StringWriter
PipePipedReader;PipedWriterPipedInputStream;PipedOutPutStream
2)处理流
  • 处理流是“连接”在已存在的流(节点流或处理流)之上,通过数据的处理为程序提供更为强大的读写功能。【套在其他流之上的】
处理类型字符流字节流
BufferingBufferedReader;BufferedWriterBufferedInputStream;BufferedOutputStream
FilteringFilterReader;FilterWriterFilterInputStream;FilterOutputStream
Converting between bytes and characterInputStreamReader;OutputStreamWriter
Object SerializationObjectInputStream;ObjectOutputStream
Data conversionDataInputStream;DataOutputStream
CountingLineNumberReaderLineNumberInputStream
Peeking aheadPusbackReaderPushbackInputStream
PrintingPrintWriterPrintStream

4.文件流
1)FileInputStream和FileOutputStream
  • FileInputStream和FileOutputStream分别继承自InputStream和OutputStream用于向文件中输入和输出字节

  • FileInputStream和FileOutputStream类支持其父类InputStream和OutputStream所提供的的数据读写方法

  • 注意

    ​ ①在实例化InputStream和OutputStream流时要用try-catch语句以处理其可能抛出的FileNotFoundException。

    ​ ②在读写数据时也要用try-catch语句以处理可能抛出的IOException

    ​ ③FileNotFoundException是IOException的子类

(1)FileInputStream举例
package com.stream;
/*
@author qw
@date 2020/8/6 - 22:08
**/
import java.io.*;
public class Demo01 {
    public static void main(String[] args) {
        int b = 0;
        FileInputStream in = null;
        try {
            in = new FileInputStream("D:\\javaEx\\io\\TestFileInputStream.java");
        } catch (FileNotFoundException e) {
            System.out.println("找不到指定文件");
            System.exit(-1);//系统退出
        }

        try {
            long num = 0;
            while ((b = in.read()) != -1) {
                System.out.println((char) b);
                num++;
            }
            in.close();
            System.out.println();
            System.out.println("共读取了" + num + "个字节");
        } catch (IOException e1) {
            System.out.println("文件读取错误");
            System.exit(-1);
        }

    }
}
(2)FileOutputStream举例
package com.stream;
/*
@author qw
@date 2020/8/6 - 22:16
**/
import java.io.*;
public class Demo02 {
    public static void main(String[] args) {
        int b = 0;
        FileInputStream in = null;
        FileOutputStream out = null;
        try {
            in = new FileInputStream("D:\\javaEx\\HelloWorld.java");
            out = new FileOutputStream("D:\\javaEx\\io\\HW.java");
            while ((b = in.read()) != -1) {
                out.write(b);
            }
            in.close();
            out.close();
        } catch (FileNotFoundException e2) {
            System.out.println("找不到指定文件");
            System.exit(-1);
        } catch (IOException e1) {
            System.out.println("文件复制错误");
            System.exit(-1);
        }
        System.out.println("文件已复制");
    }
}
2)Reader和Writer
(1)Reader举例
package com.stream;
/*
@author qw
@date 2020/8/6 - 22:23
**/
import java.io.*;
public class Demo03 {
    public static void main(String[] args) {
        FileReader fr = null;
        int c = 0;
        try {
            fr=new FileReader("D:\\javaEx\\io\\TestFileReader.java");
            int ln = 0;
            while ((c = fr.read()) != -1) {
                System.out.println((char)c);
            }
            fr.close();
        }catch (FileNotFoundException e) {
            System.out.println("找不到指定文件");
        } catch (IOException e) {
            System.out.println("文件复制错误");
        }   
    }
}
(2)Writer举例
package com.stream;
/*
@author qw
@date 2020/8/6 - 22:23
**/
import java.io.*;
public class Demo04 {
    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            fw = new FileWriter("D:\\javaEx\\unicode.dat");
            for (int i = 0; i < 1000; i++) {
                fw.write(i);
            }
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("文件写入错误");
            System.exit(-1);
        }
    }
}

5.缓冲流
  • 缓冲流要“套接“在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了 一些新的方法

  • 提供了四种缓冲流:BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream

  • 注意:

    ①缓冲输入流支持其父类的mark和reset方法

    ②BufferedReader提供了readLine方法用于读取一行字符串(以\r或\n分隔)

    ③BufferedWriter提供了newLine用于写入一个行分隔符

    ④对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush方法使内存中的数据立刻写出

1)BufferedInputStream举例

    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("D:\\javaEx\\HelloWorld.java");
            BufferedInputStream bis = new BufferedInputStream(fis);
            int c = 0;
            System.out.println(bis.read());
            bis.mark(100);//标记从第100个字节开始读
            for (int i = 0; i < 10 && (c = bis.read()) != -1; i++) {
                System.out.print((char) c + " ");
            }
            bis.reset();//重置恢复到 第100
            bis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2)BufferedReader和BufferedWriter举例

    public static void main(String[] args) {
        try {
            BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\javaEx\\dat2.txt"));
            BufferedReader br = new BufferedReader(new FileReader("D:\\javaEx\\HelloWorld.java"));
            String s = null;
            for (int i = 0; i < 100; i++) {
                s = String.valueOf(Math.random());
                bw.write(s);
                bw.newLine();//换新行
            }
            bw.flush();
            while ((s = br.readLine())!= null) {
                System.out.println(s);
            }
            bw.close();
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

6.数据流
  • DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,它属于处理流,需要分别“套接”在InputStream和OutputStream类型的节点流上
  • DataInputStream和DataOutputStream提供了可以存取与机器无关的Java原始类型数据(如:int,double等)的方法
  • DataInputStream和DataOutputStream的构造方法为:
    • DataInputStream(InputStream in)
    • DataOutputStream(OutputStream out)
package com.stream;
/*
@author qw
@date 2020/8/7 - 15:58
**/
import java.io.*;
public class Demo09 {
    public static void main(String[] args) {
        //字节数组输出流在内存中创建一个字节数组缓冲区,
        //所有发送到输出流的数据保存在该字节数组缓冲区中
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        try {
            dos.writeDouble(Math.random());
            dos.writeBoolean(true);
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            System.out.println(bais.available()); //9
            DataInputStream dis = new DataInputStream(bais);
            System.out.println(dis.readDouble());//先写入的先读出
            System.out.println(dis.readBoolean());
            dos.close();
            dis.close();
        } catch (IOException e) {
            e.printStackTrce();
        }
    }
}

7.转换流
  • InputStreamReader和OutputStreamWriter用于字节数据到字符数据之间的转换
  • InputStreamReader需要和InputStream“套接”
  • OutputStreamWriter需要和OutputStream“套接”
  • 转换流在构造时可以指定其编码集合,例如:InputStream isr = new InputStreamReader(System.in,“ISO8859_1”)
package com.stream;
/*
@author qw
@date 2020/8/7 - 10:24
**/
import java.io.*;
public class Demo07 {
    public static void main(String[] args) {
        try {//使用处理流后,能够直接写入字符串,而不用拆分成字节再写入
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\javaEx\\char.txt"));
            osw.write("microsoftdjfhvysm");
            System.out.println(osw.getEncoding());//GBK
            osw.close();
            osw = new OutputStreamWriter(new FileOutputStream("D:\\javaEx\\char.txt", true), "ISO8859_1");
            //true表示,在原文档的基础上继续添加
            osw.write("microsoftdjfhvysm");                                   
            System.out.println(osw.getEncoding());//ISO8859_1
            osw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package com.stream;
/*
@author qw
@date 2020/8/7 - 11:11
**/
import java.io.*;
public class Demo08 {
    public static void main(String[] args) {
        InputStreamReader isr = new InputStreamReader(System.in);//键盘输入
        BufferedReader br = new BufferedReader(isr);
        String s = null;
        try {
            s = br.readLine();
            while (s != null) {
                if (s.equalsIgnoreCase("exit")) {
                    break;
                }
                System.out.println(s.toUpperCase());
                s = br.readLine();
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

8.Print流
  • PrintWriter和PrintStream都属于输出流,分别针对字符和字节
  • PrintWriter和PrintStream提供了重载的print
  • Println方法用于多种数据类型的输出
  • PrintWriter和PrintStream的输出操作不会抛出异常,用于通过检测错误状态获取错误信息
  • PrintWriter和PrintStream有自动flush功能
package com.stream;
/*
@author qw
@date 2020/8/7 - 21:18
**/
import java.io.*;
public class Demo10 {
    public static void main(String[] args) {
        PrintStream ps = null;
        try {
            FileOutputStream fos = new FileOutputStream("D:\\javaEx\\log.dat");
            ps = new PrintStream(fos);
            //PrintStream处理流套接在FileOutputStream上
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (ps != null) {
            System.setOut(ps);//设置新的out,指向了ps
        }
        int ln = 0;
        for (char c = 0; c <= 60000; c++) {
            System.out.print(c + " ");
            //使用新的out,将数据print在log.dat文件中
            if (ln++ >= 100) {
                System.out.println();
                ln = 0;
            }
        }
    }
}
package com.stream;
/*
@author qw
@date 2020/8/7 - 21:40
**/
import java.util.*;
import java.io.*;
public class Demo11 {
    public static void main(String[] args) {
        String s = null;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
            FileWriter fw = new FileWriter("D:\\javaEx\\logfile.log", true);
            //true表示:继续写入数据时,追加在原文件的后面;往往用于做日志的记录
            PrintWriter log = new PrintWriter(fw);
            //在FileWriter上套接PrintWriter
            while ((s = br.readLine()) != null) {
                if (s.equalsIgnoreCase("exit")) {
                    break;
                }
                System.out.println(s.toUpperCase());
                log.println("------");
                log.println(s.toUpperCase());
                log.flush();
            }
            log.println("===" + new Date() + "===");
            log.flush();
            log.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

9.Object流
  • 直接将Object写入或读出
1)transient关键字
  • 用来修饰成员变量
2)serializable接口
  • serializable 接口:序列化,可以被序列化的,若确实需要将某个类的对象写在硬盘上或网络上,想把他们序列化成一个字节流,就必须实现这个这个接口(标记性接口, 用来标记一下,这个类的对象可以被序列化,那么这个类到底是怎么被序列化的,自己不能控制,是 JDK 直接帮你控制这个类的对象的序列化过程).
3)externalizable接口
  • 通过 readExternal()、 writeExternal() 这个两个方法,自己实现序列化过程.
package com.stream;
/*
@author qw
@date 2020/8/7 - 22:28
**/
import java.io.*;
public class Demo12 {
    public static void main(String[] args) {
        T t = new T();
        t.j = 16;
        try {
            FileOutputStream fos = new FileOutputStream("D:\\javaEx\\io\\testobjectio.dat");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(t);
            oos.flush();
            oos.close();

            FileInputStream fis = new FileInputStream("D:\\javaEx\\io\\testobjectio.dat");
            ObjectInputStream ois = new ObjectInputStream(fis);
            T tReaded = (T) ois.readObject();
            System.out.println(tReaded.i + " " + tReaded.j + " " + tReaded.d + " " + tReaded.k);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class T implements Serializable{
    int i=10;
    int j=9;
    double d=2.3;
    transient int k=15;
    //该参数不需要序列化,即它的值不写入到计算机中,最后读取是零
}

学习视频——b站尚学堂马士兵Java视频教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值