Blocking IO / Non-blocking IO 操作文件

BufferedReader(字符读入处理流)读取文件中的内容

BufferReader适合需要对文件中的内容进行处理的情况

private StringBuilder getFileContent(MultipartFile oneFile) {//MultipartFile是spring文件上传的工具类
        StringBuilder fileContent = new StringBuilder("");
        //try-with-resource,将自动关闭resource(前提是其中的类实现AutoCloseable接口)
        try (InputStream is = oneFile.getInputStream()
             ; InputStreamReader isr = new InputStreamReader(is, "gb2312")//gb2312是win下txt编码模式
             ; BufferedReader br = new BufferedReader(isr)
        ) {
            String temp = null;     //用于接收每读一行的内容
            while ((temp = br.readLine()) != null) {    //null判断文件读取是否结束,不能用temp的长度判断
                fileContent.append(temp);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileContent;
    }

try-with-resource相关语法可参考


当只需要对文件进行输入输出时,可以使用字节节点流(如FileInputStream、FileOutputStream)

private void writeFile(MultipartFile multipartFile, String path) throws IOException {
        // 如果没有文件上传,MultipartFile也不会为null,可以通过调用getSize()方法获取文件的大小来判断是否有上传文件
        if (multipartFile.getSize() <= 0) {
            return;
        }
        File file = new File(path);
        if (!file.exists()) {
            file.mkdir();
            System.out.println(file.getPath() + "不存在,现已被创建");
        }
        file = new File(path, multipartFile.getOriginalFilename());
        //下面两行语句都可以完成文件的写入,且都是使用的字节节点流
//        multipartFile.transferTo(file);
//org.apache.commons.io.IOUtils,其方法体的主要内容参考下面的copyLarge
        IOUtils.copy(multipartFile.getInputStream(),new FileOutputStream(file));
    }
//copy方法的主要内容。buffer为读入缓存数组的大小
public static long copyLarge(final InputStream input, final OutputStream output, final byte[] buffer)
            throws IOException {
        long count = 0;
        int n;
        while (EOF != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
            count += n;
        }
        return count;
    }


使用 NIO 的 FileChannel 来读写文件(建议大文件场景下使用)

/**
     * 通过Nio方式去读取内容
     * <p>
     * 1.通过FileInputStream创建通道
     * 2.创建ByteBuffer缓冲区
     * 3.将数据读取到缓冲区
     *
     * @param txtPath
     */
    private static StringBuilder readContextByNio(String txtPath) throws IOException {
        StringBuilder context = new StringBuilder("");
        //1
        try (FileInputStream fis = new FileInputStream(txtPath)
             ; FileChannel channel = fis.getChannel()
        ) {
            //2
            int byteCapacity = 128;
            ByteBuffer bf = ByteBuffer.allocate(byteCapacity);
            //缓冲区重要变量大小关系:
            //mark(缓冲区中执行reset操作时,position应该置于的位置) <= position(可读写数据的起始位置) <= limit(不可读写的起始位置) <= capacity(缓冲区最大数据容量)
            System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity() + "位置是:" + bf.position());
            //3
            int length = -1;
            while ((length = channel.read(bf)) != -1) {
                /*
                 * 注意,读取后,将位置置为0,将limit置为容量, 以备下次读入到字节缓冲中,从0开始存储
                 */
                bf.clear();
                byte[] bytes = bf.array();
                String s = new String(bytes, 0, length, "gbk");//在文件读取时是按字节读取的,所以此处设置编码不会乱码
                context.append(s);

                System.out.println("限制是:" + bf.limit() + "容量是:" + bf.capacity() + "位置是:" + bf.position());

            }
        }
        return context;
    }
    
	 /**
     * 使用NIO方式完成数据的读取与写入
     * @param txtPath
     */
    private static String RWContextByNio(String txtPath) throws IOException {
        try ( //读入
              FileInputStream fis = new FileInputStream(txtPath)
              ; FileChannel inChannel = fis.getChannel()
              //写出
              ; FileOutputStream fos = new FileOutputStream(new File(txtPath).getParent() + "/out.txt")
              ; FileChannel outChannel = fos.getChannel()
        ) {
            ByteBuffer bf = ByteBuffer.allocate(128);

            int length = -1;
            while ((length = inChannel.read(bf)) != -1) {
                bf.flip();
                int outlength = 0;
                while ((outlength = outChannel.write(bf)) != 0) {
                    System.out.println("读," + length + "写," + outlength);
                }
                //清空缓冲区,使得整个缓冲区均可用
                bf.clear();
            }
        }
        return "success";
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值