数据流是指一组有顺序的,有起点和终点的字节集合。

  最初的版本中,java.io 包中的流只有普通的字节流,即以 byte 为基本处理单位的流。字节流用来读写 8 位的数据,由于不会对数据做任何转换,因此可以用来处理二进制的数据。在后来的版本中,java.io 包中又加入了专门用于字符流处理的类,这个以 Reader 和 Writer 为基础派生的一系列的类。

  另外,为了使对象的状态能够方便地永久保存下来,java.io 包中又提供了以字节流为基础的用于对象的永久化保存状态的机制,通过实现 ObjectInput 和 ObjectOutput 接口来完成。

  InputStream 和 OutputStream 两个类都是抽象类,抽象类不能进行实例化。在实际应用中我们要用到一系列基本数据流类,都是他们的子类,在实现其父类方法的同时又都定义了其特有的功能。

  • 输入数据流

    • 输入数据流中提供的主要数据操作方法

      • int read():从输入流中读取一个字节的二进制数据
      • int read(byte[] b):将多个字节读到数组中,填满整个数组
      • int read(byte[] b, int off, int len):从输入流中读取长度为len的数据,从数组 b 中下标为 off 的位置开始放置读入的数据,读毕返回读取的字节数
      • 以上三个方法中,所读取的数据都默认为字节类型。当输入流读取结束时,会得到 -1,以标志数据流的结束。第一个 read() 方法将读取的一个字节作为低位,形成一个 0~255 的 int 类型的数值返回
      • void close():关闭数据流
      • long skip(long l):跳过数据流中指定数量的字节不读取,返回值表示实际跳过的字节数
      • 对于数据流中的字节的读取通常是按从头到尾顺序进行的,如果需要以反方向读取,则需要使用回推(Push Back)操作,支持回推操作的数据流中常用的方法如下
      • boolean markSupported():用于测试数据流是否支持回推操作,当一个数据流支持 mark() 和 reset() 方法时返回 true,否则返回 false
      • void mark(int markarea):用于标记数据流的当前位置,并划出一个缓冲区,其大小至少为指定参数的大小
      • void reset():将输入流重新定位到对此流最后调用 mark 方法时的位置
  • 输出数据流

    • 输出数据流中提供的主要数据操作方法

      • void write(int i):将字节 i 写入到数据流中,它只输出所读入参数的最低 8 位
      • void write(byte b[]):将数组 b[] 中的全部 b.length 个字节写入数据流
      • void write(byte b[], int off, int len):将数组 b[] 中从下标 off 开始的 len 个字节写入数据流。元素 b[off] 是此操作写入的第一个字节, b[off + len - 1] 是此操作写入的最后一个字节
      • void close():当结束对输出数据流的操作时应该将其关闭
      • void flush():刷新此输出流并强制写出所有缓冲的输出字节

