前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java基础之IO流(二)

Java基础之IO流(二)

作者头像
Remember_Ray
发布2020-08-05 11:32:06
3240
发布2020-08-05 11:32:06
举报
文章被收录于专栏:Ray学习笔记

I/O 工作原理

磁盘I/O

tips: DMA:全称叫直接内存存取(Direct Memory Access),是一种允许外围设备(硬件子系统)直接访问系统主内存的机制。基于 DMA 访问方式,系统主内存与硬件设备的数据传输可以省去CPU 的全程调度

特点

  • 读写操作基于系统调用实现
  • 读写操作经过用户缓冲区,内核缓冲区,应用进程并不能直接操作磁盘
  • 应用进程读操作时需阻塞直到读取到数据

网络I/O

特点

  • 网络I/O读写操作经过用户缓冲区,Sokcet缓冲区
  • 服务端线程在从调用recvfrom开始到它返回有数据报准备好这段时间是阻塞的,recvfrom返回成功后,线程开始处理数据报

字节流

在上一篇中,我们一直都是在操作文件或者文件夹,并没有给文件中写任何数据。现在我们就要开始给文件中写数据,或者读取文件中的数据

字节输出流OutputStream

OutputStream此抽象类,是表示输出字节流的所有类的超类。操作的数据都是字节,定义了输出字节流的基本共性功能方法 输出流中定义都是写write方法

FileOutputStream类

OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件 FileOutputStream类,即文件输出流,是用于将数据写入 File 的输出流

将数据写到文件中
代码语言:javascript
复制
/**
 * 将数据写到文件中
 */
public static void test1() throws IOException {
    // 创建存储数据的文件
    File file = new File("e:\\file.txt");
    // 创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。
    // 输出流目的是文件,会自动创建。如果文件存在,则覆盖。
    FileOutputStream fos = new FileOutputStream(file);
    // 写入数据
    byte[] data = "abcde".getBytes();
    // 调用父类的write方法
    fos.write(data);
    // 关闭流资源
    fos.close();
}

我们直接new FileOutputStream(file)这样创建对象,写入数据,会覆盖原有的文件,那么我们想在原有的文件中续写内容怎么办呢?

给文件中续写数据和换行
代码语言:javascript
复制
/**
 * 给文件中续写数据和换行
 */
public static void test2() throws IOException {
    File file = new File("e:\\file.txt");
    // append true 表示可追加,默认是false
    FileOutputStream fos = new FileOutputStream(file, true);
    String str = "\r\n" + "Hello";
    // 调用父类的write方法
    fos.write(str.getBytes());
    // 关闭流资源
    fos.close();
}

字节输入流InputStream

InputStream此抽象类,是表示字节输入流的所有类的超类,定义了字节输入流的基本共性功能方法

代码语言:javascript
复制
int read():读取一个字节并返回,没有字节返回-1
int read(byte[]): 读取一定量的字节数,并存储到字节数组中,返回读取到的字节数

FIleInputStream 类

InputStream有很多子类,其中子类FileInputStream可用来读取文件内容 FileInputStream 从文件系统中的某个文件中获得输入字节

在读取文件中的数据时,调用read方法,实现从文件中读取数据 如果返回的是-1,说明流已经读完了

读取文件内容
代码语言:javascript
复制
/**
 * 读取文件内容
 */
public static void test3() throws IOException {
    File file = new File("e:\\file.txt");
    // 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
    FileInputStream fis = new FileInputStream(file);
    // 读取数据。使用 read() 一次读一个字节。
    int ch = 0;
    // 循环读取内容
    while ((ch = fis.read()) != -1) {
        System.out.println("ch = " + (char)ch);
    }
    // 关闭资源
    fis.close();

    //ch = a
    //ch = b
    //ch = c
    //ch = d
    //ch = e
    //ch =
    //ch =
    //
    //ch = H
    //ch = e
    //ch = l
    //ch = l
    //ch = o
}

读取数据read(byte[])方法 在读取文件中的数据时,调用read方法,每次只能读取一个,太麻烦了,于是我们可以定义数组作为临时的存储容器,这时可以调用重载的read方法,一次可以读取多个字符,返回读取到的位置。如果是-1说明读完了

代码语言:javascript
复制
/**
 * 读取文件内容
 * read(byte[] b)
 */
