14_IO_其他流


数据流

DataOutputStream数据输出流

数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中
然后,应用程序可以使用数据输入流将数据读入。

构造方法

DataOutputStream(OutputStream out)        
// 创建一个新的数据输出流,将数据写入指定基础输出流。

成员方法

在这里插入图片描述

  • 每种数据类型都有1个对应的write方法

DataInputStream数据输入流

数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型

构造方法

DataInputStream(InputStream in)       
// 使用指定的底层 InputStream 创建一个 DataInputStream。

成员方法

在这里插入图片描述

  • 每种数据类型都有1个对应的read方法

eg:

/*
通过数据流写数据
 */
 
// 1. 创建数据输出流对象
DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream("a.txt"));

// 2. writeInt
dataOutputStream.writeInt(1000);

// 3. writeDouble
dataOutputStream.writeDouble(3.14);

// 4. close
dataOutputStream.close();

/*
通过数据流读取数据
 */

// 1. 创建数据输入流对象
DataInputStream dataInputStream = new DataInputStream(new FileInputStream("a.txt"));

// 2. readInt
int readint = dataInputStream.readInt();
System.out.println(readint);

// 3. readDouble
double readdouble = dataInputStream.readDouble();
System.out.println(readdouble);

// 4. close
dataInputStream.close();

注意事项

  • 读取的顺序要跟写的顺序保持一致

打印流

核心思想: 把不同的数据类型转换成String

需求

  • 定义一个类Printer
  • 定义成员变量OutputStream
  • 定义5个方法
    • int的方法 void printInt(int a)
    • int并且换行的方法 void printIntLn(int a)
    • double的方法 void printDouble(double a)
    • double并且换行的方法 void printDoubleLn(double a)
    • 写一个close方法 void close()

eg:


class Printer{
   
    // 定义成员变量OutputStream
    OutputStream out;

    public Printer(OutputStream out){
   
        this.out = out;
    }

    // 写int的方法  void printInt(int a)
    public void printInt(int a) throws IOException {
   
        // int 转换成 String
        String s = String.valueOf(a);
        out.write(s.getBytes());
    }

    // 写int并且换行的方法 void printIntLn(int a)
    public void printIntLn(int a) throws IOException{
   
        // int 转换成 String
        String s = String.valueOf(a);
        out.write(s.getBytes());
        out.write(System.lineSeparator().getBytes());
    }

    // 写double的方法  void printDouble(double a)
    public void printDouble(double a) throws IOException{
   
        // int 转换成 String
        String s = String.valueOf(a);
        out.write(s.getBytes());
    }

    // 写double并且换行的方法 void printDoubleLn(double a)
    public void printDoubleLn(double a) throws IOException{
   
        // int 转换成 String
        String s = String.valueOf(a);
        out.write(s.getBytes());
        out.write(System.lineSeparator().getBytes());
    }

    // 写一个close方法  void  close()
    public void close() throws IOException{
   
        out.close();
    }

}

PrintStream字节打印流

PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式

继承关系
在这里插入图片描述

构造方法


PrintStream(File file)        // 创建具有指定文件且不带自动行刷新的新打印流。

PrintStream(OutputStream out)       // 创建新的打印流。

PrintStream(OutputStream out, boolean autoFlush)      // 创建新的打印流。

PrintStream(String fileName)       // 创建具有指定文件名称且不带自动行刷新的新打印流。

成员方法

在这里插入图片描述

  • 每个数据类型有一个相对应的print方法

/*
使用字节打印流打印数据
 */

// 1. 创建字节打印流对象
PrintStream printStream = new PrintStream("a.txt");

// 2. 写 1000
printStream.print(1000);

// 3. 写 true
printStream.print(true);

// 4. close
printStream.close();

PrintWriter字符打印流

向文本输出流打印对象的格式化表示形式

构造方法


PrintWriter(File file)       // 使用指定文件创建不具有自动行刷新的新 PrintWriter。

