千峰教育2218期 IO 流

10102022.12.27 笔记 -- IO流

今天的内容

File 类
IO 流

1. File 类

File 类是 Sun 公司提供的内置的类,专门处理磁盘上面的文件和文件夹上的类
咱们 window 系统可以通过鼠标右键新建一个文件或者是文件夹,但是咱们也可以通过 Java 代码来新建文件或者文件夹,或删除文件,使用 File 类
路径问题:
相对路径
得有参照物
我在张三前面坐着。参照物是张三,
./ 当前的工作目录
../ 上一级目录
../../ 上上一级目录
./note2

绝对路径
郑州市二七区海威科技园 C 区十层的 8 教室第二排的第四个有个我。
从磁盘的根目录一直找。
D:\AQF\x64\note\note3
/ windows 和 Linux 系统都是可以的
\ windows 系统可以的 Linux 不可以的
开发中用 /

想学一个新的类 File,咱们首先关注这几点

1. 打开 API 官方手册
2. 看构造方法,为啥看构造方法?
3. 看方法
	看方法的意思,也就是功能
	看方法的参数
	看方法的返回值	
`[File](../../java/io/File.html#File(java.lang.String))(String pathname)`   
  • 通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。

package com.study.file;

import java.io.File;

/**
 * @author big God
 * @date 2022/12/27 21:36 * @version 1.0
 */
public class Demo1 {
    public static void main(String[] args) {
        /*
        * ctrl + shift + ? 多行注释的快捷键
        * 把一个字符串的路径变成 file 对象的路径
        * 拿对象可以对当前文件路径进行操作 删除 新建 等
        * */
        File file = new File("D:/AQF/x64/note/1.png");
        System.out.println(file);

        // window 系统 \ 也可以 转义字符
        File file1 = new File("D:\\AQF\\x64\\note\\1.png");
        System.out.println(file1);

        // static String separator
        // 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。

        // File.separator 在 window 系统是 \  在 linux 系统下面是 /
        System.out.println(File.separator); // \
        // 会自动默认
        // "D:/AQF/x64/note/1.png"  这种兼容性是更好的!!!
        File file2 = new File("D:" + File.separator + "AQF" + File.separator + "x64" + File.separator + "note" + File.separator + "1.png");
        System.out.println(file2);
    }
}
1.1 File 类中的方法
boolean createNewFile(); 创建一个新的文件
注意事项:
如果文件的路径不存在,报错,系统找不到文件的路径
如果文件的名字存在了,再创建会返回 false
磁盘坏了,不能进行读写的操作了,也创建不成功的
boolean mkdir(); 创建单机的文件夹 directory
boolean mkdirs(); 创建多机的文件夹
package com.study.file;

import java.io.File;
import java.io.IOException;

/**
 * @author big God
 * @date 2022/12/27 22:05 * @version 1.0
 */
public class Demo2 {
    public static void main(String[] args) throws IOException {
        File file = new File("D:/aaa/11.txt");
        System.out.println(file.createNewFile());

        // 创建单级文件夹
        File file1 = new File("D:/aaa/aaa");
        System.out.println(file1.mkdir());

        // 想要创建多级文件夹,使用另外一个方法,mkdirs()
        File file2 = new File("D:/aaa/aaa/aaa/aaa/aaa/aaa");
        System.out.println(file2.mkdirs());
    }
}
删除文件或者文件夹
boolean delete(); 立即删除文件
void deleteOnExit(); 不是立即删除,程序退出以后才删除【不常用】
package com.study.file;

import java.io.File;
import java.util.Scanner;

/**
 * @author big God
 * @date 2022/12/27 22:25 * @version 1.0
 */
public class Demo3 {
    public static void main(String[] args) {
        File file = new File("D:/aaa/11.txt");
        // 删除文件
        System.out.println(file.delete());

        // 删除文件夹,删除文件夹的时候一定此文件夹里面没有内容(没有文件或者文件)
        // 只能删除空的文件夹
        File file1 = new File("D:/aaa/a");
        System.out.println(file1.delete());
        // 删除不了 aaa 文件夹,因为 aaa 文件夹不是空文件夹
        System.out.println(new File("D:/aaa/aaa/aaa").delete());

        // deleteOnExit(); 退出程序才删除
        // 咋保证先不退出程序呢?
        File file2 = new File("D:\\aaa\\条条.txt");
        file2.deleteOnExit();
        Scanner scanner = new Scanner(System.in);
        scanner.nextInt();
    }
}
 
FIle对象中判断方法【开发中常用的几个方法】
boolean isFile(); 判断是否是文件
boolean isDirectory(); 判断是否是文件夹
boolean isHidden(); 判断是否是隐藏文件【不常用】
boolean isAbsolute(); 判断是否是绝对路径 【不常用】
boolean exists(); 判断文件或者文件夹是否存在
package com.study.file;