基本字节数据流类


  • 文件数据流

    • 文件数据流包括 FileInputStream 和 FileOutputStream,这两个类用来进行文件的I/O处理,其数据源或数据终点都应当是文件。通过所提供的方法可以对本机上的文件进行操作,但是不支持方法 mark() 和 reset()

    • 示例(1)

      • FileInputStream fis = new FileInputStream("myFile.txt");
        // 同样可以使用 FileOutputStream 向文件中输出字节
        FIleOutputStream out = new FileOutputStream("myFile.txt");
    • 示例(2)

      • FIleOutputStream out = new FileOutputStream("myFile.txt");
        out.wirte('H');
        out.wirte(69);
        out.wirte(76);
        out.wirte('L');
        out.wirte('O');
        out.close();
        FIleInputStream fis = new FileInputStream("myFile.txt");
        while(fis.available() > 0){
        System.out.print(fis.read() + " ");
        }
        fis.close();
  • 过滤器数据流(直接继承与FilterInputStream、FilterOutputStream)

    • 缓冲区数据流
      • 一个过滤器数据流在创建时与一个已经存在的数据流相连,这样在从这样的数据流中读取数据时,它提供的是对一个原始输入数据流的内容进行了特定处理的数据。缓冲区数据流有BufferedInputStream 和 BufferedOutinputStream,它们是在数据流上增加了一个缓冲区,都属于过滤器数据流。当读写数据时,数据以块为单位先进入缓冲区(块大小可以进行设置),其后的读写操作则作用于缓冲区。采用这个办法可以降低不同硬件设备之间速度的差异,提高I/O操作的效率

      • 示例(使用默认缓冲区大小)

      • FileInputStream fis = new FileInputStream("myFile.txt");
        InputStream is = new BufferedInputStream(fis);
        FileOutputStream fos = new FileOutputStream("myFile.txt");
        OutputStream is = new BufferedOutputStream(fos);
      • 示例(自定义设置缓冲区大小)

      • FileInputStream fis = new FileInputStream("myFile.txt");
        InputStream is = new BufferedInputStream(fis, 1024);
        FileOutputStream fos = new FileOutputStream("myFile.txt");
        OutputStream is = new BufferedOutputStream(fos, 1024);
      • 一般在关闭一个缓冲区输出流之前,应先使用 flush() 方法,强制输出剩余数据,以确保缓冲区内的所有数据全部写入输出流

    • 数据数据流
      • 前面提到的数据流中处理数据都是指字节或字节数组,这是进行数据传输时系统默认的数据类型。但实际上所处理的数据并非只有这两种类型,遇到这种情况时就要应用一种专门的数据流来处理。DataInputStream 和 DataOutputStream 就是这样的两个过滤器数据流,它们允许通过数据流来读写 Java 基本类型

      • 示例

      • DataInputStream dis = new DataInputStream(is);
        DataOutputStream ous = new DataOutputStream(os);
      • 常用方法

      • // DataInputStream 常用方法
        
        byte readByte()
        long readLong()
        doublue readDouble()
        boolean readBoolean()
        String readUTF()
        int readInt()
        float readFloat()
        short readShort()
        char readChar() // DataOutputStream 常用方法 void writeByte(int aByte)
        void writeLong(long aLong)
        void writeDouble(double aBouble)
        void writeBoolean(boolean aBool)
        void writeUTF(String aString)
        void writeInt(int aInt)
        void writeFloat(float aFloat)
        void writeShort(short aShort)
        void rwriteChar(char aChar)
      • 虽然这两个数据流定义了对字符串进行读写的方法,但是由于字符编码的原因,应该避免使用这些方法。Reader 和 Writer 重载了这两个方法,对字符进行操作时应当使用 Reader 和 Writer 两个系列类中的方法

  • 对象流

    • 能够输入/输出对象的流称为对象流。Java 通过 java.io 包中的 ObjectInputStream 和 ObjectOutputStream 两个类实现把对象写入文件数据流或从文件数据流中读出的功能

    • 示例

    • // 写对象数据流
      
      Date date = new Date();
      FileOutputStream fos = new FileOutputStream("date.ser");
      ObjectOutputStream oos = new ObjectOutputStream(fos);
      oos.writeObject(date);
      oos.close(); // 读对象数据流 Date date = null;
      FileInputStream fis = new FileInputStream("date.ser");
      ObjectInputStream ois = new ObjectInputStream(fis);
      date = (Date) ois.readObject(date);
      ois.close();
      System.out.println("Date serialized at " + date);
  • 序列化

    • 序列化的概念

      • 能够记录自己的状态以便将来得到复原的能力,称为对象的持久性(Persistence)。一个对象时可持久的,意味着它可以把这个对象存入内存或者磁盘等介质中,也就是把对象存为某种永久存储类型。对象通过数值来描述自己的状态,记录对象也就是记录下这些数值。把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化。序列化的主要任务是写出对象实例变量的数值。序列化是一种用来处理对象流的机制,所谓的对象流也就是将对象的内容进行流化。序列化是为了解决在对对象流进行读写操作时所引发的问题
    • Serializable 接口中没有定义任何方法,只是作为一个标记来指示实现该接口的类可以进行序列化,只有实现 Serializable 接口的类才能被序列化。当一个类实现 Serializable 接口时,表明该类加入了对象序列化协议

    • 序列化一个对象,必须与特定的对象输出/输入流联系起来,通过对象输出流/输入流将对象状态保存下来或者将对象状态恢复。通过 java.io 包中的 ObjectInputStream 和 ObjectOutputStream 两个类可以实现。writeObject() 和 readObject() 方法可以直接将对象保存到输出流中或者从输出流中读取一个对象

    • // 序列化
      
      public class Student implements Serializable {
      int id;
      String name;
      int age;
      String department;
      public Student(int id, String name, int age, String department) {
      this.id = id;
      this.name = name;
      this.age = age;
      this.department = department;
      }
      } // 对象的存储 Student stu = new Student(927103, "Li Ming", 16, "CSD");
      FileOutputStream fo = new FileOutputStream("data.ser");
      ObjectOutputStream so = new ObjectOutputStream(fo);
      so.writeObject(stu);
      so.close(); // 对象的恢复 Student stu;
      FileInputStream fi = new FileInputStream("data.ser");
      ObjectInputStream si = new ObjectInputStream(fi);
      stu = (Student)si.readObject();
      si.close();
      System.out.println("ID:" + stu.id + ";name:" + stu.name);
    • 对象结构表

      • 序列化只能保存对象的非静态成员变量,而不能保存任何成员方法和静态成员变量,并且保存的只是变量的值,对于变量的任何修饰符都不能保存,访问权限(public, protected, private)对于数据域的序列化没有影响
      • 有一些对象不具有可持久性,因为其数据的特性决定了它会经常变化,其状态只是瞬时的,这样的对象是无法保存起状态的,如 Thread 对象。对于这样的成员变量,必须用 transient 关键字标明,否则编译器将报错。任何用 transient 关键字标明的成员变量都不会被保存
      • 序列化可能涉及将对象存放到磁盘上或者再网络上发送数据,这时会产生安全问题。对于一些保密的数据,为了保证安全,不应保存在永久介质中,应在这些变量前加上 transient 关键字
      • 当数据变量是一个对象时,该对象的数据成员也可以被持久化。对象的数据结构或结构树,包括其子对象树在内,构成了这个对象的结构表
    • 示例

    • public class Student implements Serializable {
      public transient Thread myThread;
      private transient String customerID;
      private int total;
      }

