Java文件IO流的操作总结

简介: Java文件IO流的操作总结

Java中的IO操作涉及到的概念及相关类很多,很容易弄混,今天特来整理总结一下,并附上一份完整的文件操作的代码。

概念解析

读和写

流就是管道,向管道里面写数据用输出流:write

从管道里面读数据,用输入流:read

流的分类

流,按照不同的维度有不同的分类,按照从流中每次读取数据单位不同,划分为字节流字符流。

按照流-对应操作的角色的不同(是IO设备,还是其他流)是否能够直接向特定的IO设备如文件、网络、磁盘等,能够直接与这些进行读写的称之为节点流,

对节点流进一步封装的流,通过封装后的流来实现读写功能,处理流也被称为高级流。

注意事项

1、流和数组不一样,不能通过索引读写数据。在流中,你也不能像数组那样前后移动读取数据,除非使用RandomAccessFile 处理文件。

2、流仅仅只是一个连续的数据流。流中的数据只能够顺序访问。当达到流末尾时,返回-1。

3、InputStream的read()方法返回一个字节大小,返回值的范围在0到255之间。

4、Reader的read()方法返回一个字符,会根据文本的编码,一次读取一个或者多个字节,返回值的范围在0到65535之间。

5、read(byte[])会尝试读取与给定字节数组容量一样大的字节数,返回值int表示已经读取过的字节数。如果InputStream内可读的数据不足以填满字节数组,那么数组剩余的部分将包含本次读取之前的数据。记得检查有多少数据实际被写入到了字节数组中。

6、read(byte, int offset, int length)同样将数据读取到字节数组中,不同的是,该方法从数组的offset位置开始,并且最多将length个字节写入到数组中。同样地,read(byte, int offset, int length)方法返回一个int变量,表示有多少字节已经被写入到字节数组中,所以请记得在读取数据前检查上一次调用read(byte, int offset, int length)的返回值。

示例代码

package com.lingyejun.io;
import java.io.*;
/**
 * Created by Lingye on 2018/9/27 20:15
 */