public static void test4() throws IOException {
    File file = new File("e:\\file.txt");
    // 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
    FileInputStream fis = new FileInputStream(file);
    // 创建一个字节数组,长度可以定义成1024的整数倍。
    byte[] buf = new byte[1024];
    int len = 0;
    // 循环读取内容
    while ((len = fis.read(buf)) != -1) {
        System.out.println(new String(buf, 0 ,len));
    }
    // 关闭资源
    fis.close();

    //abcde
    //Hello
}
字节流复制图片
代码语言:javascript
复制
/**
 * 字节流复制图片
 */
public static void test5() throws IOException {
    // 1. 明确源和目的
    File srcFile = new File("e:\\1.jpg");
    File destFile = new File("e:\\1copy.jpg");

    // 2. 明确字节流 输入流和源相关联,输出流和目的关联
    FileInputStream fis = new FileInputStream(srcFile);
    FileOutputStream fos = new FileOutputStream(destFile);

    // 3. 使用输入流的读取方式读取字节,并将字节写入到目的中
    // 先定义一个缓冲区
    byte[] buf = new byte[1024];
    int len = 0;

    // 循环读取
    while ((len = fis.read(buf)) != -1) {
        // 将数组中的指定长度的数据写入到输出流中
        fos.write(buf, 0, len);
    }

    // 4. 关闭资源,先开后关原则
    fos.close();
    fis.close();
}

字符流

在操作过程中字节流可以操作所有数据,可是当我们操作的文件中有中文字符,并且需要对中文字符做出处理时怎么办呢? 我们读取中文打印再控制台的时候是一个个字节 一个字节是-127 到128的,那如果我们要直接打印中文的话,就需要用到字符流了

字符输入流Reader

我们读取拥有中文的文件时,使用的字节流在读取,那么我们读取到的都是一个一个字节。只要把这些字节去查阅对应的编码表,就能够得到与之对应的字符。API中是否给我们已经提供了读取相应字符的功能流对象,Reader,读取字符流的抽象超类

代码语言:javascript
复制
read():读取单个字符并返回
read(char[]):将数据读取到数组中,并返回读取的个数
FileReader类

用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader

代码语言:javascript
复制
/**
 * 读取中文
 */
public static void readText() throws IOException {
    FileReader fr = new FileReader("e:\\a.txt");
    int ch = 0;
    while ((ch = fr.read()) != -1) {
        // 输出字符对应的编码值
        System.out.println(ch);
        // 输出字符本身
        System.out.println((char)ch);
    }

    //20170
    //今
    //22825
    //天
    //22810
    //多
    //20113
    //云
    //65292
    //,
    //23567
    //小
    //38632
    //雨
}

/**
 * 写入中文
 */
public static void writeText() throws IOException {
    File file = new File("e:\\a.txt");
    if (!file.exists()) {
        file.createNewFile();
    }
    FileOutputStream fos = new FileOutputStream(file);
    fos.write("今天多云,小雨".getBytes());
    fos.close();
}

字符输入流Writer

既然有专门用于读取字符的流对象,那么肯定也有写的字符流对象

FileWriter类

flush():将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用 close():关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据,然后在关闭流。流不可以使用。如果写入数据多,一定要一边写一边刷新,最后一次可以不刷新,由close完成刷新并关闭

写入字符到文件中,先进行流的刷新,再进行流的关闭

代码语言:javascript
复制
/**
 * 写入字符到文件中,先进行流的刷新,再进行流的关闭
 */
public static void test7() throws IOException {
    // 验收 FileWriter 用于操作文件的便捷类
    FileWriter fw = new FileWriter("e:\\fw.txt");
    // 这些文字都要先编码。都写入到了流的缓冲区中
    fw.write("写入字符到文件中,先进行流的刷新,再进行流的关闭");
    // 刷新
    fw.flush();
    // 关闭之前需要刷新
    fw.close();
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-02-07|,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • I/O 工作原理
    • 磁盘I/O
      • 网络I/O
      • 字节流
        • 字节输出流OutputStream
          • FileOutputStream类
            • 将数据写到文件中
            • 给文件中续写数据和换行
          • 字节输入流InputStream
            • FIleInputStream 类
              • 读取文件内容
              • 字节流复制图片
          • 字符流
            • 字符输入流Reader
              • FileReader类
            • 字符输入流Writer
              • FileWriter类
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档