基本字符流


  从 JDK1.1 开始,java.io 包中加入了专门用于字符流处理的类,它们是以 Reader 和 Writer 为基础派生的一系列类。

  一、读者(Reader)和写者(Writer)

    同其他语言使用 ASCII 字符集不同,Java 使用 Unicode 字符集来表示和字符。ASCII 字符集以一个字节(8bit)表示一个字符,可以认为一个字符就是一个字节(byte)。但是 Java 使用的 Unicode 是一种大字符集,用两个字节(16bit)来表示一个字符,这时字节与字符就不再相同。为实现与其他程序语言及不同平台的交互,Java 提供一种新的数据流处理方案称作 Reader 和 Writer。在 java.io 包中有许多不同类对其进行支持,其中最重要的是 InputStreamReader 和 OutputStreamWriter 类。这两个类是字节流和 Reader 和 Writer 的接口,用来在字节流和字符流之间作为中介。

    在英语国家中,字节编码采用 ISO8859_1 协议。ISO8859_1 是 Latin-1 编码系统映射到 ASCII 标准,能够在不同平台之间正确转换字符。

// 构造映射到 ASCII 码的标准的 InputStreamReader 的方法

InputStreamReader ir = new InputStreamReader(System.in, "8859_1");

// Reader 提供的方法

void close();
void mark(int readAheadLimit);
boolean markSupported();
int read();
int read(char[] cbuf);
int read(char[] cbuf, int off, int len);
boolean ready();
void reset();
long skip(long n); // Writer 提供的方法 void close();
void flush();
void write(char[] cbuf);
void write(char[] cbuf, int off, int len);
void write(int c);
void write(String str);
void write(String str, int off, int len);

  二、缓冲区读者和缓冲区写者

    java.io 中提供流缓冲流 BufferedReader 和 BufferedWriter。其构造方法与 BufferedInputStream 和 BufferedOutputStream 类似。另外,除了 read() 和 write() 方法外,还提供了整行字符的处理方法

    • 方法如下

      • public String readLine():BufferedReader 的方法,从输入流中读取一行字符,行结束标志为 '\n' 、'\r' 或者两者一起
      • public void newLine():BufferedWriter 的方法,向输出流中写入一个行结束标志
    • 示例

      • FileInputStream fis = new FileInputStream("data.ser");
        InputStreamReader dis = new InputStreamReader(fis);
        BufferedReader reader = new BufferedReader(dis);
        // BufferedReader reader = new BufferedReader(new FileReader("data.ser"));
        String s;
        while((s = reader.readLine()) != null) {
        System.out.println("read:" + s);
        }
        dis.close();
    • 当你写文件的时候,为了提高效率,写入的数据会先放入缓冲区,然后写入文件。因此有时候你需要主动调用 flush()方法

      • // FileWriter
        FileWriter fw = new FileWriter("D:/Test.txt");
        String s = "hello world";
        fw.write(s, 0, s.length());
        fw.flush(); //flush将缓冲区内容写入到问题件
        // OutputStreamWriter
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:/Test1.txt"));
        osw.write(s, 0, s.length());
        osw.flush();
        // PrintWriter
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(new
        FileOutputStream("D:/Test2.txt")), true);
        // PrintWriter pw = new PrintWriter(new FileWriter("D:/Test2.txt")); pw.println(s); // close AllWriter fw.close();
        osw.close();
        pw.close();
    • 文件拷贝
      • File file = new File("D:/Test.txt");
        File dest = new File("D:/new.txt");
        try {
        BufferedReader reader = new BufferedReader(new FileReader(file));
        BufferedWriter writer = new BufferedWriter(new FileWriter(dest));
        String line = reader.readLine();
        while(line!=null){
        writer.write(line);
        line = reader.readLine();
        }
        writer.flush();
        reader.close();
        writer.close();
        } catch (FileNotFoundException e) {
        e.printStackTrace();
        } catch (IOException e) {
        e.printStackTrace();
        }