import java.io.File;
import java.io.IOException;

/**
 * @author big God
 * @date 2022/12/28 10:09 * @version 1.0
 */
public class Demo4 {
    public static void main(String[] args) throws IOException {
        File file = new File("D:/aaa/1.txt");
        System.out.println(file.isFile()); // true
        File file1 = new File("D:/aaa");
        System.out.println(file1.isFile()); // false
        System.out.println(file1.isDirectory()); // true

        System.out.println(file.isHidden()); // false
        System.out.println(file.isAbsolute()); // true

        System.out.println(file.exists()); // true

        // 文件不存在的时候
        if (!file.exists()) {
            // 文件存在不创建,文件不存在就创建
            file.createNewFile();
        }
    }
}
返回值是字符串类型的数据
String getName(); 获取文件或者文件夹的,名字
String getPath(); 获取路径
String getParent(); 获取当前文件的上一级目录
package com.study.file;

import java.io.File;

/**
 * @author big God
 * @date 2022/12/28 10:22 * @version 1.0
 */
public class Demo5 {
    public static void main(String[] args) {
        File file = new File("D:/aaa/1.txt");
        // 字符串的 1.txt
        System.out.println(file.getName());
        File file1 = new File("D:/aaa");
        // aaa
        System.out.println(file1.getName());
        // D:\aaa 字符串
        System.out.println(file1.getPath());
        // D:\
        System.out.println(file1.getParent());
    }
}
返回值是 long 类型数据的
long length(); 返回的是文件占用的字节数
long lastModified(); 获取当前文件最后一次修改的时间
package com.study.file;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author big God
 * @date 2022/12/28 10:22 * @version 1.0
 */
public class Demo5 {
    public static void main(String[] args) throws ParseException {
        File file = new File("D:/aaa/1.txt");
        // 字符串的 1.txt
        System.out.println(file.getName());
        File file1 = new File("D:/aaa");
        // aaa
        System.out.println(file1.getName());
        // D:\aaa 字符串
        System.out.println(file1.getPath());
        // D:\
        System.out.println(file1.getParent());
        // 3181440 个字节
        System.out.println(file.length());
        // 1668484958495 时间戳  毫秒数
        // 从 1970 年 1 月 1 日 00:00:00 到现在的毫秒数
        System.out.println(file.lastModified());

        // 创建一个日期格式化工具,指定日期的格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 格式化日期对象:毫秒值 =》 自定义日期格式
        System.out.println(simpleDateFormat.format(file1.lastModified()));
        // 获取当前时间
        System.out.println(new Date());
        // 获取当前时间转换成毫秒值 并 格式化日期对象,转成自定义格式
        System.out.println(simpleDateFormat.format(new Date().getTime()));
        // 获取当前时间转换成毫秒值
        System.out.println(simpleDateFormat.format(new Date()));
        // 格式化日期对象:字符串 =》 日期对象 日期格式需要和格式化工具中的预设格式相同,否则会报错
        System.out.println(simpleDateFormat.parse("2022-7-12 10:10:10"));
    }
}
File[] listFiles(); 获取当前文件夹下所有的文件或者文件夹,返回值是文件数组
String[] list(); 获取当前路径下面的所有的文件夹或者文件,返回值是一个字符串数组
package com.study.file;

import java.io.File;
import java.util.Arrays;

/**
 * @author big God
 * @date 2022/12/28 11:03 * @version 1.0
 */
public class Demo6 {
    public static void main(String[] args) {
        File file = new File("D:/");
        System.out.println(Arrays.toString(file.listFiles()));
        // 碰到数组有啥想法?
        for (File listFile : file.listFiles()) {
            // 是 file 对象
            System.out.println(listFile);
        }
        System.out.println("===============");
        for (String s : file.list()) {
            // 是 字符串
            System.out.println(s);
        }
    }
}

上午回顾

File类方法
	没有别的方法,只能记忆,通过作业来记忆一些东西
1.2 关于 File 类练习题
  • 递归: 方法会自己调用自己 ,但是一定要加结束条件,如果让其一直调用下去会内存溢出

  • StackOverflowError

package com.study.file;

/**
 * @author big God
 * @date 2022/12/28 11:11 * @version 1.0
 */
public class Demo7 {
    public static void main(String[] args) {
        test();
    }
    public static void test () {
        System.out.println("嘻嘻");
        test();
    }
}
删除某一个目录下面的所有的文件
第一步:
	aaa/aaa:
		1.txt;
		aaa;
第二步:
	aaa/aaa/aaa
		2.txt;
		aaa; 
package com.study.file;

import java.io.File;

/**
 * @author big God
 * @date 2022/12/28 11:19 * @version 1.0
 */