PrintWriter(OutputStream out)  //  根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。

PrintWriter(OutputStream out,  boolean autoFlush)    
// 通过现有的 OutputStream 创建新的  PrintWriter。

PrintWriter(String fileName)    //  创建具有指定文件名称且不带自动行刷新的新 PrintWriter。

PrintWriter(Writer out)    // 创建不带自动行刷新的新 PrintWriter。

PrintWriter(Writer out,  boolean autoFlush)     // 创建新 PrintWriter。

成员方法

在这里插入图片描述

  • 每个数据类型有一个相对应的print方法

eg:

// 1.
PrintWriter printWriter = new PrintWriter("a.txt");

// 2.
printWriter.println(100);
printWriter.print("a");

// 3.
printWriter.flush();

// 4.
printWriter.close();
    

打印流特点

  • 只能操作目的地,不能操作数据来源。
    • 没有与之相对应的输入流
  • 可以操作任意类型的数据
    • 任意类型的数据—>String(String.valueOf(不同类型的数据))
  • 如果启动了自动刷新,能够自动刷新。
    • autoFlush如果为 true,则 printlnprintfformat 方法将刷新输出缓冲区
    • 下面是println源码举例:
    public void write(String s) {
         
        write(s, 0, s.length());
    }
    
    private void newLine() {
         
        try {
         
            synchronized (lock) {
         
                ensureOpen();
                out.write(System.lineSeparator());
                if (autoFlush)
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
         
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
         
            trouble = true;
        }
    }
    
  • 可以操作文件的流
    • 构造方法里可以传File对象或者String fileName

标准输入输出流

标准输入流

  • System.in
  • 默认输入设备是键盘
  • 本质: InputStream 普通的字节输入流

标准输出流

  • System.out
  • 默认输出设备是显示器
  • 本质: PrintStream 字节打印流

注意事项

  • read方法是一个阻塞方法

eg:

需求:利用System.in 完成Scanner的nextLine()的功能


BufferedReader bufferedReader = new BufferedReader(
        new InputStreamReader(System.in));
// InputStreamReader是字节流和字符流的转换桥梁

String s = bufferedReader.readLine();
System.out.println(s);

bufferedReader.close();


对象流(序列化与反序列化流)

  • 序列化: 把对象数据转为二进制数据, 存到文件的过程
  • 反序列:(序列化的逆过程) :把二进制数据还原回对象数据的过程

ObjectOutputStream序列化流

  • ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。
    可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储
    如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。
  • 只能将支持 java.io.Serializable 接口的对象写入流中,Serializable接口是一个空接口(跟cloneable接口是一样的), 起到标记的作用
  • writeObject 方法用于将对象写入流中

继承关系

在这里插入图片描述

构造方法

ObjectOutputStream(OutputStream out)  // 创建写入指定 OutputStream 的 ObjectOutputStream。

成员方法

writeObject(Object obj)      // 将指定的对象写入 ObjectOutputStream。

ObjectInputStream反序列化流

ObjectInputStream以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化

构造方法

ObjectInputStream(InputStream in)   //  创建从指定 InputStream 读取的 ObjectInputStream。

成员方法

readObject()     //  从 ObjectInputStream 读取对象。

eg:


public class Demo {
   
    public static void main(String[] args) throws IOException, ClassNotFoundException {
   
        /*
        使用对象流(序列化和反序列化)
        写入对象
        读取对象
         */

        // 序列化流操作

        // 1. 创建学生对象
        Student stu = new Student("zs",10);

        // 2. 创建序列化流的对象
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("a.txt"));

        // writeObject(Object obj)
        out.writeObject(stu);

        // close
        out.close();

        // 反序列化流操作

        // 1. 创建反序列化流对象
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("a.txt"));

        // 2. readObject()
        Object o = in.readObject();
        System.out.println(o);

        // 3. close
        in.close();

    }
}