public class FileStreamOperate {
    public static final String READ_UTF8_FILE_PATH = "D:\\input-utf8.txt";
    public static final String READ_UNICODE_FILE_PATH = "D:\\input-unicode.txt";
    public static final String WRITE_BYTES_FILE_PATH = "D:\\output-bytes.txt";
    public static final String WRITE_CHARS_FILE_PATH = "D:\\output-char.txt";
    /**
     * 按照字节流的方式读取文件内容
     *
     * Step 1.根据文件路径,构建文件对象
     * Step 2.创建输入流用来读取文件内容
     * Step 3.创建字节数组来存放读取内容
     * Step 4.关闭读取文件的输入流
     *
     * @return
     */
    public void readFileByFileInputStream() {
        System.out.println("=== readFileByFileInputStream Start ===");
        // 构建文件对象
        File inputFile = new File(READ_UTF8_FILE_PATH);
        // 初始化输入流
        InputStream inputStream = null;
        try {
            // 创建字节输入流
            inputStream = new FileInputStream(inputFile);
            // 读取到1KB字节数组中
            byte[] buffer = new byte[100];
            // 每次读取的字节数
            int readLength;
            // 读取数据并放到buffer数组中
            while ((readLength = inputStream.read(buffer)) != -1) {
                // UTF-8为变长编码,一个汉字占3个字节
                System.out.println("本次读取" + readLength + "个字节数据内容为:" + new String(buffer));
            }
        } catch (FileNotFoundException e) {
            // 文件未找到时异常处理
            e.printStackTrace();
        } catch (IOException e) {
            // 读取过程中,删除文件会出此异常
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    // 关闭流过程,也有可能出现异常
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("=== readFileByFileInputStream End ===");
    }
    /**
     * 按照字符流的方式读取文件内容
     *
     * Step 1.根据文件路径,构建文件对象
     * Step 2.创建字符输入流读取文件内容
     * Step 3.创建字符数组来存放读取内容
     * Step 4.关闭读取文件的字符输入流
     *
     * @return
     */
    public void readFileByFileReader(){
        System.out.println("=== readFileByFileReader Start ===");
        // 根据路径拿到文件对象
        File file = new File(READ_UTF8_FILE_PATH);
        // 初始化字符输入流
        Reader fileReader = null;
        // 初始化存放读取内容的字符数组
        char[] charArray = new char[100];
        // 初始化一个字符
        char once;
        try {
            fileReader = new FileReader(file);
            // 一次读取一个数组长度的字符串
            fileReader.read(charArray);
            System.out.println(charArray);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileReader != null) {
                try {
                    // 关闭流过程,也有可能出现异常
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("=== readFileByFileReader End ===");
    }
    /**
     * 通过字节流的方式写入信息到文件
     *
     * Step 1.根据文件路径,构建文件对象
     * Step 2.创建字节输出流写出信息到文件
     * Step 3.构造待写出的内容,并转为字节数组
     * Step 4.关闭读取文件的字符输出流
     */
    public void writeFileByFileOutputStream() {
        System.out.println("=== writeFileByFileOutputStream Start ===");
        // 创建写出文件
        File file = new File(WRITE_BYTES_FILE_PATH);
        // 初始化字节输出流
        OutputStream outputStream = null;
        // 写出内容
        String outInfo = "写出测试";
        // 转成字节数组
        byte[] byteArray = outInfo.getBytes();
        try {
            // 创建输出字节流
            outputStream = new FileOutputStream(file);
            outputStream.write(byteArray);
            System.out.println("按照字节流成功写出内容:"+outInfo);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    // 关闭写出流时,注意抓异常
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("=== writeFileByFileOutputStream End ===");
    }
    /**
     * 通过字符流的方式写入信息到文件
     *
     * Step 1.根据文件路径,构建文件对象
     * Step 2.创建字符输出流写出信息到文件
     * Step 3.构造待写出的内容,并转为字符数组
     * Step 4.关闭读取文件的字符输出流
     */
    public void writeFileByFileWriter(){
        System.out.println("=== writeFileByFileWriter Start ===");
        // 创建写出文件
        File file = new File(WRITE_CHARS_FILE_PATH);
        // 初始化字符输出流
        Writer fileWriter = null;
        String strInfo = "字符写出数据";
        try {
            // 创建输出字符流
            fileWriter = new FileWriter(file);
            // 写出内容
            fileWriter.write(strInfo);
            System.out.println("按照字符流成功写出内容:"+strInfo);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fileWriter != null){
                try {
                    // 关闭写出流时,注意抓异常
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("=== writeFileByFileWriter End ===");
    }
    /**
     * 任意读取文件内容
     */
    public void randomAccessFile(){
        System.out.println("=== randomAccessFile Start ===");
        File file = new File(READ_UTF8_FILE_PATH);
        try {
            RandomAccessFile randomAccessFile = new RandomAccessFile(file,"r");
            // 获取文件当前的指针位置
            System.out.println("file now pointer is "+randomAccessFile.getFilePointer());
            // 将文件指针设置到指定位置(绝对位置)
            randomAccessFile.seek(3);
            // 相对位置,相对于当前的位置,
            randomAccessFile.skipBytes(3);
            System.out.println("file now pointer is "+randomAccessFile.getFilePointer());
            // 字节数组
            byte[] buffer = new byte[17];
            // off是指的写到buffer的数组的起始位置
            randomAccessFile.read(buffer,0,buffer.length);
            System.out.println(new String(buffer));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("=== randomAccessFile End ===");
    }
    /**
     * 通过字节流的方式将文件内容拷贝到另一个文件中
     *
     * Step 1.根据文件路径,构建源文件对象
     * Step 2.根据文件路径,构造目的文件对象
     * Step 3.创建字节输入流从源文件中读取信息
     * Step 4.将读入到内存的信息再写出到目的文件中
     * Step 5.拷贝完成后关闭输入输出流
     */
    public void copyFile() {
        System.out.println("=== copyFile Start ===");
        // 输入文件对象
        File inFile = new File(READ_UTF8_FILE_PATH);
        // 输出文件对象
        File outFile = new File(WRITE_BYTES_FILE_PATH);
        // 初始化输入流
        InputStream inputStream = null;
        // 初始化输出流
        OutputStream outputStream = null;
        try {
            // 将输入流怼到输入文件,使程序内存与磁盘建立联系
            inputStream = new FileInputStream(inFile);
            // 将输出流怼到输出文件,使程序内存与磁盘建立联系
            outputStream = new FileOutputStream(outFile);
            while (true) {
                // 读取信息到内存
                int temp = inputStream.read();
                // 拷贝完成
                if (temp == -1) {
                    break;
                }
                // 将内容拷贝到输出文件中
                outputStream.write(temp);
            }
            System.out.println("拷贝文件成功完成");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    // 关闭输入流异常后,也要保证输出流关闭
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (outputStream != null) {
                        try {
                            outputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        System.out.println("=== copyFile End ===");
    }
    public static void main(String[] args) {
        FileStreamOperate fileStreamOperate = new FileStreamOperate();
        // 按照字节流读取的话,一个汉字两个字节
        fileStreamOperate.readFileByFileInputStream();
        // 按照字符读取,java Unicode编码一个字符(不论字母还是汉字)两个字节
        fileStreamOperate.readFileByFileReader();
        // 采用任意读取的方式读取文件信息
        fileStreamOperate.randomAccessFile();
        // 按照字节流的方式写信息到文件
        fileStreamOperate.writeFileByFileOutputStream();
        // 按照字符流的方式写信息到文件
        fileStreamOperate.writeFileByFileWriter();
        // 拷贝文件
        fileStreamOperate.copyFile();
    }
}  

输入输出文件和执行结果

文件展示

执行结果

小结

通过本篇,我们学会了文件IO的一些常规操作方式,但是每次读取完文件后都需要在最后进行关闭流资源的close操作,这个操作不可省略,但是每次都写又显得十分啰嗦,有没有更加简便的方式呢,请看我的下一篇文章《try with resources简洁的异常捕获机制》

 

参考文章:https://blog.csdn.net/yhl_jxy/article/details/79272792


目录
相关文章
|
12小时前
|
XML 前端开发 Oracle
16:JSP简介、注释与Scriptlet、Page指令元素、Include操作、内置对象、四种属性-Java Web
16:JSP简介、注释与Scriptlet、Page指令元素、Include操作、内置对象、四种属性-Java Web
8 2
|
1天前
|
C++ 数据格式
【C++】C++中的【文件IO流】使用指南 [手把手代码演示] & [小白秒懂]
【C++】C++中的【文件IO流】使用指南 [手把手代码演示] & [小白秒懂]
【C++】C++中的【文件IO流】使用指南 [手把手代码演示] & [小白秒懂]
|
1天前
|
存储 Java
java IO接口(Input)用法
【5月更文挑战第1天】Java的`java.io`包包含多种输入输出类。此示例展示了如何使用`FileInputStream`从`input.txt`读取数据。首先创建`FileInputStream`对象,接着创建一个字节数组存储读取的数据,调用`read()`方法将文件内容填充至数组。然后将字节数组转换为字符串并打印,最后关闭输入流。注意,`InputStream`是抽象类,此处使用其子类`FileInputStream`。其他子类如`ByteArrayInputStream`、`ObjectInputStream`和`BufferedInputStream`各有特定用途。
7 2
|
2天前
|
安全 Go
Golang深入浅出之-Go语言标准库中的文件读写:io/ioutil包
【4月更文挑战第27天】Go语言的`io/ioutil`包提供简单文件读写,适合小文件操作。本文聚焦`ReadFile`和`WriteFile`函数,讨论错误处理、文件权限、大文件处理和编码问题。避免错误的关键在于检查错误、设置合适权限、采用流式读写及处理编码。遵循这些最佳实践能提升代码稳定性。
6 0
|
2天前
|
存储 NoSQL 安全
java 中通过 Lettuce 来操作 Redis
java 中通过 Lettuce 来操作 Redis
java 中通过 Lettuce 来操作 Redis
|
2天前
|
分布式计算 DataWorks Java
DataWorks操作报错合集之在使用MaxCompute的Java SDK创建函数时,出现找不到文件资源的情况,是BUG吗
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
15 0
|
2天前
|
Java 测试技术 Python
《手把手教你》系列技巧篇(三十六)-java+ selenium自动化测试-单选和多选按钮操作-番外篇(详解教程)
【4月更文挑战第28天】本文简要介绍了自动化测试的实战应用,通过一个在线问卷调查(<https://www.sojump.com/m/2792226.aspx/>)为例,展示了如何遍历并点击问卷中的选项。测试思路包括找到单选和多选按钮的共性以定位元素,然后使用for循环进行点击操作。代码设计方面,提供了Java+Selenium的示例代码,通过WebDriver实现自动答题。运行代码后,可以看到控制台输出和浏览器的相应动作。文章最后做了简单的小结,强调了本次实践是对之前单选多选操作的巩固。
10 0
|
3天前
|
分布式计算 DataWorks 监控
DataWorks操作报错合集之DataWorks在调用java sdk的createFile功能时报错com.aliyuncs.exceptions.ClientException: 1201111000 如何解决
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
9 1
|
3天前
|
存储 Java Linux
【Java EE】 文件IO的使用以及流操作
【Java EE】 文件IO的使用以及流操作
|
3天前
|
存储 前端开发 测试技术
《手把手教你》系列技巧篇(三十五)-java+ selenium自动化测试-单选和多选按钮操作-下篇(详解教程)
【4月更文挑战第27天】本文介绍了使用Java+Selenium进行Web自动化测试时,如何遍历和操作多选按钮的方法。文章分为两个部分,首先是一个本地HTML页面的示例,展示了多选按钮的HTML代码和页面效果,并详细解释了遍历多选按钮的思路:找到所有多选按钮的共同点,通过定位这些元素并放入list容器中,然后使用for循环遍历并操作。 第二部分介绍了在JQueryUI网站上的实战,给出了被测网址,展示了代码设计,同样使用了findElements()方法获取所有多选按钮并存储到list中,然后遍历并进行点击操作。最后,文章对整个过程进行了小结,并推荐了作者的其他自动化测试教程资源。
11 0