public class Demo8 {
    public static void main(String[] args) {
        File file = new File("D:/aaa/aaa");
        // 使用递归删除 自己调用自己, 得有结束条件
        del(file);
    }
    public static void del(File file) {
        // 将 aaa 文件夹下面的所有的文件和文件夹取出来
        for (File listFile : file.listFiles()) {
            // D:\aaa\aaa\1.txt
            // D:\aaa\aaa\aaa
            // 碰到文件就删除,碰到文件夹就再次进入
            // System.out.println(listFile);
            // 判断是否是文件夹
            if (listFile.isDirectory()) {
                // 是文件夹的情况
                // 继续进入到文件夹 aaa
                // 递归
                del(listFile);
            } else {
                // 是文件的情况
                listFile.delete();
            }
        }
    }
}

2. IO 流【重点】

以后开发中会遇到比如上传文件,下载文件,导入,导出功能等,都是需要 io 流的
咱们电脑上面的文件,文档 音频 视频 等 图片,等都是可以进行读和写的 !!!
处理文件的时候,形式以流的形式处理的。IO 流比较抽象
有一个城楼在二七区的海威科技园,现在我想把这个城楼复制一份弄到高新区的海威科技园 咋弄? 要求:原滋原味。用的材料还是二七区的海威科技园的材料 咋办? 拆成一个一个的材料 搬运到高新区再重新建筑
和 IO 流特别像。
一个图片你把它复制到另一个地方,通过流来操作,将图片变成一个字节一个字节的。 传输到另一个地方,再把一个字节一个字节的数据堆砌起来变成一个文件。中间的过程将文件变成一个字节一个字节的形式就是流的形式,相当于水流。
2.1 缓冲的概念
看视频有点卡,暂停一下,加载缓冲一下。
快递:中转站,不是派送一件送货一件,而是赞够一批一块送,效率高!!!!!!。
IO 流的本质就是对电脑上的文件进行读和写
计算机是通过 CPU 内存读取硬盘上的数据,可以加入缓冲的效果,每次读取 4 kb。 搬砖一样。一次搬运一个砖头,和一次用斗车搬运一斗车,效果不一样,斗车就是缓冲效果。
2.2 IO 流分类
I:
input: 输入。从磁盘的某一个文件中的数据读取到内存(Java 代码)展示一下。
O:
output: 输出,从内存(Java 代码中 String str = "abcd")写入到磁盘中某一个文件中 1.txt。
参照物: 是内存
磁盘 => 内存 输入流
字节输入流:
字符输入流:
内存 => 磁盘 输出流:
字节输出流:
字符输出流:
2.3 字节流
2.31 字节输入流
Java 给咱们封装了一个类:FileInputStream
能干嘛?需求:磁盘上面 D:/aaa/1.txt. 将 1.txt 数据读取到 Java 代码中展示出来
磁盘 => 内存

