08 - JavaSE之IO流

IO流

JAVA流式输入输出原理:可以想象成一根管道怼到文件上,另一端是我们程序,然后流的输入输出都是按照程序本身作为第一人称说明的。比如 input,对于我们程序来说就是有数据输入我们程序,output就是我们程序输出数据到文件等。对象不能搞错了,否则就南辕北辙了。

  • 通过不同的角度对流的输入输出功能进行分类:
  1. 按数据流的方向分为:输入流和输出流
  2. 按处理数据单位不同分为:字节流和字符流(2个字节)
  3. 按功能不同分为:节点流和处理流


输入流和输出流

  • JAVA JDK 所提供的所有流类型位于包 java.io 内部,分别继承自下面四个抽象流类型:

    字节流             字符流   

    输入流 InputStream Reader

    输出流 OutputStream Writer



节点流和处理流

  • 节点流为可以从一个特定的数据源(节点)读写数据(如:文件,内存)。

节点流可以简单的理解为:一根管道直接怼到文件上,进行数据的读写。

  • 处理流是连接在已存在的节点流或处理流上的,通过读数据进行处理(过滤等)为程序提供更加强大的读写功能。

处理流可以简单的理解为:套在节点流管道的管子,可以对流过节点流的数据进行处理,过滤等操作。



InputStream 抽象类

  • 继承自 InputStream的流都是用于向程序中输入数据,且数据的单位为字节。
  • 继承自 InputStream的类有如下等:(加粗为节点流,未加粗为处理流)

FileInputStream

PipedInputStream

FilterInputStream

ByteArrayInputStream

SequenceInputStream

StringBufferInputStream

ObjectInputStream

  • InputStream的基本方法

    int read() throws IOException

    int read(byte[] buffer) throws IOException

    int read(byte[] buffer, int offset, int length) throws IOException

    void close() throws IOException



OutputStream 抽象类

  • 继承自 OutputStream的流都是用于从程序中输出数据,且数据的单位为字节。
  • 继承自 OutputStream的类有如下等:(加粗为节点流,未加粗为处理流)

FileOutputStream

PipedOutputStream

FilterOutputStream

ByteArrayOutputStream

ObjectOutputStream

  • OutputStream 基本方法

    void write(int b) throws IOException

    void write(byte[] b) throws IOException

    void write(byte[] b, int off, int len) throws IOException

    void close() throws IOException

    void flush() throws IOException // 在关闭输出流之前使用,将输出缓冲区的数据写到目的地



Reader

  • 继承自 Reader 的流都是用于程序从外部读入数据,且数据的单位是字符(2个字节)。
  • 如下为继承自Reader的流。(加粗为节点流,未加粗为处理流)

BufferedReader

CharArrayReader

InputStreamReader

FilterReader

PipedReader

StringReader

  • Reader的基本方法 - 略


Writer

  • 继承自 Writer的流都是用于程序向外部写入数据,且数据的单位是字符(2个字节)。
  • 如下为继承自Writer的流。(加粗为节点流,未加粗为处理流)

BufferedWriter

CharArrayWriter

OutputStreamWriter

FilterWriter

PipedWriter

StringWriter

  • Writer的基本方法 - 略


节点流类型

类型 字节流 字符流

File(文件) FileInputStream / FileOutputStream FileReader / FileWriter

Memory Array ByteArrayInputStream / ByteArrayOutputStream CharArrayReader / CharArrayWriter

Memory String -- StringReader / StringWriter

Pipe(管道) PipedInputStream / PipedOutputStream PipedReader / PipedWriter

举例1:FileInputStream

import java.io.*;
public class Test {
    public static void main(String[] args) {
        int b = 0;
        long num = 0;
        FileInputStream ln = null;

        try {
             ln = new FileInputStream("I:/Java/Demo/test.txt");
        } catch (FileNotFoundException e) {
            System.out.println("文件不存在!");
            System.exit(-1);
        }

        try {
            while ((b=ln.read()) != -1) {
                System.out.print((char)b);
                num++;
            }
            ln.close();
            System.out.println();
            System.out.println("共读出:" + num + "个字节。");
        } catch (IOException e) {
            System.out.println("文件读取失败!");
            System.exit(-1);
        }
    }
}

