zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    BZOJ 1051: [HAOI2006]受欢迎的牛( tarjan )
    BZOJ 2208: [Jsoi2010]连通数( DFS )
    js效果-鼠标提示框
    CSS-背景
    CSS-文本
    tomcat 安装 for Mac
    CSS选择器基础
    POJ3349-Snowflake Snow Snowflakes-Hash
    数据库的三大设计范式
    HDU5120-Intersection-两个圆环相交面积
  • 原文地址:https://www.cnblogs.com/lingyejun/p/9744509.html
Copyright © 2011-2022 走看看