**[FileInputStream](../../java/io/FileInputStream.html#FileInputStream(java.io.File))**(File file)

通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。

package com.study.io;

import java.io.*;
import java.util.Arrays;

/**
 * @author big God
 * @date 2022/12/28 12:01 * @version 1.0
 */
public class Demo1 {
    public static void main(String[] args) throws IOException {
        // 场景: 从 D 盘的 aaa 下的 1.txt 把数据读取出来。读取到内存中(Java 代码)
        // 1. 创建 File 对象,数据源文件对象
        // 2. 创建字节输入流对象,来操作数据源文件 file 对象
        FileInputStream fileInputStream = new FileInputStream(new File("D:/aaa/1.txt"));
        // 3. fileInputStream 字节输入流 本身不具备缓冲功能
        // 可以对 fileInputStream 加上一个缓冲效果 借助与一个类
        // BufferedInputStream   为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。
        // 4. 使用 BufferedInputStream 流给 fileInputStream 加上缓冲效果
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
        // 5. 代码走到这一步,字节输入流就已经具备缓冲效果了
        // 在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。
        byte[] buf = new byte[4]; // 字节数组,数组的容量是 4 个字节 byte 是字节的意思
        // 现在代码到这,数组是空的数组,用来存储每次从 1.txt 文件中读取的数据,一次可以存储 4 个字节
        // 为啥是字节数组?因为是字节流所以用字节数组!!!

        // 6.int read(byte[] b)
        // 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
        int read = bufferedInputStream.read(buf);
        // 读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。
        System.out.println(read); // 4
        // 想看数组中的数据咋办?
        // UsCode 编码值  K S E R
        System.out.println(Arrays.toString(buf)); // [75, 83, 69, 82]
        // [K, S, E, R] String (buf, 0, 2) => [a, b, c]
        System.out.println(new String(buf,0,2)); // K S E R
        // 流程:  1.txt(数据) => file => fileInputStream => bufferedInputStream
        // bufferedInputStream(数据).read(buf);
        // 将数据读取出来存在缓冲数组【容器】 buf 这个数组一次只能读进去四个字节
        // 数组不在是空的了, 存储了四个字节的数据
        
        // 7. 流失需要关闭的  
        // 先开后关
        bufferedInputStream.close();
        fileInputStream.close();
    }
}
结果:
xixi
4
abcd
xixi
1
ebcd

数据源: abcde
while ((length = bufferedInputStream.read(buf)) != -1) {
            System.out.println("嘻嘻");
            System.out.println(length);
            System.out.println(new String(buf));
        }
xixi
4
buf = [a, b, c, d]
new String(buf) ==> abcd

循环第二次:
legth = bufferedInputStream.read(buf) = 1
xixi
1
// 原数组是【a, b, c, d】 第二次循环 e 替换了 a
buf = [e, b, c, d];
new String(buf) ==> ebcd

这个循环结束 到达流的末尾了
length = -1 -1 != -1 ==> false 循环结束
xixi
4
abcd
new String(buf,0, 4)[a, b, c, d] => abcd
xixi
1
e
new String(buf,0,1)[e,b, c,d] => e
package com.study.io;

import java.io.*;
import java.util.Arrays;

/**
 * @author big God
 * @date 2022/12/28 16:16 * @version 1.0
 */
public class Demo2 {
    public static void main(String[] args) throws IOException {
        // 1. 创建 File 对象
        File file = new File("D:/aaa/1.txt");
        // 2. 创建字节输入流
        FileInputStream fileInputStream = new FileInputStream(file);
        // 3. 给 fileInputStream 加缓冲效果
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
        // 4. 准备一个缓冲数组,设置一次存储的字节
        byte[] buf = new byte[8]; // 现在是一个空的数组【0, 0, 0, 0, 0, 0, 0, 0】
        // 5. 读取数据到缓冲数组中,此时数据源在 bufferedInputStream 读取到缓冲数组中
        // public int read(byte[] b)
        //         throws IOException从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
        //         返回:读入缓冲区的字节总数
        // System.out.println(bufferedInputStream.read(buf));; // 将 bufferedInputStream 数据存到数组中 buf 中
        // System.out.println(Arrays.toString(buf));
        // System.out.println(new String(buf)); // 将数组中的数据转成字符串并打印出来

        long startTime = System.currentTimeMillis();
        int length;
        // 将 bufferedInputStream 里面的数据 读取到 buf 数组中,并返回一个 int 类型的值,实际读取的字节数
        // 如果达到流的末尾的时候,返回值是一个 -1 ,就意味着循环结束,不再进行读取了
        while ((length = bufferedInputStream.read(buf)) != -1) {
            System.out.println("嘻嘻");
            System.out.println(length);
            System.out.println(new String(buf, 0, length));
        }
        long endTime = System.currentTimeMillis();
        System.out.println((endTime - startTime) / 1000 + "秒");

        // 6. 关闭资源流 先开后关
        bufferedInputStream.close();
        fileInputStream.close();
    }
}

2022.12.29 笔记 -- IO流

复习

public class Demo1 {
    public static void main(String[] args) throws IOException {
        File file = new File("D:/aaa/111.txt");
        System.out.println(file.createNewFile());
        System.out.println(file.isFile());
        System.out.println(file.getName());
        System.out.println(file.isDirectory());
        System.out.println(file.delete());
    }
}

public class Demo2 {
    public static void main(String[] args) throws ParseException {
        File file = new File("D:/aaa/刑天铠甲变身.txt");
        System.out.println(file.exists());
        System.out.println(file.isDirectory());
        System.out.println(file.getPath());
        System.out.println(file.getParent());
        System.out.println(file.lastModified());
        // 创建日期格式化对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 日期转字符串
        System.out.println(sdf.format(new Date()));
        // 字符串转自定义格式日期
        System.out.println(sdf.parse("2022-12-29 12:12:12"));
        // 日期转字符串
        System.out.println(sdf.format(file.lastModified()));
        System.out.println(file.length());
        System.out.println(file.isHidden());
        System.out.println(file.isAbsolute());
        System.out.println(file.mkdir());
        File file1 = new File("D:/aaa/aaa/bbb/bbb");
        System.out.println(file1.mkdirs());
        File file2 = new File("D:/aaa");
        for (String s : file2.list()) {
            System.out.println(s);
        }
        for (File listFile : file2.listFiles()) {
            System.out.println(listFile);
        }
    }
}

public class Demo3 {
    public static void main(String[] args) {
        // 创建目标路径对象
        // 把一个字符串的路径变成 file 对象的路径
        File file = new File("D:/aaa/aaa");
        // 调用方法
        del(file);
    }

    public static void del(File file) {
        // 循环遍历所有文件名
        for (File listFile : file.listFiles()) {
            // 判断是文件或者文件夹
            if (listFile.isDirectory() ) {
                // 递归 继续调用此方法
                del(listFile);
            } else {
                // 遇到文件则删除
                System.out.println(listFile.delete());
            }
        }
    }
}

public class Demo4 {
    public static void main(String[] args) throws IOException {
        // 字节输入流对象加缓冲效果
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("D:/aaa/刑天铠甲变身.txt")));
        // 创建一个缓冲数组 设置一次缓冲的容量
        byte[] buf = new byte[8];
        int length;
        while ((length = bis.read(buf)) != -1) {
            // 将对象中的数据循环存储到数组中 磁盘 => 内存
            System.out.println("奥特曼");
            System.out.println(length);
            System.out.println(new String(buf,0,length));
        }
        // 关闭资源
        bis.close();
    }
}