举例2:FileOutputStream

import java.io.*;
public class Test {
    public static void main(String[] args) {
        int b = 0;
        FileInputStream in = null;
        FileOutputStream out = null;

        try {
            in = new FileInputStream("I:/Java/Demo/test.txt");
            out = new FileOutputStream("I:/Java/Demo/newtest.txt");

            while((b=in.read()) != -1) {
                out.write(b);
            }
        } catch (FileNotFoundException e) {
            System.out.println("文件不存在!");
            System.exit(-1);

        } catch (IOException e) {
            System.out.println("文件复制失败!");
            System.exit(-2);
        }
        System.out.println("文件复制成功!");
    }
}


处理流类型

处理类型 字节流 字符流

Buffering BufferedInputStream/BufferedOutputStream BufferedReader/BufferedWriter

Filtering FilterInputStream/FilterOutputStream FilterReader/FilterWriter

Converting between bytes and character -- InputStreamReader/OutputStreamWriter

Object Serialization ObjectInputStream/ObjectOutputStream --

Data conversion DataInputStream/DataOutputStream --

Counting LineNumberInputStream LineNumberReader

Peeking ahead PushbackInputStream PushbackReader

Printing PrintStream PrintWriter

  • 缓冲流(以Buffered开头)
  1. 缓冲流套接在相应的节点流上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法。

    BufferedReader / BufferedWriter / BufferedInputStream / BufferedOutputStream

  2. 缓冲流支持其父类的 mark 和 reset 方法。
  3. BufferedReader 提供了 readLine 方法用于读取一行字符串(以\r或者\n分割)
  4. BufferedWriter 提供了 newLine 用于写入一个行分隔符。
  5. 对于输出的缓冲流,写出的数据会先在内存中缓存,使用 flush 方法将会使内存中的数据立刻写出。

举例1:

