Java IO流常用操作方法总结

一、简介

在实际工作中,基本上每个项目难免都会有文件相关的操作,比如文件上传、文件下载等,这些操作都是使用IO流进行操作的,本文将通过简单的示例对常用的一些IO流进行总结。

二、使用详解

【a】FileInputStream与FileOutputStream

首先通过查看jdk文档,了解下FileInputStream与FileOutputStream的操作方法:

FileInputStream:

FileOutputStream:

输入流主要是通过read读取文件,输出流主要是通过write写出到文件。

下面以文件拷贝的示例说明FileinputStream与FileOutputStream的使用方法:

public class CopyFileUtils {

    /**
     *
     * @param sourceFile
     * @param destFile
     * @throws IOException
     */
    public static void copyFile(File sourceFile, File destFile) throws IOException {
        //1. 源文件必须存在并且是文件
        if (!sourceFile.exists() || !sourceFile.isFile()) {
            System.out.println("源文件必须存在并且是文件");
            return;
        }

        if (destFile.isDirectory()) {
            return;
        }

        //2. 建立与文件的联系
        InputStream is = new FileInputStream(sourceFile);
        OutputStream os = new FileOutputStream(destFile);
        //实际接收长度
        int len = 0;
        //缓冲字节数组
        byte[] buffer = new byte[1024];
        //3. 循环读取文件
        while ((len = is.read(buffer)) != -1) {
            //4. 通过OutputStream写出到文件
            os.write(buffer, 0, len);
        }
        // 5. 关闭流
        os.flush();
        os.close();
        is.close();
    }

    public static void copyFile(String sourcePath, String destPath) throws IOException {
        //1. 源文件、目标文件建立联系
        File sourceFile = new File(sourcePath);
        File destFile = new File(destPath);
        copyFile(sourceFile, destFile);
    }

}

测试:

public class TestCopyFileUtils {

    public static void main(String[] args) {
        try {
            CopyFileUtils.copyFile("d:/aaa/a.txt", "d:/aaa/b.txt");
        } catch (IOException e) {
            System.out.println("文件拷贝失败!");
            e.printStackTrace();
        }
    }

}

运行结果:

下面以文件夹拷贝的示例来巩固FileinputStream与FileOutputStream的使用方法:

public class CopyDirUtils {

    public static void copyDir(String sourcePath, String destPath) throws IOException {
        //1. 建立与文件的联系
        File sourceFile = new File(sourcePath);
        File destFile = new File(destPath);
        //如果源文件是一个文件夹
        if (sourceFile.isDirectory()) {
            destFile = new File(destFile, sourceFile.getName());
        }
        copyDirDetail(sourceFile, destFile);
    }

    private static void copyDirDetail(File sourceFile, File destFile) throws IOException {
        //2. 如果源文件是一个文件,则直接拷贝即可
        if (sourceFile.isFile()) {
            //拷贝文件
            CopyFileUtils.copyFile(sourceFile, destFile);
        } else if (sourceFile.isDirectory()) {
            //3. 如果源文件是一个文件夹,那么需要确保目标文件夹存在
            destFile.mkdirs();
            //4. 使用listFiles递归调用copyDirDetail拷贝文件夹以及子文件
            for (File subFile : sourceFile.listFiles()) {
                copyDirDetail(subFile, new File(destFile, subFile.getName()));
            }
        }
    }

}

测试:

public class TestCopyDirUtils {

    public static void main(String[] args) throws IOException {
        String sourcePath = "d:/aaa";
        String destPath = "d:/bbb";
        CopyDirUtils.copyDir(sourcePath, destPath);
    }

}

运行结果:

 

【b】FileReader与FileWriter

FileReader与FileWriter并没有新增的方法,跟上面的用法基本类似,只是FileReader与FileWriter只能读取纯文本的文件。

下面分别讲解FileReader与FileWriter的基础用法:

/**
 * @Description: 纯文本读取
 * @Author: weishihuai
 * @Date: 2018/11/1 20:40
 */
public class FileReaderAndFileWriter {

    public static void main(String[] args) {
        //先写内容到文件
        writeFile();
        //再读取出来
        readFile();
    }