今天的内容

IO流

1. IO流

1.1 字节输入流
FIleInputStream 从磁盘(D:/aaa/1.txt)读取数据到 Java 的内存中
磁盘 => 内存 输入
内存 => 磁盘 输出
package com.study.fileinputstream;

import java.io.*;

/**
 * @author big God
 * @date 2022/12/29 10:31 * @version 1.0
 */
public class Demo1 {
    public static void main(String[] args) throws IOException {
        // 1. 创建 File 对象
        File file = new File("D:/aaa/刑天铠甲变身.txt");
        // 2. 创建 字节输入流 FileInputStream 对象
        // 通过打开与实际文件的连接
        FileInputStream fis = new FileInputStream(file);
        // FileInputStream 本身不具备缓冲能力
        // BufferedInputStream 为另一个输入流添加了功能,既缓冲输入
        // 3. 加上一个缓冲效果 创建 BufferInputStream 对象
        BufferedInputStream bis = new BufferedInputStream(fis);
        // 4. FileInputStream 就具备缓冲效果了
        // 当创建 BufferedInputStream 时,将创建一个内部缓冲区数组
        byte[] buf = new byte[4];
        // 用来缓冲 1.txt 数据, 100 块砖头需要搬运 弄一个斗车(每次装 4 个砖头)
        int length;
        // 读取到缓冲区的总字节数,或者如果没有更多的数据,因为已经到达流的末尾,跳出循环
        // 循环第一次 abcde ==> [a, b, c, d]
        // 循环第二次 ==> [e, b, c, d]
        while ((length = bis.read(buf)) != -1) {
            System.out.println(length);
            // [a, b, c, d] ==> abcd
            // [e, b, c, d] ==> e
            // 就是为了展示 buf 中的缓冲数组中的数据的!!!
            System.out.println(new String(buf, 0, length));
        }
        // 关闭流
        bis.close();
        fis.close();
    }
}
练习
读取磁盘上的 2.txt 内容是 abcdefg 缓冲数组容量为 3, 使用循环打印出来
package com.study.fileinputstream;

import java.io.*;

/**
 * @author big God
 * @date 2022/12/29 10:54 * @version 1.0
 */
public class Demo2 {
    public static void main(String[] args) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("D:/aaa/2.txt")));
        byte[] buf = new byte[3];

        int length;
        while ((length = bis.read(buf)) != -1) {
            System.out.println(new String(buf, 0, length));
        }
        bis.close();
    }
}

字节输入流:将数据从磁盘读取到内存中(Java 中)

1.2 字节输出流
FileOutputStream:
将 Java 代码中的数据写入到磁盘上面
package com.study.fileoutputstream;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author big God
 * @date 2022/12/29 11:00 * @version 1.0
 */
public class Demo1 {
    public static void main(String[] args) throws IOException {
        // 现在的需求是将 Java 代码写入磁盘上面
        // String str = "嘻嘻哒"; ==> D:/aaa/3.txt
        // 1. 创建 File 对象
        File file = new File("D:/aaa/3.txt"); // 没有此文件
        file.createNewFile(); // 空的文件

        // 2. 字节输出流对象
        FileOutputStream fos = new FileOutputStream(file);

        // 3. 加缓冲流 BufferedOutputStream
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        // 4. 准备一个字符串,这个字符串是可以写入到磁盘中
        String str = "eee,曲项向天歌!!!";

        // 5. 将使用 bos 去写入到磁盘的文件
        byte[] buf = new byte[4];
        // public void write(byte[] b) throws IOException
        // 将 b.length 个字节写入此输出流。
        // 参数需要的是一个字节数组,但是现在是一个字符串,将字符串转换为字节数组
        byte[] b = str.getBytes();
        // 将 b 的数据写入到输出流 bos 中
        bos.write(b);

        // 6. 关闭流
        // 针对于写的情况,输出流 一定是先开后关
        // bos.flush(); // 刷新
        bos.close();
        fos.close();
        System.out.println("写入成功");
    }
}