/*
java.io.NotSerializableException 没有实现Serializable接口
 */

class Student implements Serializable {
   
    String name;
    int age;

    // transient修饰不想被序列化的成员变量
    transient int score;
    static final long serialVersionUID = -7889256375299507710L;

    public Student(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

    public Student(String name, int age, int score) {
   
        this.name = name;
        this.age = age;
        this.score = score;
    }

    @Override
    public String toString() {
   
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

注意事项

  • java.io.NotSerializableException
    • 没有实现Serializable接口
  • java.io.InvalidClassException: _18io03.com.cskaoyan._04serialize.Student; local class incompatible: stream classdesc serialVersionUID = -7889256375299507710, local class serialVersionUID = 7388140007375758175
    • 设置为:static final long serialVersionUID = -7889256375299507710L;
    • SerialVersionUID不匹配
  • transient修饰不想被序列化的成员变量,就是反序列化后看不到具体的值

RandomAccessFile随机访问文件流

  • RandomAccessFile 声明在java.io包下,但直接继承于java.lang.Object类,这个类既可以读也 可以写
  • 支持 “随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件
    • 支持只访问文件的部分内容
    • 可以向已存在的文件后追加内容
  • RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。

构造方法

RandomAccessFile(File file, String mode)   
// 创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。

RandomAccessFile(String name, String mode)   
// 创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。

注意
创建 RandomAccessFile 类实例需要指定一个 mode 参数,该参数指 定 RandomAccessFile 的访问模式(介绍2种常用的):

  • r: 以只读方式打开(不会创建文件,读取已经存在的文件)
  • rw:可读可写(文件不存在会创建,存在不会创建)

成员方法

  • 常规的readwrite方法
  • RandomAccessFile 类对象可以自由移动记录指针
    • long getFilePointer():获取文件记录指针的当前位置
    • void seek(long pos):将文件记录指针定位到 pos 位置

eg:

@Test
public void Test() throws IOException {
   
    File file = new File("D:\\java_test\\a.txt");

    RandomAccessFile randomAccessFile = 
    new RandomAccessFile("D:\\java_test\\a.txt", "rw");

    // 获取当前文件的指针
    long filePointer = randomAccessFile.getFilePointer();

    // write写数据
    randomAccessFile.write("abjdefg".getBytes());

    // 从文件的某个位置进行写数据
    // 移动指针
    randomAccessFile.seek(4);
    randomAccessFile.write("999".getBytes());

    // 从文件的末尾开始写
    randomAccessFile.seek(file.length());
    randomAccessFile.write("1998".getBytes());

    // 从文件中读取数据
    randomAccessFile.seek(0);
    byte[] bytes = new byte[1024];
    int readCount = randomAccessFile.read(bytes);
    System.out.println(new String(bytes,0,readCount));

    randomAccessFile.close();
}

NIO

  • Java NIO(New IO, Non Blocking IO),可以替代标准的Java IO API。
  • NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同
  • NIO支持面向缓冲区buffer的、基于通道channel的IO操作
  • NIO将以更加高效的方式进行文件的读写操作。
IO NIO
面向流(Stream Oriented) 面向缓冲区(块)(Buffer Oriented)
阻塞IO(Blocking IO) 非阻塞IO(Non Blocking IO)

NIO核心

  • Buffer
  • Channel

Channel负责传输,Buffer负责存储

Buffer

除了boolean之外的基本数据类型都有1个对应的Buffer
比如 IntBuffer 放int数据(除了boolean)

  • ByteBuffer 最常用

  • IntBuffer

  • ShortBuffer

  • LongBuffer

  • DoubleBuffer

  • FloatBuffer

  • CharBuffer
    在这里插入图片描述

Buffer的实例化

ByteBuffer为例:

public static ByteBuffer allocate(int capacity)

public static ByteBuffer allocateDirect(int capacity)

public static ByteBuffer wrap(byte[] array)

public static ByteBuffer wrap(byte[] array, int offset, int length)

eg:

    @Test
    public void Test2(){
   
        ByteBuffer allocate = ByteBuffer.allocate(10);
        System.out.println(allocate);

		
    }

在这里插入图片描述
其中

  • capacity

    • 表示Buffer最大数据容量,创建后不能更改.一旦Buffer满了,需要将其清空(通过读数据或者清除数据, 才能继续往里写数据)
  • limit

    • 是第一个不应该读取或写入的元素的索引。缓冲区的限制不能为负,并且不能大于其容量
    • 写数据到Buffer时,limit表示可对Buffer最多写入多少个数据(写模式下 limit = capacity)
    • 读数据时,limit表示Buffer里有多少可读数据,可以读取到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)
  • position

    • 写数据时,position表示写入数据的当前位置,初始值为0.当数据写入到Buffer中后,position会向后移动到1个可插入数据的Buffer单元.position最大值可为capacity
    • 读数据时,position表示读入数据的当前位置,如position=2时,表示已经读入了2个值,或从第2个位置开始读取.通过flip()切换到读模式时position会被重置为0,当Buffer从position读入数据后,position会移动到下一个可读入的数据Buffer单元
  • mark

    • 跟reset()结合进行标记,通过Buffer中的mark()方法,指定一个Buffer的特定的position,之后可以通过reset()方法恢复到这个position.
  • 这4个属性遵循如下关系:

    • 0<=mark<=position<=limit<=capacity

buffer的存取数据

put操作(存)

put(byte b)   // 将给定的字节写入此缓冲区的当前位置,然后该位置递增 。  position+1

put操作


总结

类型 字节输出流 字节输入流 字符输出流 字符输入流
抽象基类 OutputStream InputStream Writer Reader
文件相关 FileOutputStream FileInputStream FileWriter FileReader
缓冲相关 BufferedOutputStream BufferedInputStream BufferedWriter BufferedReader
转换相关 OutputStreamWriter InputStreamReader
数据相关 DataOutputStream DataInputStream
打印相关 PrintStream PrintWriter
对象相关 ObjectOutpuStream ObjectInputStream

相关推荐

  1. IO——其他

    2024-01-08 03:56:02       33 阅读
  2. 19IO

    2024-01-08 03:56:02       29 阅读
  3. IO

    2024-01-08 03:56:02       69 阅读
  4. IO-字符

    2024-01-08 03:56:02       35 阅读
  5. IO(字符)

    2024-01-08 03:56:02       32 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-08 03:56:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-08 03:56:02       101 阅读
  3. 在Django里面运行非项目文件

    2024-01-08 03:56:02       82 阅读
  4. Python语言-面向对象

    2024-01-08 03:56:02       91 阅读

热门阅读

  1. 【数值分析】追赶法解三对角方程组,matlab实现

    2024-01-08 03:56:02       40 阅读
  2. 小程序面试问答(解决方案)

    2024-01-08 03:56:02       37 阅读
  3. C 语言变量详解

    2024-01-08 03:56:02       57 阅读
  4. 用数据结构python写大数计算器

    2024-01-08 03:56:02       59 阅读
  5. SpringBoot 中实现订单30分钟自动取消的策略

    2024-01-08 03:56:02       62 阅读
  6. Docker - 启动 MySQL 闪退解决方案

    2024-01-08 03:56:02       49 阅读
  7. 实现一个网页聊天室

    2024-01-08 03:56:02       47 阅读
  8. 讲解eureca和nacus的区别

    2024-01-08 03:56:02       53 阅读
  9. Kvaser使用(Can总线)

    2024-01-08 03:56:02       198 阅读
  10. 数据库连接使用问题 - 1

    2024-01-08 03:56:02       59 阅读
  11. Docker学习笔记(一):Docker命令总结

    2024-01-08 03:56:02       67 阅读
  12. 学习录

    学习录

    2024-01-08 03:56:02      52 阅读