    /**
     * 把内容输出到文件
     */
    public static void writeFile() {
        //1. 需要写出的目标文件路径
        File file = new File("d:/aaa/b.txt");
        Writer writer = null;

        try {
            //2. 建立与目标文件的联系
            writer = new FileWriter(file);
            //3. 使用write()直接写出字符串(只能写出纯文本内容)
            writer.write("hello world!!!!!!!!!");
            //4. 刷新流
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //5. 关闭流
            if (null != writer) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 读取文件中的内容
     */
    public static void readFile() {
        //1. 定义源文件路径
        File file = new File("d:/aaa/b.txt");
        Reader reader = null;

        try {
            //2. 建立与源文件的联系
            reader = new FileReader(file);
            //3. 字符缓存数组
            char[] buffer = new char[1024];
            //4. 定义实际接收长度
            int len = 0;
            //5. 循环读取文件内容
            while (-1 != (len = reader.read(buffer))) {
                System.out.println(new String(buffer));
            }

        } catch (java.io.IOException e) {
            e.printStackTrace();
            System.out.println("源文件读取失败");
        } finally {
            //6. 关闭流
            if (null != reader) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("关闭流失败");
                }
            }
        }
    }

}

运行结果:

 

【c】BufferedInputStream与BufferedOutStream

BufferedInputStream与BufferedOutStream是字节处理流,起到增强功能, 提高性能的作用。(推荐使用)

BufferedInputStream与BufferedOutStream的使用方法并没有太大区别,只是在原来FileInputStream与FileOutputStream的外层包裹一个处理流BufferInputStream与BufferOutStream而已,使用方法如下:

/**
 * @Description: 字节处理流(增强功能, 提高性能, 处理流一定要在节点流之上)
 * @Author: weishihuai
 * @Date: 2018/11/1 20:56
 */
public class BufferInputStreamAndBufferOutStream {