练习:在自己磁盘上面新建一个空的 4.txt 文件,将 Java 中 String str = "我欲乘风归去"; 写入到 4.txt 文件中

package com.study.fileoutputstream;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author big God
 * @date 2022/12/29 11:42 * @version 1.0
 */
public class Demo2 {
    public static void main(String[] args) throws IOException {
        File file =new File("D:/aaa/4.txt");
        file.createNewFile();
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
        bos.write("我欲乘风归去".getBytes()); // 字节输出流
        bos.close();
    }
}

针对于字节输入流和字节输出流的综合案例

将 D:/aaa/1.mp4 文件复制到 c:/aaa/aaa/2.mp4 文件下面
思路: 先把 aaa/1.mp4 文件读取 (FileInputStream) 到内存,然后在从内存中写入(FileOutputStream) 到 aaa/aaa 文件夹中
package com.study.io;

import java.io.*;

/**
 * @author big God
 * @date 2022/12/29 12:00 * @version 1.0
 */
public class Demo1 {
    public static void main(String[] args) throws IOException {
        copeVideo1();
    }

    public static void copeVideo() throws IOException {
        /*
        * 将一个文件夹下面的视频复制到另一个文件夹下面
        * 将磁盘的 mp4 读取出来
        * 复制这个视频需要代码执行时间是多少?
        * */
        // 代码走到这个地方有一个起始时间
        long startTime = System.currentTimeMillis();
        // 1. 使用输入流将磁盘上面的数据读取到内存
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("D:/aaa/1.mp4")));
        // 2. 使用输出流将内存中的数据写入到磁盘
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("D:/aaa/aaa/2.mp4")));
        // 3. 准备一个字节数组的缓冲区
        // 一次读取的容量 4 kb
        byte[] buf = new byte[4 * 1024];
        // 4. 开始从磁盘中读取数据到内存
        int length;
        while ((length = bis.read(buf)) != -1 ) {
            // 循环一次 读取到 buf 到这个数组中 4 kb
            // 4098 byte 4096 字节 2
            bos.write(buf, 0, length);
        }
        // 关闭流
        bos.close();
        bis.close();
        // 终止时间 - 初始时间 = 所有时间  单位:毫秒数
        long endTime = System.currentTimeMillis();
        System.out.println(endTime - startTime + "毫秒");
    }
    // 不加缓冲效果的  耗时较长!!!
    public static void copeVideo1() throws IOException {
        long startTime = System.currentTimeMillis();
        FileInputStream fis = new FileInputStream(new File("D:/aaa/1.mp4"));
        FileOutputStream fos = new FileOutputStream(new File("D:/aaa/aaa/aaa/2.mp4"));
        int length;
        while ((length = fis.read()) != -1) {
            fos.write(length);
        }
        fos.close();
        fis.close();
        long endTime = System.currentTimeMillis();
        System.out.println(endTime - startTime + "毫秒");
    }
    // 想想为啥:
    // 4096 字节: 如果是缓冲流 循环一次 
    //            过不是缓冲流 循环 4096 次
    
}
练习:找一张图片放到你的 D 盘下面的 aaa 文件夹下面 复制到 D:/aaa/aaa 下面
package com.study.io;

import java.io.*;

/**
 * @author big God
 * @date 2022/12/29 15:30 * @version 1.0
 */
public class Demo2 {
    public static void main(String[] args) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("D:/aaa/2.mp4")));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("D:/aaa/bbb/1.mp4")));
        byte[] buf = new byte[4];
        int length;
        while ((length = bis.read(buf)) != -1) {
            bos.write(buf, 0, length);
        }
        bos.close();
        bis.close();
    }
}
练习:复制一个图片,你自己找图片
1.3 字符输入流【非重点】
FileReader :用来读取字符文件的便捷类。读取文本文档的非常好用且便利的一个类。
咱们以后读取一本小说,txt 文档可以借助于字符输入流
读取音频、视频、图片可以用字符流吗?
FileReader 用于读取字符流。要读取原始字节流,请考虑使用 FileInputStream。
咱们音频 视频 图片最小的单位是字节不是字符,不能使用字符流
字符输入读取数据的时候是有局限性的,不能读取音频 视频 图片
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
底层其实还是字节流,只不过使用编码集将字节编码成了字符而已。

案例:磁盘上面有一个文件 D:/aaa/1.txt 将内容读取到内存中,使用字符输入流

package com.study.filereader;

import java.io.*;

/**
 * 字符输入流
 * @author big God
 * @date 2022/12/29 15:53 * @version 1.0
 */
