1.10 I/O流 最全 最全 最全整理


Java的IO流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作,在Java中把不同的输入/输出源(键盘、文件、网络连接等)抽象表述为“流”(stream),通过流的方式允许Java程序使用相同的方式来访问不同的输入输出源。

stream是从起源(source)到接收(sink)的有序数据。Java把所有传统的流类型(类或抽象类)都放在java.io包中,用以实现输入输出功能。

一、流的分类:

Java的IO流共涉及40多个类,这些类看上去芜杂而凌乱,但实际上非常规则,而且彼此之间存在非常紧密的联系Java的IO流的40多个类都是从如下4个抽象基类派生的。

I/O流

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、字节输出流【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) :将指定的字节输出流。

字节输出流子类: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

3、数据的追加

public FileOutputStream(File file, boolean append) :
             创建文件输出流以写入由指定的 File对象表示的文件。
public FileOutputStream(String name, boolean append) : 
             创建文件输出流以指定的名称写入文件。
true 表示追加数据, false 表示清空原有数据。
为false:cd
为true:cdabcde
Windows系统里,换行符号是 \r\n

4、字节输入流【InputStream】

共性的的方法:

public void close() :         关闭此输入流并释放与此流相关联的任何系统资源。
public abstract int read() : 从输入流读取数据的下一个字节。
public int read(byte[] b) :  从输入流中读取一些字节数,并将它们存储到字节数组 b中 。

5、子类: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();
}

6、字符输入流【Reader】

共性方法:

public void close() :      关闭此流并释放与此流相关联的任何系统资源。
public int read() :         从输入流读取一个字符。
public int read(char[] cbuf) : 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中

7、子类:FileReader类

构造方式:

FileReader(File file) :        创建一个新的 FileReader ,给定要读取的File对象。
FileReader(String fileName) :  创建一个新的 FileReader ,给定要读取的文件的名称。

8、字符输出流【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) :  写出一个字符串。

9、子类:FileWriter类

构造方法:

FileWriter(File file) :      创建一个新的 FileWriter,给定要读取的File对象。
FileWriter(String fileName) : 创建一个新的 FileWriter,给定要读取的文件的名称

**flush :**刷新缓冲区,流对象可以继续使用。

**close :**关闭流,释放系统资源。关闭前会刷新缓冲区

即便是flush方法写出了数据,操作的最后还是要调用close方法,释放系统资源。

字符流,只能操作文本文件,不能操作图片,视频等非文本文件。

当我们单纯读或者写文本文件时 使用字符流 其他情况使用字节流

10、IO异常的处理

利用try。。。catch进行处理

try {
    //可能产生异常的位置
fw = new FileWriter("fw.txt");
} catch (IOException e) {
e.printStackTrace();//异常的处理方式
} finally {
    //无论怎样都会执行的代码
}

11、属性集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编码的文本文件。

  1. 指定GBK编码的转换流,读取文本文件。
  2. 使用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字符集等。

在这里插入图片描述

九、Xmind整理

在这里插入图片描述

CSDN地址:

https://download.csdn.net/download/weixin_44624117/12702080

百度网盘地址:

链接:https://pan.baidu.com/s/1zF1ryT89AHdXdkLyduaNew 
提取码:5l0s

posted @ 2020-08-12 13:58  ah_lydms  阅读(147)  评论(0编辑  收藏  举报