I/O也叫做输入/输出,在java编程语言中,I/O更被看作是一种流;JavaI/O的体系设计与Linux内核I/O有着密不可分的关系;

为了操作系统的安全考虑,Linux进程是无法直接操作I/O设备的,必须通过内核来协助完成I/O动作,而内核会为每个I/O设备维护一个缓冲区Buffer,又叫做缓冲区;

数据从I/O设备拷贝到buffer缓冲区(等待数据阶段);

数据再从缓冲区拷贝到Linux进程(拷贝数据阶段);

此过程可分为五种模型:

**阻塞I/O模型(Blocking I/O):**在Linux中默认情况下所有请求都是阻塞的,一个典型的读操作如下图:

**非阻塞I/O(Non-Blocking I/O):**应用会不断询问内核是否准备好了数据,系统不会阻塞用户进程,而是立即返回,从用户进程角度讲,并不需要等待可以立即返回结果;

I/O 复用(I/O Multiplexing):

信号驱动 I/O(Signal Driven I/O):

异步 I/O(Asynchrnous I/O):

Java标准I/O模型(Blocking I/O)

早期的Java I/O都是基于阻塞I/O模型的,他按照处理的数据类型分为字符流和字节流,按照工作职责分为处理流和装饰流。

字节流: 以 8 位( 即 1byte, 8bit) 作为一个数据单元, 数据流中最小的数据单元是字节;

字符流: 以 16 位( 即 1char, 2byte, 16bit) 作为一个数据单元, 数据流中最小的数据单元是字符, Java 中的字符是 Unicode 编码, 一个字符占用两个字节;

Java依据据字节流定义了了InputStream/OutputStream,依据字符流Java定义了Reader/Writer;Java 再根据不同应用场景或功能, 通过继承这两种抽象基类派生出子类, 用

来满足文件、 网络、 管道等不同场景的 I/O 需求, 从而形成了 Java 的基本 I/O 体系。

又可按照工作职能分为:

处理流: 真正直接处理 I/O 数据的类, 包括文件流、 数组流、 字符串流、 管道流;

装饰流: 用来装饰加工节点流的, 比如封装某些功能, 包括缓冲流、 转换流、 数据流、 对象流;

这些标准输入现在正逐渐被NIO取代

Java NIO模型(Non-blocking I/O)

**NIO 出现了(有的也称之为 New I/O),NIO 不但新增加了许多全新的类,而且还对原 java.io 包中的很多类进行了改写,NIO 主要包含三个核心部分:Channel、Buffer 和 **

Selector。

**Channel(通道):**NIO 中所有的读写操作都是从 Channel(通道)开始的,顾名思义,Channel 就是一条能够让数据通过的管道(像喝奶茶的吸管那样),它最重要的实可

以分为两大类:用于本地文件的 Channel 和用于网络的 Channel。

**Buffer(缓冲区):**Buffer 是专门用来缓存输入或输出的数据,分为输入缓冲区和输出缓冲区,它可以解决高速设备与低速设备速度的不匹配问题,也可以减少读写次数,

Channel提供从文件、网络读取数据的渠道,但是读写的数据都必须经过 Buffer。

Selector(选择器):数据总是从 Channel 读取到 Buffer,或者从 Buffer 写入到Channel,单个线程可以监听多个 Channel——Selector 就是这个线程背后的实现机制。

Selector 通过单线程处理多个 Channel,而 Selector(线程)之间需要传递数据的话,需要用到 Pipe,它是用于 Selector 之间数据传递的一种「单向」「管道」。

Scatter/Gather

Java NIO 支持一种称之为支持本地矢量 I/O(native vectored I/O)的技术(或者称为 Scatter/Gather 操作),当应用在一个 Channel 上请求一个 Scatter/Gather 操作时,这

个请求会被翻译为适当的本地调用来直接填充或抽取缓冲区,减少或避免了缓冲区拷贝和系统调用,这也意味着,Scatter/Gather 将使用直接缓冲区以从本地 I/O 获取最大性优

势(直接缓冲区的概念请参考名词解释),具体来说:

Scatter:将从一个 Channel 里读取的信息分散到多个 Buffer 中;

Gather:将多个 Buffer 里面的内容按顺序发送到一个 Channel 中。

标准I/O如何使用

File类及相关应用

File类的构造方法:

File(File parent,String child) 从父抽象路径名和子路径名字符串创建新的 File实例。

File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。

File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例。

File(URI uri) 通过将给定的 file: URI转换为抽象路径名来创建新的 File实例。

常用方法

public String getAbsolutePath() : 返回此File的绝对路径名字符串。

public String getPath() : 将此File转换为路径名字符串。

public String getName() : 返回由此File表示的文件或目录的名称。

public long length() : 返回由此File表示的文件的长度。

判断功能的方法

public boolean exists() :File表示的文件或目录是否实际存在。

public boolean isDirectory() :File表示的是否为目录。

public boolean isFile() :File表示的是否为文件。