public class Demo1 {
    public static void main(String[] args) throws IOException {
        // 1. 创建 File 对象 真实数据文本对象
        File file = new File("D:/aaa/2.txt");
        // 2. 创建字符输入流对象  目的为了读取 1.txt 内容
        FileReader fr = new FileReader(file);
        // 3. 为了提高效率,使用 BufferedReader 加缓冲区
        BufferedReader br = new BufferedReader(fr);
        // 4. 提供一个缓冲的数组 字符输入流
        // 字节输入流的时候 使用 byte 数组
        // 字符输入流的时候 使用 char 数组
        char[] ch = new char[4]; // 缓冲 4 个字符
        int length;
        // 5. 从流中读取字符出来 read
        while((length = br.read(ch)) != -1) {
            // 将数组通过 string 展示在控制台
            System.out.println(new String(ch, 0, length));
        }
        // 6. 关闭流
        br.close();
        fr.close();
    }
}
package com.study.filereader;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author big God
 * @date 2022/12/29 16:06 * @version 1.0
 */
public class Demo2 {
    public static void main(String[] args) throws IOException {
        // 不加缓冲流
        FileReader fr = new FileReader(new File("D:/aaa/3.txt"));
//        System.out.println(fr.read()); // 97
//        System.out.println(fr.read()); // 98
//        System.out.println(fr.read()); // 99
//        System.out.println(fr.read()); // 100
//        System.out.println(fr.read()); // -1
        int length;
        while ((length = fr.read()) != -1) {
            System.out.println(length);
        }
    }
}
package com.study.filereader;

import java.io.*;

/**
 * @author big God
 * @date 2022/12/29 16:14 * @version 1.0
 */
public class Demo3 {
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new FileReader(new File("D:/aaa/2.txt")));
//        System.out.println(bf.readLine()); // abcd
//        System.out.println(bf.readLine()); // null
        String str;
        while ((str = bf.readLine()) != null) {
            System.out.println(str);
        }
    }
}
1.4 字符输出流【非重点】
FileWriter:从内存写入数据到磁盘
写入一个字符串的数据到 D:/aaa/2.txt 文件中
package com.study.fileWriter;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**
 * 字符输出流
 * @author big God
 * @date 2022/12/29 16:27 * @version 1.0
 */
public class Demo1 {
    public static void main(String[] args) throws IOException {
        // 字符输出流 内存 ==> 磁盘
        File file = new File("D:/aaa/2.txt");
        FileWriter fw = new FileWriter(file);
        BufferedWriter bw = new BufferedWriter(fw);
        String str = "一定要努力!生活不会欺骗你!!";
        // 使用 bw  写入到磁盘里面

        // write(String str);
        // bw.write(str);

        // write(String str,int off, int length)
        // bw.write(str, 6,9);

        // write(char[] cbuf)
        // 现在 str 是字符串,但是 write 方法是数组字符
        // bw.write(str.toCharArray());

        // write(char[] cbuf, int off, int len)
        // ['生', '活', '一' ......]
        bw.write(str.toCharArray(), 6,9);
        // 关闭流
        bw.close();
        fw.close();
    }
}
练习:你们下载有小说 txt 文件的
需求: 复制一个 txt 文本到另外一个路径下面
package com.study.fileWriter;

import java.io.*;

/**
 * @author big God
 * @date 2022/12/29 16:42 * @version 1.0
 */
public class Demo2 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("D:/aaa/1.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:/aaa/aaa/1.txt"));
        char[] ch = new char[4 * 104]; // 4096 字符
        int length;
        while ((length = br.read(ch)) != -1) {
            bw.write(ch, 0, length);
        }
        bw.close();
        br.close();
    }
}

你们下去试一下,使用字符流复制图片或者视频 都是不行的

总结

  1. 你得知道输入流和输出流的功能:

  1. 输入流:从磁盘中读取数据到内存 (Java 代码)

  1. 输出流:从内存(Java 代码)写入数据到磁盘的

  1. 输入流:

  1. 两种:

  1. 字节输入流: FileInputStream

  1. 字符输入流:FIleReader

  1. 使用read 方法:进行读取

  1. 关于效率问题,他们有两个对应的缓冲流

  1. FileInputStream 对应的缓冲流: BufferedInputStream

  1. FileReader 对应的缓冲流:BufferedReader

  1. 输出流:

  1. 两种

  1. 字节输出流:FileOutputStream

  1. 字符输出流:FileWriter

  1. 使用 write 方法,进行写入

  1. 关于效率问题,他们有对应的缓冲流

  1. FileOutputStream 对应的缓冲流:BufferedOutputStream

  1. FileWriter 对应的缓冲流:BufferedWirter

  1. 注意

  1. 处理文本的时候,字符流和字节流都是可以的,没有效率区分

  1. 处理图片音频的时候,使用的是字节流,字符流不可以

  1. 总之以后开发使用字节流就可以了

