Java IO流开荒

0 IO概述

从Java代码上来看,输入流就是从外部(硬盘) 读取到内存中的,并且 以 Java的数据类型表示(byte String Int…)

处理完成这些读取来的数据

输出流 结果输出到某些地方

0.1 InputStream/OutputStream

IO字节流
IO流以byte 字节(8bit) 为最小的单位

0.2 Reader/Writer

IO字符流

需要读取的是字符,并且是多语种的(不全是单byte 的ASCII字符)
按照char来读写显然更方便,这个读取的最小单位是字符

在UTF-8 中 ,一个char :1~4 个byte
中文UTF-8中占用三个byte

GBK 中文占用 2 byte,但是只有中文和英文
UTF-8 中文占用三个
例如 Reader 数组 Hello世界,并且使用UTF-8,最终占用11个byte
hello ,英文占用一个byte
世界 ,中文每个占用三个byte

使用Reader,数据源虽然是byte,但是读入的都是char类型的字符,
原因是Reader内部做了byte的解码—>char
而使用InputStream是读取了byte 后续可以手动做转码
根据使用场景,灵活切换

0.3 同步异步

同步IO:IO时,必须等待数据返回后才能继续执行后续代码,编写简单 但是效率低 。java.io

异步IO:IO时,发出IO请求后,立即执行后续的代码,提高CPU效率 但是代码编写复杂。java.nio

1 File类的使用

  • Java.io.File:文件&文件路径的抽象形式,与平台无关
  • File能创建、删除、重命名文件和目录,但是File不能访问文件内容本身,需要用到IO流
  • 想要在Java程序中表示一个真实存在的文件或目录,必须有一个FIle对象,但是一个java对象不一定真实存在一个文件
  • File对象可以作为参数传递给contractor

File构造器
在这里插入图片描述

        //构造器1
        File file1 = new File("./data/hello.txt");
        File file2 = new File("D:\\workplace\\JavaTrain\\JavaSenior\\src\\main\\java\\JavaSenior\\d09\\data\\hello.txt");

        System.out.println(file1);
        System.out.println(file2);

        //构造器2
        File file3 = new File("D:\\workplace\\JavaTrain\\JavaSenior\\src\\main\\java\\JavaSenior\\", "data");
        System.out.println(file3);

        //构造器3
        File file4 = new File(file3, "hello.txt");
        System.out.println(file4);
  • 路径中每级目录之间用一个路径分隔符隔开
  • 路径分隔符与系统有关
    • windows DOS 用”\“来分隔
    • Unix URL 用”/“来分隔
  • java程序支持跨平台性,因此路径分隔符要慎重
  • 为解决这个隐患 File类提供一个常量:
public static final String sqparator //根据操作系统,动态提供分隔符

在这里插入图片描述

1.2 常用方法


    @Test
    public void test3() throws IOException {
        File file = new File("src/main/java/JavaSenior/d09/data/test");//Test中相对于当前Modul,Mian相对于工程
        if(!file.exists()){
            System.out.println(file.createNewFile());
            file.mkdir();
        }
        System.out.println(file.getAbsolutePath());

        File file2 = new File(file, "file2");

        File file3 = new File(file, "file2/file3");

        File file4 = new File(file, "file3/test.txt");

        if(!file4.exists()){
            file4.createNewFile();//createNewFile 为创建文件所用
        }

    }
}

2 IO流原理及流的分类

2.1 流的分类

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

3 节点流(或文件流)

3.1 读数据

3.1.1 fileReader

直接作用在文件之上的流
在这里插入图片描述

* **********流的体系结构
* 抽象基类                  节点流(文件流)                缓冲流(处理流的一种)
* InputStream              FileInputStream             BufferedInputStream
* OutputStream             FileOutPutStream            BufferedOutputStream
* Reader                   FileReader                  BufferReader
* Writer                   FileWriter                  BufferWriter
    /*
    * 将hello.txt 内容输出到控制台(内存)
    * */
    @Test
    public void testFileReader() throws IOException {
        //TODO 1 实例化对象 指明操作的文件
        File file = new File("src/main/java/JavaSenior/d09/data/hello.txt");//相较于当前modle
        //TODO 2 提供具体的流
        FileReader fileReader = new FileReader(file);
        //TODO 3 数据的读入过程
        int read = fileReader.read();//read()返回读入的一个字符。文件末尾-1
        while (read != -1){
            System.out.print((char)read);
            read = fileReader.read();
        }

        //方式2
        int read;
        while ((read = fileReader.read()) != -1){
            System.out.println((char) read);
        }
        //TODO 4 流的关闭操作
        fileReader.close();

    }

3.1.2 对read()升级