增删的方法

public boolean createNewFile() : 当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。

public boolean delete() : 删除由此File表示的文件或目录。

public boolean mkdir() : 创建由此File表示的目录。

public boolean mkdirs() : 创建由此File表示的目录,包括任何必需但不存在的父目录。

目录的遍历

public String[] list() : 返回一个String数组,表示该File目录中的所有子文件或目录。

public File[] listFiles() : 返回一个File数组,表示该File目录中的所有的子文件或目录

任务一:如果是 Windows 系统,以递归方式读取 C 盘中所有的目录和文件,并打印出每个文件的大小和每个目录中文件的数量;如果是 Linux/Mac 系统,那么递归方式读取/usr中所有的目录和文件,并打印出每个文件的大小和每个目录中文件的数量。

package T11.windowC;import java.io.File;
import java.text.DecimalFormat;import static java.lang.Math.pow;/*** @Author: Administrator* Date: 2021/12/14 21:15* @Version:* @Description:*/
public class Test {public void soutWindowC(File file) {File[] files = {};if (file.isFile()) {System.out.print(file.getName());String s = fileSize(file);System.out.println("----" + s);return;} else if (file.isDirectory()) {files = file.listFiles();if (files == null) {return;} else {for (File file1 : files) {if (file1.isDirectory()) {System.out.println(file1.getName());System.out.print("\t");soutWindowC(file1);}if (file1.isFile()) {System.out.print(file1.getName());String s = fileSize(file1);System.out.println("----" + s);return;}}}}}String fileSize(File file) {DecimalFormat df = new DecimalFormat("#.00");String fileSize = "";if (file.length() < 1024) {fileSize = df.format(file.length()) + "B";}else if (file.length() < pow(1024, 2)) {fileSize = df.format(file.length()/1024) + "KB";}else if (file.length() < pow(1024, 3)) {fileSize = df.format(file.length()/pow(1024, 2)) + "MB";}else if (file.length() < pow(1024, 4)) {fileSize = df.format(file.length()/pow(1024, 3)) + "GB";}return fileSize;}@org.junit.Testpublic void test() {File file = new File("D:/");soutWindowC(file);}}

字节操作流

InputStream(字节输入流):

public void close() : 关闭此输入流并释放与此流相关联的任何系统资源。当完成流的操作时,必须调用此方法,释放系统资源。

public abstract int read() : 从输入流中读取下一个数据字节。值字节返回int ,范围为0255 。如果由于到达流末尾而没有可用字节,则返回值-1 。此方法将阻塞,直到输入数据可用,检测到流的末尾或抛出异常。子类必须提供此方法的实现.

public int read(byte[] b) : 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。

OutputStream(字节输出流):

public void close() : 关闭此输出流并释放与此流相关联的任何系统资源。当完成流的操作时,必须调用此方法,释放系统资源。

public void flush() : 刷新此输出流并强制任何缓冲的输出字节被写出。

public void write(byte[] b) : 将 b.length字节从指定的字节数组写入此输出流。

public void write(byte[] b, int off, int len) : 从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。

public abstract void write(int b) : 将指定的字节输出流。

public class InputStreamDemo {@Testpublic void test() throws IOException {FileInputStream fis = new FileInputStream("E://old/battleField.png");FileOutputStream fos = new FileOutputStream("E://new/battleField.png");byte[] b= new byte[1024];int len;while((len = fis.read(b))!=-1){fos.write(b, 0, len);}}
}

字符操作流

Reader(字符输入流):

public void close() : 关闭此输入流并释放与此流相关联的任何系统资源。当完成流的操作时,必须调用此方法,释放系统资源。

public abstract int read() : 从输入流中读取下一个数据字节。值字节返回int ,范围为0255 。如果由于到达流末尾而没有可用字节,则返回值-1 。此方法将阻塞,直到输入数据可用,检测到流的末尾或抛出异常。子类必须提供此方法的实现.

public int read(byte[] b) : 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。

Writer(字符输出流):

public void close() : 关闭此输出流并释放与此流相关联的任何系统资源。当完成流的操作时,必须调用此方法,释放系统资源。

public void flush() : 刷新此输出流并强制任何缓冲的输出字节被写出。

public void write(byte[] b) : 将 b.length字节从指定的字节数组写入此输出流。

public void write(byte[] b, int off, int len) : 从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。

public abstract void write(int b) : 将指定的字节输出流。

public class ReaderDemo {@Testpublic void test() throws IOException {FileReader reader = new FileReader("E://old/battleField.png");FileWriter writer = new FileWriter("E://new/battleField.png");char c[] = new char[1024];int len;while ((len = reader.read(c)) != -1){writer.write(c, 0, len);writer.flush();}}
}

NIO应该如何使用

public class NIODemo {@Testpublic void test() throws IOException {FileChannel channelIn = new FileInputStream("E://old/battleField.png").getChannel();FileChannel channelOut = new FileOutputStream("E://new/battleField.png").getChannel();channelIn.transferTo(0, channelIn.size(), channelOut);}
}