2. Java 的序列化和反序列化【了解】

Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列。该字节序列包括该对象的数据,有关对象的类型的信息和存储在对象中数据的类型。
将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息,对象的数据,还有对象中的数据类型可以用来在内存中新建对象。
整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。
类 ObjectInputStream 和 ObjectOutputStream 是高层次的数据流,他们包含反序列化和序列化对象的方法。
概括:
将一个对象带着数据写入本地磁盘上面 emp.ser 文件这叫序列化 ObjectOutputStream(输出流)
将 emp.ser 这个文件中的数据取出来赋值给一个对象这叫反序列化ObjectInputStream(输入流)
2.1 序列化
将 Java 对象带着数据存到一个本地磁盘文件
package com.study.serialize;

import java.io.*;

/**
 * @author big God
 * @date 2022/12/29 19:09 * @version 1.0
 */
public class Demo1 {
    public static void main(String[] args) throws IOException {
        // 实例化对象,然后对对象进行赋值
        Emp emp = new Emp();
        emp.name = "屁桃";
        emp.address = "快手";
        emp.number = 1;
        // 需求:将 emp 这个对象写入到磁盘的 emp.ser 文件中 内存 => 磁盘 输出流
        // 后缀为.ser (serialize 序列化的意思)文件 默认告知这个文件时序列化的文件
//        File file = new File("D:/aaa/emp.ser");
//        FileOutputStream fos = new FileOutputStream(file);
        FileOutputStream fos = new FileOutputStream("D:/aaa/emp.ser");
        // 借助一个更高级的流
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(emp);

        oos.close();
        fos.close();
        // NotSerializableException  没有序列化的能力
        // Emp 这个类没有序列化的能力
        // 请注意: 一个类的对象想要序列化成功,必须暂时满足一个条件:
        //       该类必须实现 java.io.Serializable 接口。
    }
}
2.2 反序列化
将 emp.ser 文件读取出来,值赋值给一个对象
package com.study.serialize;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/**
 * 反序列化
 * @author big God
 * @date 2022/12/29 19:27 * @version 1.0
 */
public class Demo2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 反序列化
        FileInputStream fis = new FileInputStream("D:/aaa/emp.ser");
        // 借助一个高级的流对象
        ObjectInputStream ois = new ObjectInputStream(fis);
        Emp emp = (Emp) ois.readObject();
        System.out.println(emp.name);
        System.out.println(emp.address);
        System.out.println(emp.number);
    }
}
练习四:
	一个文件下(文件夹地址: C:/Users/bowang/eclipse-workespace)有多少个 Java 文件
练习五:
	编写一个程序,在命令行中以树状结构展现特定的文件夹以及其子文件(夹)
	例如:  C:/aaa/bbb/1.txt    C:/aaa/ccc/2.txt   C:/aaa/3.txt
	
		aaa
			bbb
				1.txt
			ccc  
				2.txt
			3.txt
package com.study.homework;

import java.io.File;
import java.util.ArrayList;

/**
 * 一个文件夹下(文件夹地址:"D:\\AQF\\eclipse\\workspace")有多少个java文件
 * @author big God
 * @date 2022/12/29 19:41 * @version 1.0
 */
public  class Demo1 {
    // 静态变量
    static int count = 0;
    public static void main(String[] args) {
        File file = new File("D:\\AQF\\eclipse\\workspace");
        selectFileJava(file);
        System.out.println(count + "个 Java 文件");
    }
    private static void selectFileJava(File file) {
        File[] files = file.listFiles();
        for (File file1 : files) {
            if (file1.isDirectory()) {
                // 碰到文件夹 之后再进去 递归
                selectFileJava(file1);

            } else {
                if (file1.getName().endsWith(".java")) {
                    System.out.println(file1.getName());
                    // 写入到文件中名字写入到文件中
                    count++;
                }
                // 碰到文件判断后缀
            }
        }
    }
}
package com.study.homework;

import java.io.File;

/**
 * 练习五:
 * 	编写一个程序,在命令行中以树状结构展现特定的文件夹以及其子文件(夹)
 * 	例如:  C:/aaa/bbb/1.txt    C:/aaa/ccc/2.txt   C:/aaa/3.txt
 *
 * 		aaa
 * 			bbb
 * 				1.txt
 * 			ccc
 * 				2.txt
 * 			3.txt
 * @author big God
 * @date 2022/12/29 20:05 * @version 1.0
 */
public class Demo2 {
    public static void main(String[] args) {
        File file = new File("D:/aaa");
        // 打印文件名字 aaa
        System.out.println(file.getName());
        tree(file, 1);
    }

    private static void tree(File file, int level) {
        // 设置缩进字符串
        String preStr = "  ";
        for (int i = 0; i < level; i++) {
            preStr += "  ";
        }
        for (int i = 0; i < file.listFiles().length; i++) {
            System.out.println(preStr + file.listFiles()[i].getName());
            if (file.listFiles()[i].isDirectory()) {
                tree(file.listFiles()[i], level + 1);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值