    public static void main(String[] args) {
        //1.建立与源文件、目标文件的联系
        File sourceFile = new File("d:/aaa/a.txt");
        File destFile = new File("d:/aaa/aa.txt");

        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            //在外层包裹一层处理流,加强功能
            inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
            outputStream = new BufferedOutputStream(new FileOutputStream(destFile));
            //2. 定义缓冲字节数组以及实际接收长度len
            byte[] buffer = new byte[1024];
            int len = 0;
            //3. 循环读取文件中的内容
            while (-1 != (len = inputStream.read(buffer))) {
                //4.通过write将读取的内容写出到文件中
                outputStream.write(buffer, 0, len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //5. 关闭流
            if (null != outputStream) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

运行结果:

 

【d】BufferedReader与BufferedWriter

新增方法如下,其他方法都是从Reader或者Writer继承过来

BufferedReader:readLine() 读取一个文本行。

BufferedWriter:newLine() 写入一个行分隔符。

下面还是通过一个简单的示例讲解BufferedReader与BufferedWriter的使用方法:

public class BufferReaderAndBufferWriter {

    public static void main(String[] args) {
        //1. 建立与源文件、目标文件的联系
        File sourceFile = new File("d:/aaa/a.txt");
        File destFile = new File("d:/aaa/c.txt");

        BufferedReader reader = null;
        BufferedWriter writer = null;

        try {
            //2. 使用BufferedReader和BufferedWriter包裹FileReader和FileWriter
            //注意: 只能读取纯文本文件
            reader = new BufferedReader(new FileReader(sourceFile));
            writer = new BufferedWriter(new FileWriter(destFile));

            //3. 定义实际接收的字符串
            String str;

            //4. 使用reader.readLine()一行一行循环读取
            while (null != (str = reader.readLine())) {
                //5. 使用write()直接写出字符串到文件c.txt
                writer.write(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //6. 关闭流
            if (null != writer) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (null != reader) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

运行结果:

 

【e】InputStreamReader与OutputStreamWriter

转换流,主要用于解决文件读取或者写入出现的乱码问题。

出现乱码的问题一般有两种:

(1) 编码与解码的字符集不统一

(2) 字节数不够,长度丢失

下面我们通过示例讲解怎么解决乱码问题:

/**
 * @Description: 转换流(字节流 转换为 字符流)
 * @Author: weishihuai
 * @Date: 2018/11/1 21:22
 * <p>
 * 转换流: 主要用于解决乱码问题(保证源文件的编码集已知)
 */
public class InputStreamReaderAndOutputStreamWriter {

    public static void main(String[] args) throws IOException {
        //1. 指定解码字符集
        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("d:/aaa/c.txt")), "utf-8"));
        //2. 定义实际接收字符串
        String string;
        //3. 一行一行读取纯文本文件内容
        while (null != (string = reader.readLine())) {
            System.out.println(string);
        }
    }

}

如图,我们文件的编码为ANSI编码,我们指定的解码字符集为UTF-8,运行结果:

下面我们修改一下c.txt的编码字符集为UTF-8,再次运行程序,

如图,通过指定相同的编码与解码字符集,乱码问题就解决了。

【f】ByteArrayInputStream与ByteArrayOutputStream

ByteArrayInputStream与ByteArrayOutputStream是字节数组输入输出流,主要是将字节数组输出到文件中,再通过读取文件中的字节数组将内容读取出来。

/**
 * @Description: 字节数组流 字节流
 * @Author: weishihuai
 * @Date: 2018/11/2 20:43
 */
public class ByteArrayInputStreamAndByteArrayOutputStream {

    public static void read(byte[] bytes) {
        ByteArrayInputStream bis = null;
        //1. 实际接收长度
        int len = 0;
        //字节数组
        byte[] bytes1 = new byte[1024];
        try {
            //2. 创建字节数组输入流
            bis = new ByteArrayInputStream(bytes);
            //3. 循环将文件中的字节数组读取出来
            while (-1 != (len = bis.read(bytes1))) {
                System.out.println(new String(bytes1));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭流
            if (null != bis) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static byte[] write() {
        //字节数组
        byte[] dest;
        String string = "字节数组流 字节流 节点流";
        //需要写入文件的字节数组
        byte[] bytes = string.getBytes();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //使用write将字节数组写入到文件中
        bos.write(bytes, 0, bytes.length);
        //使用toByteArray()将输出流转化为字节数组
        dest = bos.toByteArray();
        return dest;
    }

    public static void main(String[] args) {
//        read();
        read(write());
    }

}

运行结果:

下面通过示例讲解字节数组流与文件流对接:

/**
 * @Description: 字节数组流与文件流对接
 * @Author: weishihuai
 * @Date: 2018/11/2 20:57
 */
public class ByteArrayToStream {

    public static void main(String[] args) {
        byte[] bytes = getBytesFromFile("d:aaa/a.txt");
        System.out.println(new String(bytes));
        toFileFromByteArray(bytes, "d:/aaa/t.txt");
    }

    /**
     * 从文件中读取到字节数组流中(文件输入流读取文件/字节数组输出流将文件写出到字节数组)
     *
     * @param sourcePath 源文件路径
     * @return
     */
    public static byte[] getBytesFromFile(String sourcePath) {
        File sourceFile = new File(sourcePath);
        byte[] dest;
        InputStream is = null;
        ByteArrayOutputStream bos = null;
        try {
            is = new BufferedInputStream(new FileInputStream(sourceFile));
            bos = new ByteArrayOutputStream();

            int len = 0;
            byte[] buffer = new byte[1024];
            while (-1 != (len = is.read(buffer))) {
                bos.write(buffer, 0, buffer.length);
            }
            bos.flush();
            dest = bos.toByteArray();
            return dest;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != bos) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 字节数组输出到文件(字节数组输入流将字节数组读取出来/文件输出流将字节数组写出到文件保存)
     *
     * @param bytes 字节数组
     */
    public static void toFileFromByteArray(byte[] bytes, String destPath) {
        OutputStream os = null;
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        int len = 0;
        byte[] buffer = new byte[1024];
        try {
            os = new FileOutputStream(new File(destPath));
            while (-1 != (len = bis.read(buffer))) {
                os.write(buffer, 0, len);
            }
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != bis) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

}

运行结果:

三、总结

以上是工作中常用的IO流操作文件的方法,具体可以根据实际情况进行调整,本文是笔者在复习IO操作方法的一些总结,仅供大家学习参考,大家可以进行进一步优化,一起学习一起进步。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,作为文本AI助手,我无法绘制思维导图。但是,我可以为您提供一个简要的java IO流知识点总结Java IO流Java中用于处理输入和输出的机制。它提供了一种有效的方式来读取和写入数据,以及与文件、网络和其他设备进行交互。 Java IO流包括字节流和字符流两种类型。字节流以字节为单位进行操作,适用于处理二进制数据。而字符流以字符为单位进行操作,适用于处理文本数据。 常用的字节流包括InputStreamOutputStream类,用于读取和写入字节数据。常用的字符流包括Reader和Writer类,用于读取和写入字符数据。可以通过使用字节流和字符流的组合来实现不同类型数据的读写操作。 在Java IO流中,还有一些特殊的流,如缓冲流、转换流、对象流等。缓冲流提供了缓冲区来提高IO性能。转换流用于处理字符编码和解码。对象流用于对Java对象进行读写操作。 此外,Java IO流还包括一些常用的类和方法,如File类用于处理文件和目录,RandomAccessFile类用于对文件进行随机访问,FileInputStreamFileOutputStream类用于读写文件等。 通过组合和使用不同类型的流和类,您可以实现各种复杂的IO操作,如读写文件、网络通信、序列化对象等。 希望这个简要总结对您有所帮助。如果您有任何更具体的问题,请随时提问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [万字长文+思维导图帮你梳理 Java IO 流,还学不会你来打我(值得收藏)](https://blog.csdn.net/a1405/article/details/116766237)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值