文章目录
Java的IO流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作,在Java中把不同的输入/输出源(键盘、文件、网络连接等)抽象表述为“流”(stream),通过流的方式允许Java程序使用相同的方式来访问不同的输入输出源。
stream是从起源(source)到接收(sink)的有序数据。Java把所有传统的流类型(类或抽象类)都放在java.io包中,用以实现输入输出功能。
一、流的分类:
1、节点流与非节点流
1.1 节点流
节点流:直接与数据源相连,读入或读出。
直接使用节点流,读写不方便,为了更快的读写文件,才有了处理流。
这里写图片描述
常用的节点流
父 类 :InputStream
、OutputStream
、 Reader
、 Writer
文 件 :FileInputStream
、 FileOutputStrean
、FileReader
、FileWriter
文件进行处理的节点流
数 组 :ByteArrayInputStream
、 ByteArrayOutputStream
、 CharArrayReader
、CharArrayWriter
对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
字符串 :StringReader
、 StringWriter
对字符串进行处理的节点流
管 道 :PipedInputStream
、PipedOutputStream
、PipedReader
、PipedWriter
对管道进行处理的节点流
1.2 处理流
处理流和节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。
这里写图片描述
常用的处理流
缓冲流:BufferedInputStrean
、BufferedOutputStream
、 BufferedReader
、 BufferedWriter
增加缓冲功能,避免频繁读写硬盘。
转换流:InputStreamReader
、OutputStreamReader
实现字节流和字符流之间的转换。
数据流: DataInputStream
、DataOutputStream
等-提供将基础数据类型写入到文件中,或者读取出来。
1.3 转换流
InputStreamReader
、OutputStreamWriter
要InputStream
或OutputStream
作为参数,实现从字节流到字符流的转换。
Java的IO流共涉及40多个类,这些类看上去芜杂而凌乱,但实际上非常规则,而且彼此之间存在非常紧密的联系Java的IO流的40多个类都是从如下4个抽象基类派生的。
1、输入流和输出流
按照流的流向来分,可以分为输入流和输出流。输入、输出都是从程序运行所在内存的角度来划分的。
输入流:只能从中读取数据,而不能向其写入数据。由InputStream和Reader作为基类
输出流:只能向其写入数据,而不能从中读取数据。由OutputStream和Writer作为基类
2、字节流和字符流
字节流和字符流的用法几乎完全一样,区别在于字节流和字符流所操作的数据单元不同。字节流操作的数据单元是字节,字符流操作的数据单元是字符。
**字节流:**操作的数据单元是8位的字节,由InputStream和OutputStream作为基类。
**字符流:**操作的数据单元是16位的字符,由 Reader和 Writer作为基类。
3、节点流和处理流
按照流的角色来分,可以分为节点流和处理流。
节点流:可以从向一个特定的IO设备(如磁盘、网络)读/写数据的流。也被称为低级流。
处理流:用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能。也称为高级流。
4、Stream流:
根据Collection获取流:
Set<String> set = new HashSet<>();
//通过 stream 默认方法获取流
Stream<String> stream2 = set.stream();
方式2: 根据数组获取流
//通过Stream 接口中提供了静态方法of
Stream<String> stream = Stream.of(array);
——常用方法:
终结方法:返回值类型不再是 Stream 接口自身类型的方法
count:统计个数
forEach 方法:并不保证元素的在流中是被有序执行的。
非终结方法:返回值类型仍然是 Stream 接口自身类型的方法;
filter:过滤
limit:取用前几个;
skip:跳过前几个;
Stream<String> result = original.skip(2);
concat:组合,把两个流合并成一个;
Stream<String> result = Stream.concat(streamA, streamB);
与Lambda表达式联合使用:
list.stream()
.filter(s -> s.startsWith("张")) //过滤开头为张的
.filter(s -> s.length() == 3) //过滤长度为3的
.forEach(s -> System.out.println(s)); //打印
}
5、函数拼接与终结方法
凡是返回值仍然为 Stream 接口的为函数拼接方法,它们支持链式调用;而返回值不再
为 Stream 接口的为终结方法,不再支持链式调用
二、File类
1、File类
类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。
2、构造方法:
public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File实例。
public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File实例。
3、常用方法
public String getAbsolutePath() :绝对路径名(字符串)
public String getPath() : 构造路径名(字符串)
public String getName() : 文件或目录的名称。
public long length() : 文件的长度。
File f = new File("d:/aaa/bbb.java");
输出结果:
文件绝对路径:d:\aaa\bbb.java
文件构造路径:d:\aaa\bbb.java
文件名称:bbb.java
文件长度:636字节
**绝对路径:**从盘符开始的路径,这是一个完整的路径。
**相对路径:**相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。
4、判断功能的方法
public boolean exists() : 此File表示的文件或目录是否实际存在。
public boolean isDirectory() :此File表示的是否为目录。
public boolean isFile() : 此File表示的是否为文件。
5、创建删除功能的方法
public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
public boolean mkdir() : 创建由此File表示的目录。
public boolean mkdirs() : 创建由此File表示的目录,包括任何必需但不存在的父目录。
public boolean delete() : 删除由此File表示的文件或目录,java中删除动作不走回收站。
6、目录的遍历
public String[] list() :返回一个String数组,表示该File目录中的所有子文件或目录。
public File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录
目录遍历的代码:
//获取当前目录下的文件以及文件夹的名称。
String[] names = dir.list();
for(String name : names){
System.out.println(name);
}
7、递归搜索文件
——文件搜索:
public class DiGuiDemo3 {
public static void main(String[] args) {
// 创建File对象
File dir = new File("D:\\aaa");
// 调用打印目录方法
printDir(dir);
}
public static void printDir(File dir) {
// 获取子文件和目录
File[] files = dir.listFiles();
// 循环打印
for (File file : files) {
if (file.isFile()) {
// 是文件,判断文件名并输出文件绝对路径
if (file.getName().endsWith(".java")) {
System.out.println("文件名:" + file.getAbsolutePath());
} else {
// 是目录,继续遍历,形成递归
printDir(file);
}
三、基本流(字节流、字符流)
1、分类:
2、字节流:
2.1 字节输出流【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) :将指定的字节输出流。
2.2 子类【FileOutputStream】
构造方法:
public FileOutputStream(File file) :创建文件输出流以写入由指定的 File对象表示的文件。
public FileOutputStream(String name) : 创建文件输出流以指定的名称写入文件。
public class FOSWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 字符串转换为字节数组
byte[] b = "abcde".getBytes();
// 写出从索引2开始,2个字节。也就是cd。
fos.write(b,2,2);
// 关闭资源
fos.close();
}
输出结果:
cd
数据的追加
public FileOutputStream(File file, boolean append) :
创建文件输出流以写入由指定的 File对象表示的文件。
public FileOutputStream(String name, boolean append) :
创建文件输出流以指定的名称写入文件。
true 表示追加数据, false 表示清空原有数据。
为false:cd
为true:cdabcde
Windows系统里,换行符号是 \r\n
2.3 字节输入流【InputStream】
共性的的方法:
public void close() : 关闭此输入流并释放与此流相关联的任何系统资源。
public abstract int read() : 从输入流读取数据的下一个字节。
public int read(byte[] b) : 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。
2.4 子类【FileInputStream】
——构造方法:
FileInputStream(File file) : 通过打开与实际文件的连接来创建一个 FileInputStream ,
该文件由文件系统中的 File对象 file命名。
FileInputStream(String name) : 通过打开与实际文件的连接来创建一个 FileInputStream ,
该文件由文件系统中的路径名 name命名
流操作完毕后,必须释放系统资源,调用close方法,千万记得。
重要代码:
public class Copy {
public static void main(String[] args) throws IOException {
// 1.创建流对象
FileInputStream fis = new FileInputStream("D:\\test.jpg");
FileOutputStream fos = new FileOutputStream("test_copy.jpg");
// 2.读写数据
byte[] b = new byte[1024];
int len;
while ((len = fis.read(b))!=-1) {
fos.write(b, 0 , len);
}
// 3.关闭资源
fos.close();
fis.close();
}
3、字符流
3.1 字符输入流【Reader]
共性方法:
public void close() : 关闭此流并释放与此流相关联的任何系统资源。
public int read() : 从输入流读取一个字符。
public int read(char[] cbuf) : 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中
3.2 子类:【FileReader类]
构造方式:
FileReader(File file) : 创建一个新的 FileReader ,给定要读取的File对象。
FileReader(String fileName) : 创建一个新的 FileReader ,给定要读取的文件的名称。
3.3 字符输出流【Writer】
共性方法:
public abstract void close() : 关闭流,释放系统资源。关闭前会刷新缓冲区
public abstract void flush() : 刷新缓冲区,流对象可以继续使用。
public void write(int c) : 写出一个字符。
public void write(char[] cbuf) :将 b.length字符从指定的字符数组写出此输出流。
public abstract void write(char[] b, int off, int len) :
从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。
public void write(String str) : 写出一个字符串。
3.4 子类【FileWriter】
构造方法:
FileWriter(File file) : 创建一个新的 FileWriter,给定要读取的File对象。
FileWriter(String fileName) : 创建一个新的 FileWriter,给定要读取的文件的名称
flush : 刷新缓冲区,流对象可以继续使用。
close : 关闭流,释放系统资源。关闭前会刷新缓冲区
即便是flush方法写出了数据,操作的最后还是要调用close方法,释放系统资源。
字符流,只能操作文本文件,不能操作图片,视频等非文本文件。
当我们单纯读或者写文本文件时 使用字符流 其他情况使用字节流
IO异常的处理
利用try…catch进行处理
try {
//可能产生异常的位置
fw = new FileWriter("fw.txt");
} catch (IOException e) {
e.printStackTrace();//异常的处理方式
} finally {
//无论怎样都会执行的代码
}
4、属性集Properties类
构造方式:
public Properties() : 创建一个空的属性列表
基本方法:
public Object setProperty(String key, String value) : 保存一对属性。
public String getProperty(String key) : 使用此属性列表中指定的键搜索属性值。
public Set<String> stringPropertyNames() : 所有键的名称的集合
基本储存属性的方式(存储在properties对象中):
// 创建属性集对象
Properties properties = new Properties();
// 添加键值对元素
properties.setProperty("filename", "a.txt");
// 打印属性集对象
System.out.println(properties);
// 通过键,获取属性值
System.out.println(properties.getProperty("filename"));
利用流的方式从文件中获取属性:
public void load(InputStream inStream) : 从字节输入流中读取键值对。
public static void main(String[] args) throws FileNotFoundException {
// 创建属性集对象
Properties pro = new Properties();
// 加载文本中信息到属性集
pro.load(new FileInputStream("read.txt"));
// 遍历集合并打印
Set<String> strings = pro.stringPropertyNames();
for (String key : strings ) {
System.out.println(key+" -- "+pro.getProperty(key));
}//filename -- a.txt
四、缓冲流
1、缓冲流
缓冲流,也叫高效流,是对4个基本的 FileXxx 流的增强,所以也是4个流;
—分类:
字节缓冲流: BufferedInputStream , BufferedOutputStream
字符缓冲流: BufferedReader , BufferedWriter
—基本原理:
是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率
2、字节缓冲流【BufferedInputStream】【BufferedOutputStream】
构造方法:
public BufferedInputStream(InputStream in) : 创建一个 新的缓冲输入流。public BufferedOutputStream(OutputStream out) : 创建一个新的缓冲输出流。
缓存流的速度比基本的流对象的传输速度快了很多;
3、字符缓冲流【BufferedReader】【BufferedWriter】
构造方法:
public BufferedReader(Reader in) :创建一个 新的缓冲输入流。
public BufferedWriter(Writer out) : 创建一个新的缓冲输出流。
特有的方法:
BufferedReader: public String readLine() : 读一行文字。
BufferedWriter: public void newLine() : 写一行行分隔符,(也就是换行)。
——文字排序的案例:
public class BufferedTest {
public static void main(String[] args) throws IOException {
// 创建map集合,保存文本数据,键为序号,值为文字
HashMap<String, String> lineMap = new HashMap<>();
// 创建流对象
BufferedReader br = new BufferedReader(new FileReader("in.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
// 读取数据
String line = null;
while ((line = br.readLine())!=null) {
// 解析文本
String[] split = line.split("\\.");
// 保存到集合
lineMap.put(split[0],split[1]);
}
// 释放资源
br.close();
// 遍历map集合
for (int i = 1; i <= lineMap.size(); i++) {
String key = String.valueOf(i);
// 获取map中文本
String value = lineMap.get(key);
// 写出拼接文本
bw.write(key+"."+value);
// 写出换行
bw.newLine();
}
// 释放资源
bw.close();
}
五、转换流
1、转换流【InputStreamReader】【OutputStreamWriter类】
构造方法:
InputStreamReader(InputStream in) : 创建一个使用默认字符集的字符流。
InputStreamReader(InputStream in, String charsetName) : 创建一个指定字符集的字符流
——OutputStreamWriter类
构造方法:
OutputStreamWriter(OutputStream in) : 创建一个使用默认字符集的字符流。
OutputStreamWriter(OutputStream in, String charsetName) : 创建一个指定字符集的字符流。
2、案例:转换文件编码
将GBK编码的文本文件,转换为UTF-8编码的文本文件。
- 指定GBK编码的转换流,读取文本文件。
- 使用UTF-8编码的转换流,写出文本文件。
public class TransDemo {
public static void main(String[] args) {
// 1.定义文件路径
String srcFile = "file_gbk.txt";
String destFile = "file_utf8.txt";
// 2.创建流对象
// 2.1 转换输入流,指定GBK编码
InputStreamReader isr = new InputStreamReader(new FileInputStream(srcFile)
, "GBK");
// 2.2 转换输出流,默认utf8编码
OutputStreamWriter osw = new OutputStreamWriter(new
FileOutputStream(destFile));
// 3.读写数据
// 3.1 定义数组
char[] cbuf = new char[1024];
// 3.2 定义长度
int len;
// 3.3 循环读取
while ((len = isr.read(cbuf))!=-1) {
// 循环写出
osw.write(cbuf,0,len);
}
// 4.释放资源
osw.close();
isr.close();
}
六、序列化流
1、序列化【ObjectOutputStream类】
构造方法:
public ObjectOutputStream(OutputStream out) : 创建一个指定OutputStream的ObjectOutputStream
—序列化条件:
1、实现 java.io.Serializable 接口,只是标记接口;没有具体方法;
2、该类的所有属性必须是可序列化的。若有不需要可序列化的,使用transient 关键字修饰
public class Employee implements java.io.Serializable {
public String name;
public String address;
public transient int age; // transient瞬态修饰成员,不会被序列化
}
—写出对象的方法:
public final void writeObject (Object obj) : 将指定的对象写出
User user = new User();
user.name = "zhangsan";
// 创建序列化流对象
ObjectOutputStream out = new ObjectOutputStream(new
FileOutputStream("employee.txt"));
// 写出对象
out.writeObject(user);
// 释放资源
out.close();
fileOut.close();
2、反序列化【ObjectInputStream类】
反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象。
构造方法:
public ObjectInputStream(InputStream in) : 创建一个指定InputStream的ObjectInputStream。
方法:
public final Object readObject () : 读取一个对象。
案例:
// 创建反序列化流
FileInputStream fileIn = new FileInputStream("employee.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
// 读取一个对象(User是一个bean对象名)
User e = (User) in.readObject();
// 释放资源
in.close();
fileIn.close();
七、打印流【PrintStream】
public PrintStream(String fileName) : 使用指定的文件名创建一个新的打印流
更改打印流的输出位置:
public class PrintDemo {
public static void main(String[] args) throws IOException {
// 调用系统的打印流,控制台直接输出97
System.out.println(97);
// 创建打印流,指定文件的名称
PrintStream ps = new PrintStream("ps.txt");
// 设置系统的打印流流向,输出到ps.txt
System.setOut(ps);
// 调用系统的打印流,ps.txt中输出97
System.out.println(97);
}
八、字符编码和字符集
编码: 按照某种规则,将字符存储到计算机中;
解码: 将存储在计算机中的二进制数按照某种规则解析显示出来;
常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。
九、常用工具类
1、读取文件中数据
/**
* @param filePath 文件目录
* @return
*/
public static String getFileData(String filePath) {
try {
// 1.创建流对象
FileInputStream fis = null;
fis = new FileInputStream(filePath);
StringBuilder stringBuilder = new StringBuilder();
// 2.读写数据
byte[] b = new byte[1024];
int len;
while ((len = fis.read(b)) != -1) {
String s = new String(b, 0, len);
stringBuilder.append(s);
}
// 3.关闭资源
fis.close();
return stringBuilder.toString();
} catch (IOException e) {
log.error("获取文件失败:{}", e.getMessage());
return null;
}
}
十、Xmind整理
https://download.csdn.net/download/weixin_44624117/12702080
链接:https://pan.baidu.com/s/1zF1ryT89AHdXdkLyduaNew
提取码:5l0s