File和流一

1、File概述

在java的世界中,万事万物皆对象;在Linux中,万物皆文件。而程序的运行就是在Linux服务器中来进行运行的。

对于文件来说,java利用File来进行封装,File代表的是对文件和文件夹的抽象表示。

也就是说用一个File来表示文件和文件夹,在当前的操作系统中对于一个File来说,代表的可能不是一个真实的文件,仅仅只是一个路径名,在而磁盘上,可能是存在的,也可能是不存在的。所以file也就面临着为空的情况。

下面附上一个总结图:

对于文件来说,文件的内容不能够使用File来进行读取,而是通过流的方式来进行读取。File对象可以用来表示流的来源地和目的地。

File类中只是提供了一些创建、查找、删除文件,但是却无法对文件的内容来进行操作。所以只能够通过流的操作方式来进行操作。

所以使用流主要是用来实现对内容的读取、传输和写入数据的。又称为IO操作

3、IO分类

1. 字节流

1. 概述

IO : I : IN;O : OUT

计算机中存储数据:最小的存储单元是字节

输入和输出 : 站在内存的角度思考

  • IO流的分类
输入 输出
字节 字节输入流(InputStream) 字节输出流
字符 字符输入流 字符输出流

2. 字节输入流

  • FileInputStream : 从文件中读取字节

(1 ) 构造方法

// 创建字节输入流对象, 关联到文件(路径)上
public FileInputStream(File file)
public FileInputStream(String name)

注意 : 关联的文件如果不存在会报错, 如果关联的是文件夹也会报错

(2) 成员方法

public int read() : 读取一个字节, 返回: 读取到的字节
    				如果读取到文件末尾, 会返回-1
    
public int read(byte[] b)
    			: 读取字节数组, 将读取到的字节存入数组中, 
				返回: 读取到有效的字节个数
                     如果读到文件的末尾, 会返回-1
    
                    
// 了解即可
public int read(byte[] b, // 字节数组
                int offset,  // 起始偏移量(索引)
                int len)   // 长度
                    
                : 读取字节数组, 将字节读取到数组中, 从offset开始的 len  个

    
public void close() : 关流

3. 字节输出流

  • FileOutputStream : 输出字节到文件上

(1)构造方法

// 创建字节输出流对象, 关联文件
public FileOutputStream(File file)
public FileOutputStream(String name)
    
// 以上两种构造方法, 创建输出流对象, 关联文件中的内容会被清空.
// 输出流关联的文件如果不存在, 会创建出来

(2) 成员方法

public void write(int b) : 写出一个字节
    
public void write(byte[] b) : 写出字节数组(将字节数组中的内容写到文件上)

public void write(byte[] b, // 字节数组
                  int off,  // 索引
                  int len)  // 长度
    : 写出字节数组中, 从off索引开始的 len 个字节

4. 一个字节的拷贝

package com.guang._06copy;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
    字节流一个字节一个字节的拷贝

 */
public class Demo01 {
    public static void main(String[] args) throws IOException {
        // 1. 创建输入流对象
        FileInputStream fis = new FileInputStream("day12-code\\def.mp4");
        // 2. 创建输出流对象
        FileOutputStream fos = new FileOutputStream("day12-code\\copyDef.mp4");

        // 3. 使用输入流读取
        int b; // 代表每一次读取到的字节
        while ((b = fis.read()) != -1) {
            // 4. 使用输出流写出
            fos.write(b);
        }

        // 5. 关闭输出流
        fos.close();
        // 6. 关闭输入流
        fis.close();



    }
}

5. 字节数组的拷贝

package com.guang._06copy;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*

    read(byte[] arr) :  将文件中的字节, 读取到字节数组中,
                        返回的是读取到有效的字节个数
                        读取到文件末尾, 返回-1


    write(byte[] arr, int offset, int len) :
                        将arr数组中 从offset索引开始的 len个字节, 写出到文件中


 */
public class Demo02 {
    public static void main(String[] args) throws IOException {

        // 1. 创建输入流对象
        FileInputStream fis = new FileInputStream("day12-code\\def.mp4");
        // 2. 创建输出流对象
        FileOutputStream fos = new FileOutputStream("day12-code\\copyDef.mp4");

        // 3. 使用输入流读取
        // 创建字节数组
        byte[] arr = new byte[1024 * 8];


        // 创建变量, 用来记录读取到有效的字节个数
        int len;
        while ((len = fis.read(arr)) != -1) {
            // 4. 使用输出流写出
            fos.write(arr, 0, len);
        }

        // 5. 关闭输出流
        fos.close();
        // 6. 关闭输入流
        fis.close();

    }
}

四. 字符流

1. 概述

当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。

2. 字符输入流

  • FileReader

(1) 构造方法

FileReader(String pathname)
FileReader(File file)

(2) 成员方法

public int read()
public int read(char[] cbuf)
public abstract int read(char[] cbuf,
                         int off,
                         int len)

3. 字符输出流

  • FileWriter

(1) 构造方法

public FileWriter(File file)
public FileWriter(String fileName)

(2) 成员方法

public void write(int c)	: 写出一个字符
public void write(char[] cbuf) : 写出字符数组
public void write(char[] cbuf, : 写出字符数组中从off索引开始的len个字符
                  int off,
                  int len)
    
public void write(String str) : 可以直接写出字符串

字符流的使用场景:

  1. 仅读取中文字符
  2. 仅写出中文字符

所有格式文件的拷贝, 都使用字节流.

4. 字符流拷贝

字符流只能拷贝纯文本的文件(我们能看得懂的)

5. 其他知识点

(1) 关闭和刷新

FileOutputStream : 内部没有任何缓冲区(数组)

FileWriter : 内部有一个长度为1024的字符数组 --- 缓冲区

  			写出的内容会先被写到缓冲区中, 然后再刷出到文件上

缓冲区中的内容, 刷出到文件上有两种情况:

  1. 缓冲区满了, 会自动刷 2. 手动刷(close, flush)
  • close() : 关流, 但是在关流之前, 会刷出一次缓冲区.
  • flush() : 刷出一次缓冲区.

flush本意是冲刷,这个方法大概取自它引申义冲马桶的意思,马桶有个池子,你往里面扔东西,会暂时保存在池子里,只有你放水冲下去,东西才会进入下水道。

同理很多流都有一个这样的池子,专业术语叫缓冲区,当你print或者write的时候,会暂时保存在缓冲区,并没有发送出去,这是出于效率考虑的,因为数据不会自己发送过去,必须有其他机制,而且这个很消耗资源,就像马桶你需要很多水,才能冲走,你如果扔一点东西,就冲一次水,那你水费要爆表了,同样如果你写一行文字,或者一个字节,就要马上发送出去,那网络流量,CPU使用率等等都要爆表了,所以一般只有在你真正需要发送否则无法继续的时候,调用flush,将数据发送出去。

什么时候使用呢?其实看接口,都可以来进行使用。所以推荐使用完成之后flush一下即可。

(2) 换行和续写

  • 换行符

    • "\r\n" 换行符
    • "\t" 制表符
  • 续写

    public FileOutputStream(String name, boolean append) : append: 是否续写
    public FileWriter(String fileName, boolean append)
    
posted @ 2021-09-23 19:06  雩娄的木子  阅读(173)  评论(0编辑  收藏  举报