//对read()升级,使用read的重载方法
    @Test
    public void testFileReader1() throws IOException {
        FileReader fr = null;
        try {
            //TODO 1 File类的实例化
            File file = new File("src/main/java/JavaSenior/d09/data/hello.txt");//相较于当前modle
            //TODO 2 FileReader流的实例化
            fr = new FileReader(file);
            //TODO 3 读入的操作
            //read(char[] cbub):返回每次读入到cbuf数组中的字符个数
            char[] cbuf = new char[5];
            int len;
            while((len = fr.read(cbuf)) !=-1 ){
                //错误写法
//                for(int i = 0; i < cbuf.length ; i++){
//                    System.out.println(cbuf[i]);
//                }
//                //正确写法:
//                for(int i = 0 ; i < len ; i++){
//                    System.out.println(cbuf[i]);
//                }

                //方式二:
                //错误
//                String s = new String(cbuf);
//                System.out.println(s);
                
                //正确
                String s = new String(cbuf,0,len);
                System.out.println(s);
                

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //TODO 4 资源的关闭
            fr.close();
        }

3.2 写数据

 @Test
    public void testWriter() throws IOException {
        //TODO 1 提供File类的对象,指明写出到的文件
        File file = new File("src/main/java/JavaSenior/d09/data/Writer2.txt");

        //TODO 2 提供一个FileWriter对象,用于写出
        FileWriter fileWriter = new FileWriter(file,true);//false会覆盖原文件

        //TODO 3 写出的操作
        fileWriter.write("I have a dream!\n");
        fileWriter.write("U have a dream!");

        //TODO 4 流资源的关闭
        fileWriter.close();

3.3 读入写出文件

 @Test
    public void testRW() throws IOException {
        //TODO 1 创建File类的对象,读入和写出文件
        File srcFile = new File("src/main/java/JavaSenior/d09/data/Writer2.txt");
        File destFile = new File("src/main/java/JavaSenior/d09/data/Writer3.txt");


        //TODO 2 创建输入流 和 输出流的对象
        FileReader fr = new FileReader(srcFile);
        FileWriter fw = new FileWriter(destFile);

        //TODO 3 数据读入和写出操作
        try {
            char[] cbuf = new char[5];
            int len;//记录每次读入到cbuf数组中的字符的个数
            while ((len = fr.read(cbuf)) != -1){
                fw.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //TODO 4 关闭资源
            fw.close();
            fr.close();
        }

3.4 图片的写入写出

 @Test
    public void photoRW() throws IOException {
        //todo 1 文件对象
        File srcFile = new File("src/main/java/JavaSenior/d09/data/LOL.PNG");
        File destFile = new File("src/main/java/JavaSenior/d09/data/PHOTO2.PNG");
        FileInputStream is = null;
        FileOutputStream os = null;

        try {
            //todo 2 创建字节流
            is = new FileInputStream(srcFile);
            os = new FileOutputStream(destFile);

            //todo 3 写入写出
            byte[] buf = new byte[1024];
            int len;
            while (-1 != (len = is.read(buf))){
                os.write(buf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //todo 4 关闭资源
            is.close();
            os.close();
        }

4 缓冲流

提高数据读取速度,Java提供了带换成功能的流,会创建一个内部缓冲区数组,缺省8192个字节(8kb)缓冲区

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

@Test
    public void BufferedStreamTest() throws IOException {
        //TODO 1 文件
        File srcFile = new File("src/main/java/JavaSenior/d09/data/hello.txt");
        File descFile = new File("src/main/java/JavaSenior/d09/data/hello22.txt");

        //TODO 2 节点流
        FileInputStream fileInputStream = new FileInputStream((srcFile));
        FileOutputStream fileOutputStream = new FileOutputStream((descFile));
        // todo 2.2 缓冲流
        BufferedInputStream bis = new BufferedInputStream(fileInputStream);
        BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);

        //TODO 3 复制的细节:读取、写入
        byte[] buffer = new byte[10];
        int len;
        while (-1 != (len = bis.read(buffer))){
            bos.write(buffer,0,len);
            bos.flush();//不满的话也写出去
        }

        //TODO 4 资源关闭
        bos.close();
        bis.close();
        //外层关闭之后,内层也会直接关闭
//        fileOutputStream.close();
//        fileInputStream.close();

5 转换流(装换流)

字节流 & 字符流之间的转换

  • InputStreamReader:将InputStream转换为Reader
  • OutputStreamWriter:将Writer转换为OutputStream

字节流中的数据都是字符时,转换成字符流更加高效
转换流尝试解决乱码问题,实现编码&解码功能

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

@Test
    public void test() throws IOException {
        File file = new File("src/main/java/JavaSenior/d09/data/hello.txt");
        FileInputStream fis = new FileInputStream(file);
        //参数2指明字符集,
        InputStreamReader isr = new InputStreamReader(fis,"UTF-8");//使用系统默认的字符集

        char[] chars = new char[1024];
        int len;
        while (-1 != (len = isr.read(chars))){
            String s = new String(chars, 0, len);
            System.out.println(s);
        }
        isr.close();

5.2 字符集

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

6 标准输入、输出流

在这里插入图片描述

7 打印流

在这里插入图片描述

PrintStream ps = null;
try {
FileOutputStream fos = new FileOutputStream(new File("D:\\IO\\text.txt"));
// 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
ps = new PrintStream(fos, true);
if (ps != null) {// 把标准输出流(控制台输出)改成文件
System.setOut(ps);
}
for (int i = 0; i <= 255; i++) { // 输出ASCII字符
System.out.print((char) i);
if (i % 50 == 0) { // 每50个数据一行
System.out.println(); // 换行
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (ps != null) {
ps.close();
}
}

8 数据流

在这里插入图片描述

9 对象流

在这里插入图片描述

9.1 序列化的理解

  • 对象序列化机制:把内存中的java对象----- 序列化 --> 二进制流 ,从而允许这种二进制流保存在磁盘上,或传输到另外网络节点 ,其他节点 ------反序列化-------> Java对象
  • 序列化可以将任何实现了Serializable接口的对象---------->字节数据,
  • 序列化是RMI(Remote Method Invoke) 过程参数&返回值都必须有的机制,序列化 --> RMI —> JavaEE
  • 对象可序列化 —> 对象的类 对象的属性 都可序列化 。 类序列化 —> Serializable Externalizable 接口

在这里插入图片描述

9.2 使用对象流序列化对象

在这里插入图片描述

 /*
    * 序列化过程:内存对象存储到磁盘
    * ObjectOutputStream使用
    * */
    @Test
    public void testObjectOutputStream() throws IOException {
        ObjectOutputStream oops = new ObjectOutputStream(new FileOutputStream("object.txt"));

        oops.writeObject(new String("hello world"));

        oops.flush();
        oops.close();
    }


    /*
    反序列化:从文件中的数据还原为内存中的对象
    * */
    @Test
    public void testObjectInputStream() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt"));

        Object o = ois.readObject();
        String str = (String) o;
        System.out.println(str);

        ois.close();

    }

9.3 对象可序列化

1 . 需要实现Serializable接口
2 . 需要当前类提供一个全局常量serialVersionUID

在这里插入图片描述

ObjectOutputStream和ObjectInputStream不能序列化static和transient修
饰的成员变量

10 随机存取文件流

在这里插入图片描述

在这里插入图片描述

/*
直接继承与Object ,实现了DataInput 、DataOutput接口
* 2.姐可以作为一个输入流,又可以作为一个输出流

  3. 如果Random文件已经存在,从头覆盖
* */
public class RandomAccessFileTest {

    @Test
    public void test1() throws IOException {
        RandomAccessFile randomAccessFile1 = new RandomAccessFile(new File("src/main/java/JavaSenior/d09/data/hello.txt"),"r");
        RandomAccessFile randomAccessFile2 = new RandomAccessFile(new File("src/main/java/JavaSenior/d09/data/helloR.txt"),"rw");

        byte[] bytes = new byte[1024];
        int len;
        while ((len = randomAccessFile1.read(bytes)) != -1 ){
            randomAccessFile2.write(bytes,0,len);
        }

        randomAccessFile1.close();
        randomAccessFile2.close();

    }

}

11 NIO2中Path、Paths File类的使用

11.1 NIO

New IO, Non-Blocking IO从Java1.4开始引入的一套新的IO API,可以替代标准版的Java IO API
NIO将以更加高效的方式进行文件的读写操作 ,NIO支持面向缓冲区,IO支持面向流的

在这里插入图片描述
 随着 JDK 7 的发布,Java对NIO进行了极大的扩展,增强了对
文件处理和文件系统特性的支持,以至于我们称他们为 NIO.2。
因为 NIO 提供的一些功能,NIO已经成为文件处理中越来越重要
的部分。

11.2 Path Paths Files 核心API

在这里插入图片描述

commons.io

在这里插入图片描述

public class FileUtilsTest {

    public static void main(String[] args) throws IOException {
        File file1 = new File("JavaSenior/src/main/java/JavaSenior/d09/data/hello.txt");
        File file2 = new File("JavaSenior/src/main/java/JavaSenior/d09/data/commonsIO.txt");
        FileUtils.copyFile(file1,file2);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oifengo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值