Java IO 输入和输出流的更多相关文章

  1. java.IO输入输出流:过滤流:buffer流和data流

    java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? ...

  2. Java IO 输入输出流 详解 (一)***

    首先看个图: 这是Javaio 比较基本的一些处理流,除此之外我们还会提到一些比较深入的基于io的处理类,比如console类,SteamTokenzier,Externalizable接口,Seri ...

  3. java IO输入输出流中的各种字节流,字符流类

    字节流字节流主要是操作byte类型数据,也byte数组为准,主要操作类就是·字节输出流:OutputStream·字节输入流:InputStream字符流在程序中一个字符等于2个字节,那么java提供 ...

  4. java io 输入输出流

    数据流分类: 流序列中的数据既可以是未经加工的原始二进制数据, 也可以是经一定编码处理后符合某种格式规定的特定数据. 因此Java中的流分为两种: 1) 字节流:数据流中最小的数据单元是字节 2) 字 ...

  5. Java——IO(输入输出流)

     *  * 想要知道开发时用到哪些数据对象,只要通过四个明确即可:  * 1.明确源,和目的:  * 源: InputStream reader  * 目的: OutPutStream Write ...

  6. Java - io输入输出流 --转换流

    转换流  转换输出流 OutputStreamWriter: 说明: /* * OutputStreamWriter 这个类的作用 * 就是指定输出流的编码格式 * 这个类的构造方法 需要传递 一个输 ...

  7. Java IO输入输出流 字符数组流 ByteArrayOutputStream/ByteArrayInputStream

    private static void StringWriterAndReader() throws Exception { //字符串流(字符串的内存流) //字符串输入流 StringWriter ...

  8. Java IO输入输出流File 字节流

    public static void main(String[] args) throws IOException { //创建源 File f =new File("file/stream ...

  9. java IO输入输出流实现文本复制

随机推荐

  1. nginx负载均衡设置

    在nginx的配置文件[./conf/nginx.conf]中加入: upstream test.balance123.com { server 192.168.1.223:80; server 19 ...

  2. cdcqの省选膜你赛 题解

    题解: 第一题: 有一个很明显的性质:后面的修改不会对前面的询问做出影响,CDQ分治套上BIT即可. 第二题: 有一个类似于斜率的形式,分数规划套上树分治,码量稍大,细节稍多. 最后20W的点出题人原 ...

  3. Module.exports和exports的区别

    原文链接: https://www.ycjcl.cc/2017/02/10/module-exportshe-exportsde-qu-bie/ 学习Seajs时,看到了exports.doSomet ...

  4. PHP之面向对象PHP之面向对象(面向对象是什么)

    PHP之面向对象(面向对象是什么) 一.总结 一句话总结: 面向对象就是类:类都要 属性 和 方法 比如人:属性比如身高体重,方法比如吃饭喝水 面向对象中 ,方法即是函数 : 属性即是变量 ,只是面相 ...

  5. 分享知识-快乐自己:MySQL中的约束,添加约束,删除约束,以及一些其他修饰

    创建数据库: CREATE DATABASES 数据库名: 选择数据库: USE 数据库名: 删除数据库: DROP DATAVBASE 数据库名: 创建表: CREATE TABLE IF NOT ...

  6. hdu 1002 A + B Problem II(大数)

    题意:就是求a+b (a,b都不超过1000位) 思路:用数组存储 第一道大数的题目,虽然很水,纪念一下! 代码: #include<cstdio> #include<cstring ...

  7. google IO大会

    怎么参加一次 Google I/O?大概要多少预算? Google I/O(参加Goole I/O 是我的一个梦想,因为我是Google死忠,想亲自去Google总部看看,所以想知道这些) 费用构成: ...

  8. SocketSessionConfig参数设制

    Mina 是一个韩国人写的基本java NIO的一个高性能的传输框架,我们的搜索就是基本它作为一个搜索服务开放接口了.对于系统的TIME_WAIT过多,造成服务器的负载过高,这个问题我也不用多说了,这 ...

  9. C/C++的四大内存分区和常量的存储位置

    原文:https://blog.csdn.net/k346k346/article/details/45592329 正确的理解C/C++程序的内存分区,是合格程序猿的基本要求. 网络上流形两大版本内 ...

  10. xgboost算法原理

    XGBoost是2014年3月陈天奇博士提出的,是基于CART树的一种boosting算法,XGBoost使用CART树有两点原因:对于分类问题,CART树的叶子结点对应的值是一个实际的分数,而非一个 ...