感谢您的阅读,如果本篇文章对您有帮助,欢迎点赞,关注,您的阅读是我莫大的鼓励!

JavaIO流——文件的读取与传输相关推荐

  1. javaIO流详解--读取,写入文件的所有类与方法

    目录 IO流简介: 1 :InputStream 2:OutputStream 3:FileInputStream 4:FileOutputStream 5:利用FileInputStream和Fil ...

  2. javaio流_万字长文+思维导图帮你梳理 Java IO 流,还学不会你来打我(值得收藏)...

    前言 在上一篇的文章获取不错的浏览量后,继续加更的念头一直徘徊在心中,本来是想花段时间深入学习tomcat的,可是tomcat的源码中就有至关重要的NIO,于是得先整一下NIO,但是NIO的基础是BI ...

  3. 文件_ _android从资源文件中读取文件流并显示的方法

    ======== 1   android从资源文件中读取文件流并显示的方法. 在android中,假如有的文本文件,比如TXT放在raw下,要直接读取出来,放到屏幕中显示,可以这样: private ...

  4. php接收流文件,PHP传输文件流及文件流的保存

    什么是文件流 在HTTP数据传送过程中,传输一方直接以二进制流方式传送文件内容,这样就形成了一个文件流: 文件流的接收通常涉及到预定义变量函数 $HTTP_RAW_POST_DATA 和 file_g ...

  5. Java------IO流之文件专属流

    文件专属流 文章目录 文件专属流 FileInputStream流 FileInputStream初步读取 FileInputStream循环读 IDEA默认当前路径 往byte数组中读 最终版Fil ...

  6. 用对象流把对象存到文件中,再从文件中读取出来打印。

    例如把学生对象存到文件中: 1.先创建一个学生类      ***注意 用对象流时,要保存的对象所属的类必须要实现序列化(implements Serializable) package my_tes ...

  7. 小师妹学JavaIO之:文件读取那些事

    文章目录 简介 字符和字节 按字符读取的方式 按字节读取的方式 寻找出错的行数 总结 简介 小师妹最新对java IO中的reader和stream产生了一点点困惑,不知道到底该用哪一个才对,怎么读取 ...

  8. java读取二进制流文件_java分别通过字节流、字符流、二进制读取文件的代码

    将做工程过程中比较好的一些内容段做个备份,下面的资料是关于 java分别通过字节流.字符流.二进制读取文件的内容,应该是对小伙伴们有些用途. public class Start { public s ...

  9. 使用IO流对文件进行读取功能

    对于文件的读取可以用字符流也可以用字节流,下面整理了一份利用字节读流对本地文件进行读取 1.实现思路 第一步:选择文件 实例化一个文件File,在File的构造里放上你要读取的文件路径,文件路径的斜杠 ...

  10. Java字符流Writer写入文件Reader读取文件

    写文件 public class WriteDemo {public static void main(String[] args) throws IOException {File file = n ...

最新文章

  1. 基于python的快速傅里叶变换FFT(二)
  2. POJ 2481 Cows POJ 2352 Stars(树状数组妙用)
  3. Linux上安装Julia-1.1
  4. u盘病毒之tel.xls.exe
  5. Memcached服务端自动启动(转载)
  6. Spark 性能优化指南(官网文档)
  7. input组件android,React-Native TextInput组件详解及实例代码
  8. 【免费下载】2021年9月热门报告盘点(附热门报告列表及下载链接)
  9. 如何解决多机房、多网络下的物联网部署方案?
  10. 正则表达式替换字符串
  11. mql 查询多结果_MQL入门到精通EA教程第六课MQL语言基础(五)
  12. 编码,隐匿在计算机软硬件背后的语言读书笔记(作者序)
  13. 将US7ASCII 字符集的数据转到ZHS16GBK 字符集数据库
  14. 网站更换国外服务器,备案被注销替换外国服务器?这样合理吗?
  15. 混沌的有关概念——1
  16. 基于ARMv8的固件系统架构
  17. Halium 9 尝鲜 -- 在小米平板4上的移植 (一)
  18. python日常实用小脚本-用Python编写渗透用小脚本 短小实用
  19. Helicon Focus Pro(景深合成软件)官方中文版V7.6.6 | helicon focus中文版下载 | 含helicon focus使用方法
  20. photon 服务器操作系统,PhotonServer游戏服务器端教程

热门文章

  1. Fisher判别式(LDA)
  2. 如何更高效的学习SLAM?
  3. FAST-LIO2代码解析(四)
  4. JavaScript JSON的key 下划线格式与驼峰格式互相转换
  5. 利用官方预训练模型快速计算Inception Score和FID
  6. spark处理大数据实例
  7. pandas 两列数据合并
  8. IDEA如何设置鼠标滚轮调节字体大小
  9. iOS小技能:模拟鼠标点击(针对Mac)
  10. 域无法在加入计算机,计算机无法加入域的终级解决方法