import java.io.*;
public class Test {
    public static void main(String[] args) {
        int b = 0;
        FileInputStream in = null;
        BufferedInputStream bin = null;

        try {
            in = new FileInputStream("I:/Java/Demo/test.txt");
            bin = new BufferedInputStream(in);

            bin.mark(100);

            for(int i=0; (i<=10)&&(b=bin.read()) != -1; i++) {
                System.out.print((char)b);
            }

            bin.reset();
            System.out.println();

            for(int i=0; (i<=10)&&(b=bin.read()) != -1; i++) {
                System.out.print((char)b);
            }

        } catch (FileNotFoundException e) {
            System.out.println("文件不存在!");
            System.exit(-1);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

举例2:

import java.io.*;
public class Test {
    public static void main(String[] args) {
        String s = null;
        try {
            BufferedWriter bw = new BufferedWriter(new FileWriter("I:/Java/Demo/test.txt"));
            BufferedReader br = new BufferedReader(new FileReader("I:/Java/Demo/test.txt"));

            for(int i=0; i<100; i++) {
                s = Double.toString(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();
        }
    }
}
//0.7365309652822098
//0.577186775602007
//0.11736466966949166
//0.2998096440959087
//0.23859539950503672
//...
  • 转换流
  1. InputStreamReader 和 OutputStreamWriter 用于字节数据到字符数据之间的转换。
  2. InputStreamReader 需要和 InputStream 套接。
  3. OutputStreamWriter 需要和 OutputStream 套接。
  4. 转换流在构造时可以指定其编码结合,例如: InputStream is = new InputStreamReader(System.in, "ISO8859_1")

举例1:

import java.io.*;
public class Test {
    public static void main(String[] args) {
        try {
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("I:/Java/Demo/test.txt"));
            osw.write("1234567890");
            System.out.println(osw.getEncoding());
            osw.flush();
            osw.close();

            osw = new OutputStreamWriter(new FileOutputStream("I:/Java/Demo/test.txt", true), "ISO8859_1");
            osw.write("abcdefghijklmn");
            System.out.println(osw.getEncoding());
            osw.flush();
            osw.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

举例2:

import java.io.*;
public class Test {
    public static void main(String[] args) {
        try {
            String s = null;
            InputStreamReader isr = new InputStreamReader(System.in);
            BufferedReader br = new BufferedReader(isr);

            while((s = br.readLine()) != null) {
                if(s.equalsIgnoreCase("exit")) {
                    break;
                }
                System.out.println(s);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 数据流
  1. DataInputStream 和 DataOutputStream 分别继承自 InputStream 和 OutputStream,它属于处理流,需要分别套接在 InputStream 和 OutputStream 类型的节点流上。
  2. DataInputStream 和 DataOutputStream 提供了可以存取与机器无关的 Java 原始类型数据(如:int,double 等)的方法。
  3. DataInputStream 和 DataOutputStream 的构造方法为:

    DataInputStream (InputStream in)

    DataOutputStream (OutputStream out)

数据流的作用?

比如,我们如何存储一个很大的数到文件?我们之前的方法是将其转换成字符串存储,可不可以直接存储呢?数据流可以。它提供了很多方法用于存储基础数据类型的数据,参看 API 文档。

举例1:

import java.io.*;
public class Test {
    public static void main(String[] args) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 在内存自动生成一个 Byte[] 数组
        DataOutputStream dos = new DataOutputStream(baos);

        try {
            dos.writeDouble(Math.random());
            dos.writeBoolean(true);

            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            System.out.println(bais.available());

            DataInputStream dis = new DataInputStream(bais);

            System.out.println(dis.readDouble());
            System.out.println(dis.readBoolean());

            dos.close();
            dis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

问题:我们写一个 double,写一个boolean写到哪里了呢?

其实,在我们 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 的时候,就在内存中开辟了一块空间,用来将程序要写入的数据写到这片内存中。

还有,在读数据的时候,由于这片内存的分配是按照队列的方式分配的,所以先写进去的数据要先读出来,如果如上面程序那样,先读boolean的话,就会读取到double 8个字节的第一个字节上,切记!

  • Print 流(打印流)
  1. PrintWriter 和 PrintStream 都属于输出流,分别针对与字符和字节。
  2. PrintWriter 和 PrintStream 提供了重载的 print println 方法用于多种数据类型的输出。
  3. PrintWriter 和 PrintStream 的输出操作不会抛出异常,用户通过检测错误状态获取错误信息。
  4. PrintWriter 和 PrintStream 有自动 flush 功能。

    PrintWriter(PrintWriter out)

    PrintWriter(Writer out, boolean autoFlush)

    PrintWriter(OutputStream out)

    PrintWriter(OutputStream out, boolean autoFlush)

    PrintStream(OutputStream out)

    PrintStream(OutputStream out, boolean autoFlush)

举例1:

import java.io.*;
public class Test {
    public static void main(String[] args) {
        PrintStream ps = null;

        try {
            FileOutputStream fos = new FileOutputStream("I:\\Java\\Demo\\test.txt");

            ps = new PrintStream(fos);

            if(null != ps) {
                System.setOut(ps);
            }

            for(int i=0; i<60000; i++) {
                System.out.print((char)i + " ");

                if(i%50 == 0) {
                    System.out.println();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

将输出打印语句重定向到 test.txt 文件中。

举例2:

import java.io.*;

public class Test {
    public static void main(String[] args) {
        String filename = args[0];

        if (filename != null) {
            list(filename, System.out);
        }
    }

    public static void list(String f, PrintStream fs) {
        try {
            String s = null;
            BufferedReader br = new BufferedReader(new FileReader(f));

            while ((s = br.readLine()) != null) {
                fs.println(s);
            }
            br.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

将 args[0] 所写的文件名对应的文件打印到终端。

举例3:

import java.io.*;
import java.util.*;

public class Test {
    public static void main(String[] args) {
        String s = null;

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        try {
            FileWriter fw = new FileWriter("I:/Java/Demo/log.txt", true);
            PrintWriter log = new PrintWriter(fw);

            while((s=br.readLine()) != null) {
                if(s.equalsIgnoreCase("exit")) {
                    break;
                }
                System.out.println(s);
                log.println("------");
                log.println(s);
                log.flush(); // 可以省略

            }
            log.println("--- " + new Date() + " ---");
            log.flush(); // 可以省略
            log.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

将从终端输入的内容作为 log 写到 log.txt 文件里面。

  • Object 流

Object 流的作用:当我们存储一个元素的时候,(比如在画图软件上画了一个圆)我们的圆有很多属性,原点位置,半径大小,颜色,粗细等,既然每一个属性都需要存储,而且这些属性都在一个 Object 对象里面,那么我们为什么不直接写整个 Object呢?(这叫序列化。)

注意:当你 new 一个 Object 的时候,不单单只有你的属性,还有一些比如 Object的版本号,this,super 等。

举例:

import java.io.*;
public class Test {
    public static void main(String[] args) {
        TmpClass tm = new TmpClass();
        tm.a  =10;
        tm.d = false;

        try {
            FileOutputStream fos = new FileOutputStream("I:/Java/Demo/text.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);

            oos.writeObject(tm);
            oos.flush();
            oos.close();

            FileInputStream fis = new FileInputStream("I:/Java/Demo/text.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
            TmpClass t = (TmpClass) ois.readObject();
            System.out.println(t.a + " " + t.b + " " + t.c + " " + t.d);
        } catch (ClassNotFoundException c) {
            System.out.println("读取文件失败");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class TmpClass implements Serializable {
    int a = 1;
    int b = 2;
    double c = 3.0;
    boolean d = true;
}
  • Serializable 接口
  1. 可以被序列化的,如果想把一个类的对象,写到硬盘或者网络,想把这个对象序列化成一个字节流的话,必须要实现这个接口。
  2. 这个接口没有任何方法,是一个空接口,是一个标记性接口,它只是给编译器看的,编译器看到后就知道这个类的对象时可以被序列化的,是可以整个写入文件的。
  • tansient关键字
  1. 使用方法,修饰成员变量。

    class TmpClass implements Serializable {

    int a = 1;

    int b = 2;

    tansient double c = 3.0;

    boolean d = true;

    }

  2. transient 表示透明的意思,就是说在一个类的对象序列化的时候不予考虑,就是将这个类的对象写入文件的时候,不写这个被transient 修饰的成员变量,那么我们再读出来的时候就是默认值(如上,c 读出来的时候是 0.0)
  • externalizable 接口
  1. 可以理解为个性化的 Serializable 接口,externalizable 接口是继承 Serializable 接口得到的,相当于自己控制序列化的过程。(了解就好)


总结

  • 本章复习方法:把所有的名字,关键字写到一张纸上,每天看看想想自己,给朕看半个时辰。—— 康熙

原文地址:https://www.cnblogs.com/lvonve/p/8323649.html

时间: 2024-08-03 16:01:38

08 - JavaSE之IO流的相关文章

基于JavaSE阶段的IO流详解

1.IO流基本概述 在Java语言中定义了许多针对不同的传输方式,最基本的就是输入输出流(俗称IO流),IO流是属于java.io包下的内容,在JavaSE阶段主要学下图所示的: 其中从图中可知,所有输入流类都是抽象类,是InputStream或者抽象类Reader的子类:而所有输出流都是抽象类,是OutputStream或者Writer的子类.输入输出流的定义是根据流向所决定的,我们可以是本地为一个实体物质,从外界往本地输入,按照本地的状态就是读取,反之,从本地向外写入就是输出.IO流是最基本

6.IO流(2016年10月07日01:08:06创建)

分类 输入流 大致方法 分类 流向:输入流与输出流 数据: 字节流 字符流 功能: 节点流:包裹源头 处理流:增强功能,提高性能 输入流 大致方法 关于输入流的问题大致分四步: 设立代理 建立管道(通用性) 数据装箱(效能) 结尾手工 以下是个人理解 处理IO流的软件相当一个搬运公司,真实文件好比是一间需要搬运的房子(包括房子里的一切). 1.设立代理: File类建立的对象貌似拥有文件的身份但却不是文件,因为没有内容,就像是一个影子.除了内容,它几乎可以以假乱真.验证,读取大小,设立目录,删除

JavaSE 学习笔记之IO流(二十二)

IO流:用于处理设备上数据. 流:可以理解数据的流动,就是一个数据流.IO流最终要以对象来体现,对象都存在IO包中. 流也进行分类: 1:输入流(读)和输出流(写). 2:因为处理的数据不同,分为字节流和字符流. 字节流:处理字节数据的流对象.设备上的数据无论是图片或者dvd,文字,它们都以二进制存储的.二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节.意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据. 那么为什么要有字符流呢?因为字符每个国

JavaSE(一) IO类层次关系和各种IO流的用法总结

今天把IO流的这一知点进行一下总结,因为在之前使用io流的时候,就只知道几个重点常用的IO类,比如FileInputStream,BufferedInputStream(缓冲流)等等,但是不知道它处于整个IO体系中的什么位置,对于其中的整个IO体系一点不了解,每次使用的时候都需要百度查看用法例子,这就说明自己对这块的知识有所欠缺,所以今天,来详细的分析,解剖一下IO的整个结构. 借鉴博文:http://www.cnblogs.com/skywang12345/p/io_01.html  该博主写

一、javaSE (二十)递归、IO流、自学字符流

1:递归(理解) (1)方法定义中调用方法本身的现象 举例;老和尚給小和尚讲故事,我们学编程 (2)递归的注意事项; A:要有出口,否则就是死递归 B:次数不能过多,否则内存溢出 C:构造方法不能递归使用 (3)递归的案例 A:递归求阶乘 B:兔子问题 C:递归输出指定目录下所有指定后缀名的文件绝对路径 D:递归删除带内容的目录(小心使用) 2:IO流(掌握) (1);O用于在设备间进行数据传输的操作 (2)分类 A:流向 输入流     读取数据 输出流     写出数据 B:数据类型 字节流

JavaSE IO流学习总结

IO流 io流分为字节流和字符流 字节流:输入流父类 InputStream 常用的子类有 FileInputStream BufferedInputStream ? 输出流父类OutputStream 常用的子类有 FileOutputStream BfferedOutputStream 字符流:输入流父类 Reader 常用的子类有BufferedReader InputStreamReader ? 输出流父类 Writer 常用的子类有BufferedWriter OutputStream

java(九)IO流

IO流: IO流是用来处理设备之间的数据传输的. java对数据的操作是通过流的方式. java用于操作流的对象都在IO包中. 流按操作的数据分为两种:字符流和字节流. 字符流的由来:字符流其实就是字节流读取文字字节数据后,不直接操作而是先查指定的编码表,  获取对应的文字.再对这个文字进行操作. 简单说,就是字符流=字节流+编码表. 字节流的抽象基类(就是顶层父类):InputStream,OutputStream 字符流的抽象基类:Reader,Writer 这些体系的子类都以父类名作为后缀

JavaSE_ IO流 总目录(19~22)

黑马程序员_JavaSE学习总结第19天_IO流119.01 集合的特点和数据结构总结19.02 如何选择使用哪种集合19.03 集合常见功能和遍历方式总结19.04 异常的概述和分类19.05 JVM默认处理异常19.06 try...catch的方式处理异常1(一个异常)19.07 try...catch的方式处理异常2(两个异常)19.08 JDK7针对多个异常的处理方案19.09 编译期异常和运行期异常的区别19.10 Throwable的几个常见方法19.11 throws的方式处理异

慕课网_文件传输基础——Java IO流

fadf 第1章 文件的编码 1-1 文件的编码 (15:07) 第2章 File 类的使用 2-1 File 类常用 API 介绍 (10:50) import java.io.File; import java.io.IOException; public class FileDemo { public static void main(String[] args) { File file = new File("E:\\helloworld\\java"); System.out