Java之IO流技术详解
何为IO?
首先,我们看看百度给出的解释。
I/O输入/输出(Input/Output),分为IO设备和IO接口两个部分。
i是写入,Input的首字母。o是输出,Output的首字母。
IO 也称为IO流,IO = 流,它的核心就是对文件的操作,对于 字节 、字符类型的输入和输出流。
IO分类
IO流主要分为两大类,字节流和字符流。而按照作用分类,可以分为输入流和输出流。
流?
在电脑上的数据有三种存储方式,一种是外存,一种是内存,一种是缓存。比如电脑上的硬盘,磁盘,U盘等都是外存,在电脑上有内存条,缓存是在CPU里面的。外存的存储量最大,其次是内存,最后是缓存,但是外存的数据的读取最慢,其次是内存,缓存最快。这里总结从外存读取数据到内存以及将数据从内存写到外存中。对于内存和外存的理解,我们可以简单的理解为容器,即外存是一个容器,内存又是另外一个容器。那又怎样把放在外存这个容器内的数据读取到内存这个容器以及怎么把内存这个容器里的数据存到外存中呢?
我们可以将这个整个看成一个水池。水池里面连接了出水口管与注水管。出水相当于我们的输出流。注水相当于我们的输入流。
File(文件类)
首先我们如果需要用IO流的话,我们肯定是需要创建一个我们所谓的**“水池”**的。
怎么创建呢?我们直接创建一个File类对象。
package IoDemo;
import java.io.*;
public class IoDemo {public static void main(String[] args) {//创建File对象File file = new File("D:\\test.txt");}
}
实际上这个对象,说白了就是用来储存一个IO流的文件地址的。
创建了对象后,它也没有任何什么操作,操作得使用这个对象调用方法。
我们先使用createNewFile()
方法创建我们上面那个路径的文件。
file.createNewFile();
注意定义文件路径时,可以用“/”或者“\”。
并且在创建一个文件时,如果目录下有同名文件将被覆盖。
因为有时候,可能我们的路径下已经存在了相对应的同名文件,所以我们要使用exists()
方法判断文件是否已经存在。
//创建File对象File file = new File("D:\\test.txt");//创建文件try {//判断文件是否存在if(!file.exists()){file.createNewFile();}} catch (IOException e) {e.printStackTrace();}
其实,File类里面还存在许多方法,用法都是可以直接调用的,作为一个合格的程序员,我们可以直接阅读相关说明而在合适的时候使用对应方法。
下面列举一些常用方法。
①、创建方法
1.boolean createNewFile() 不存在返回true 存在返回false 2.boolean mkdir() 创建目录,如果上一级目录不存在,则会创建失败 3.boolean mkdirs() 创建多级目录,如果上一级目录不存在也会自动创建
②、删除方法
1.boolean delete() 删除文件或目录,如果表示目录,则目录下必须为空才能删除 2.boolean deleteOnExit() 文件使用完成后删除
③、判断方法
1.boolean canExecute()判断文件是否可执行 2.boolean canRead()判断文件是否可读 3.boolean canWrite() 判断文件是否可写 4.boolean exists() 判断文件或目录是否存在 5.boolean isDirectory() 判断此路径是否为一个目录 6.boolean isFile() 判断是否为一个文件 7.boolean isHidden() 判断是否为隐藏文件 8.boolean isAbsolute()判断是否是绝对路径 文件不存在也能判断
④、获取方法
1.String getName() 获取此路径表示的文件或目录名称 2.String getPath() 将此路径名转换为路径名字符串 3.String getAbsolutePath() 返回此抽象路径名的绝对形式 4.String getParent()//如果没有父目录返回null 5.long lastModified()//获取最后一次修改的时间 6.long length() 返回由此抽象路径名表示的文件的长度。 7.boolean renameTo(File f) 重命名由此抽象路径名表示的文件。 8.File[] liseRoots()//获取机器盘符 9.String[] list() 返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。 10.String[] list(FilenameFilter filter) 返回一个字符串数组,命名由此抽象路径名表示的目录中满足指定过滤器的文件和目录。
字节流的使用
我们现在已经建好这个**“水池”了,同时还可以使用方法来获取到“水池”**的一些信息。
那接下来,我们可以试着创建一套流。
字节流,相当于一滴滴的水在一个管道里运输。这个管道我们可以抽象的称之为流。
我们还是先看看知乎上,某些大佬的解释。
大佬的解释
图中蓝色为主要对应部分,红色为不对应部分,黑色的虚线部分代表这些流一般需要搭配使用。从上面的图中可以看出Java IO中的字节流是非常对称的。我们来看看这些字节流中不对称的几个类。
LineNumberInputStream 主要完成从流中读取数据时,会得到相应的行号,至于什么时候分行、在哪里分行是由改类主动确定的,并不是在原始中有这样一个行号。在输出部分没有对应的部分,我们完全可以自己建立一个LineNumberOutputStream,在最初写入时会有一个基准的行号,以后每次遇到换行时会在下一行添加一个行号,看起来也是可以的。好像更不入流了。
PushbackInputStream 的功能是查看最后一个字节,不满意就放入缓冲区。主要用在编译器的语法、词法分析部分。输出部分的BufferedOutputStream 几乎实现相近的功能。
StringBufferInputStream 已经被Deprecated,本身就不应该出现在InputStream 部分,主要因为String 应该属于字符流的范围。已经被废弃了,当然输出部分也没有必要需要它了!还允许它存在只是为了保持版本的向下兼容而已。
SequenceInputStream 可以认为是一个工具类,将两个或者多个输入流当成一个输入流依次读取。完全可以从IO 包中去除,还完全不影响IO 包的结构,却让其更“纯洁”――纯洁的Decorator 模式。
PrintStream 也可以认为是一个辅助工具。主要可以向其他输出流,或者FileInputStream 写入数据,本身内部实现还是带缓冲的。本质上是对其它流的综合运用的一个工具而已。一样可以踢出IO 包!System.out 和System.out 就是PrintStream 的实例。
对于不完全学透的看法
听起来有些难度哈,这些高级用法我们先不管。我们先来看看它到底怎么用的。
那有人又说了,那如果不去学完整,以后要是不会用怎么办?
答:其实只需要掌握主要方法就可以,因为你如果需要实现一个非常用的东西,你肯定是事先就需要去查阅相关资料,而日常开发中,常用的也就可以信手拈来啦。
OutputStream(字节输出流)
这个抽象类是表示输出字节流的所有类的超类。
!!!这里的输出可不是我们正常的输出,它反而想法,是将字节写入到文件,可以理解为将字节输出到文件。
看看里面有些啥常用方法。
我们先演示一下,字节输出流如何使用?
//定义一个String值
String str = "Hello World";
等下我们利用字节流将这个String写入我们的文件里面。
等等!这里是字节流,我怎么可以直接写入**String
**?
嘿嘿,我们使用String类中的getBytes()方法将String转换成字节数组。
//将String值转换成字节数组
byte[] bytes = str.getBytes();
整个代码是这样的:
package IoDemo;
import java.io.*;
public class IoDemo {public static void main(String[] args) {//创建File对象File file = new File("D:\\test.txt");//创建文件try {//判断文件是否存在if(!file.exists()){file.createNewFile();}} catch (IOException e) {e.printStackTrace();}//定义一个String值String str = "Hello World";//创建字节流FileOutputStream fos = null;try {//将File对象(即地址)给到FileInputStreamfos = new FileOutputStream(file);//将String值转换成字节数组byte[] bytes = str.getBytes();//循环将字节数组写入到文件中for (int i = 0; i < bytes.length; i++) {//将bytes写入文件fos.write(bytes[i]);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
我们进我们的文件看看输出效果。
就已经写入了我们的String里面的内容了。
InputStream(字节输入流)
这里我也就不解释了,他这个输入不是将内容输入到文件,而是将文件里面的内容输入到我们的代码中。
//创建字节输入流
FileInputStream fis = null;
try {//将File对象(即地址)给到FileInputStreamfis = new FileInputStream(file);//创建字节数组byte[] bytes = new byte[1024];//输出字节数组int len = 0;while ((len = fis.read(bytes)) != -1) {System.out.println(new String(bytes, 0, len));}
} catch (FileNotFoundException e) {e.printStackTrace();
} catch (IOException e) {e.printStackTrace();
}
在上文,我们已经写入了一个Hello Word
我们现在这段代码,我们将会输出文件中的内容。
len = fis.read(bytes)) != -1
我现在还是先讲解一下这一段。
我们的
len
是定义的一个数值。而read()
方法,是为了读取到整个文件里面内容的字节长度,就像数组的lenth()
一样。而
!= -1
是因为,如果值为-1
那么,这个文件可以说是没有数据的,空的你也没必要输出。
而我们字节流呢,一般是用于读取二进制文件,如音频、图片这些,大片的文字内容还是交给字符流吧。
字符流的使用
上面的字节流,它是一个个的输出的,而我们现在的字符流,是大水管输出,一次可以运输一段。
一般可以用记事本打开的文件,我们可以看到内容不乱码的。就是文本文件,可以使用字符流。而操作二进制文件(比如图片、音频、视频)必须使用字节流。
FileWriter(字符输出流)
老规矩哈,方法自己看看。
先写入一个String
试试。
package IoDemo;
import java.io.*;
public class IoDemo {public static void main(String[] args) {String str = "嘿嘿!我是字符流·········";//创建File对象File file = new File("D:\\test.txt");try {//将str用writer写入文件FileWriter fw = new FileWriter(file);fw.write(str);//关闭流,字符流必须关闭流才可以输出fw.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
写入效果如下:
实际上,写入字符串就几个步骤。
//1.将str用writer写入文件FileWriter fw = new FileWriter(file);//2.使用write()方法写入字符串fw.write(str);//3.关闭流,字符流必须关闭流才可以输出fw.close();
FileReader(字符输出流)
//输出文件内容try {//创建输入字符流FileReader fr = new FileReader(file);//输出文件内容int ch = 0;while ((ch = fr.read()) != -1){System.out.print((char)ch);}//关闭流fr.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}
这里采用
Char
挨个字符遍历数据。
包装流
缓冲流
为什么使用缓冲流呢?
简单地说就是,写入数据更快,可以加速写入。
缓冲流,也叫高效流。 能够高效读写缓冲流,能够转换编码的转换流,能够持久化存储对象的序列化对象等等。 它是四个基本File流的增强,所以也是4个流,按照数据类型分类。 缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO读取次数,从而提高读写的效率。
package IoDemo;
import java.io.*;
public class IoDemo {public static void main(String[] args) {//创建File对象File file = new File("D:\\test.txt");//创建缓冲流BufferedWriter bw = null;try {//创建FileWriter对象FileWriter fw = new FileWriter(file);//创建BufferedWriter对象bw = new BufferedWriter(fw);//写入一首诗分四次写入bw.write("窗前明月光,");bw.write("疑是地上霜。");bw.write("举头望明月,");bw.write("低头思故乡。");bw.flush();} catch (IOException e) {e.printStackTrace();}}
}
这个很简单,自己看就可以看懂。
转换流
InputStreamReader:把字节输入流转换为字符输入流
OutputStreamWriter:把字节输出流转换为字符输出流
我就不写示范了,网上找了一段。
//转换流实现将 a.txt 文件 复制到 b.txt 中//1、创建源和目标File srcFile = new File("io"+File.separator+"a.txt");File descFile = new File("io"+File.separator+"b.txt");//2、创建字节输入输出流对象InputStream in = new FileInputStream(srcFile);OutputStream out = new FileOutputStream(descFile);//3、创建转换输入输出对象Reader rd = new InputStreamReader(in);Writer wt = new OutputStreamWriter(out);//3、读取和写入操作char[] buffer = new char[10];//创建一个容量为 10 的字符数组,存储已经读取的数据int len = -1;//表示已经读取了多少个字符,如果是 -1,表示已经读取到文件的末尾while((len=rd.read(buffer))!=-1){wt.write(buffer, 0, len);}//4、关闭流资源rd.close();wt.close();
扩展
然后,找相关资料时,还涨了个知识。大家可以看看。
合并流
合并流:把多个输入流合并为一个流,也叫顺序流,因为在读取的时候是先读第一个,读完了在读下面一个流。
SequenceInputStream seinput = new SequenceInputStream();new FileInputStream("io/1.txt"), new FileInputStream("io/2.txt"));byte[] buffer = new byte[10];int len = -1;while((len=seinput.read(buffer))!=-1){System.out.println(new String(buffer,0,len));}seinput.close();
这里先是创建了一个SequenceInputStream
对象,然后new
了两个FileInputStream
对象,我们使用合并流读取,先使用**seinput.read方法
**读取1.txt
的内容,然后再对其2.txt
的内容。
Java之IO流技术详解相关推荐
- java 常见io流 万字详解
文章目录 1.IO简介 1.1什么是IO流. 1.2数据源(Data Source) 1.3什么是流 1.4处理对象分类 1.5 java四大io抽象类及其他 1.6inputStream 1.61简 ...
- IO流的详解,彻底了解IO流
文章目录 前言 一.基本概念 1.1.用户空间和内核空间 1.2.操作系统的IO 1.3.java的IO流 1.4.IO流的分类 1.5.扩展 1.5.1.同步与异步 1.5.2.阻塞与非阻塞 1.5 ...
- JAVA基础 IO流技术学习笔记
目录 一.IO 流技术介绍 1.1 什么是IO? 1.2 流的概念 1.3 数据源 1.3.1 什么是数据源? 1.3.2数据源的分类 二.第一个简单的IO流程序 三.IO流经典写法(适用于任何 ...
- 【Java基础】· IO流习题详解
写在前面 Hello大家好, 我是[麟-小白],一位软件工程专业的学生,喜好计算机知识.希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正!谢谢大家!!! ...
- Java IO流使用详解
1.前言 在众多流行的编程语言中,Java对IO的处理应该是最特殊的,Java打着"尽量减少IO类的设计理念",搞出了目前应该是最复杂的一套IO相关类,并称之为Java流. 对于新 ...
- Java IO流(详解)
1. File 1. 创建 2. 操作 1. 获取文件信息 2. 目录创建/删除 2. IO流 1. FileInputStream 1. 简单使用 2. 读取中文 2. FileOutputStre ...
- Java SE 第八十八,八十九,九十讲 递归深度剖析 IO流深入详解,递归作业详解
1.所谓递归(Recursion),就是方法调用自身,对于递归来说,一定有一个出口,让递归结束,只有这样才能保证不出现死循环. 2.作业:给定任意一个目录,以树形方式展现该目录中所有子目录和文件.另外 ...
- Guava-RateLimiter秒杀限流技术详解
使用场景 系统使用下游资源时,需要考虑下游对资源受限.处理能力,在下游资源无法或者短时间内无法提升处理性能的情况下,可以使用限流器或者类似保护机制,避免下游服务崩溃造成整体服务的不可用. 常用算法 常 ...
- Java的常用日志技术详解(一)
日志文件 日志文件是用于记录系统操作事件的文件集合. 日志文件它具有处理历史数据.诊断问题的追踪以及理解系统的活动等重要的作用. 日志种类 调试日志 调试程序,或者做一些状态的输出,便于我们查询程序的 ...
最新文章
- 【廖雪峰python入门笔记】dict
- 安装eAccelerator
- python比java简单好学-是不是Python比Java更容易学,更容易就业?
- python怎么读取文件-Python中怎么读写文件
- 北航算法作业一 约瑟夫环问题
- 03_运算符、键盘录入、流程控制
- c++程序设计语言第四版pdf_寒假攻略 | 开启C语言自学模式
- 液晶拼接处理器_大屏幕显示系统设备中矩阵与液晶拼接屏的连接方法
- [图文并茂]手把手教你用`U盘启动盘`重装Windows系统
- 证明:T(n)= T(n-1) + O(n)等于O(n的平方)
- GitHub 配置SSH Key
- 什么是美国能源之星计划?
- 可靠性 可用性 可维护性
- SEI文献整理2:A Review of Radio Frequency Fingerprinting Techniques(2020)
- 创新创业大赛的目的是什么?为什么要参加创新创业大赛?
- 使用 Hyper-V 安装 Linux
- 黑马程序员Java零基础视频教程(2022最新Java)B站视频学习笔记-Day15-阶段项目(拼图小游戏)(上篇)
- 如何进入BIOS设置界面
- NeHe OpenGL教程 第二十九课:Blt函数
- 广东计算机职业学校排名2015年,广东职业高中学校排名