返回顶部
首页 > 资讯 > 后端开发 > Python >一文探索Java文件读写更高效方式
  • 221
分享到

一文探索Java文件读写更高效方式

2024-04-02 19:04:59 221人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

目录背景场景分析场景1:小文件单文件压缩方式1:网上流传(流传在坊间的神话,其实是带刺的玫瑰)方式2:使用缓冲区方式3:使用通道方式4:使用mmp场景2:大文件单文件压缩场景3:大文

背景

最近在探秘kafka为什么如此快?其背后的秘诀又是什么?

怀着好奇之心,开始像剥洋葱 一样逐层内嵌。一步步揭晓kafka能够吊打MQ的真因。了解之后不得不说kafka:yyds。

了解到顺序存盘的运用

探测到稀疏索引的引进

知晓其零拷贝技术的威力

嗅觉到mmp(内存映射文件)的神来之笔

......

mmp如此神奇,那么运用于文件压缩,是否同样可以实现飞速压缩呢?

又怀着好奇之心,决定用实际行动证明这个结论(否则我们的知识只能纸上谈兵)

编码是我们的本能功能,好奇之心是我们永远的利器。不能丢

曾几何时,有位BA告诉我他的经历:DEV转为BA后,代码就生疏了,后来他强迫自己每个迭代都领一个小需求鞭策自己。

曾几何时,有位前辈告诉我:即使你以后成长为架构师甚至更高职位,也不能丢失编码这件神器。否则你会发现会很尴尬——会被人称为“需求翻译机”

......

这不是心灵鸡汤,这是来自灵魂的谏言,我深刻了解到:编码真的是学到老活到老的工作。

看到很多优秀的同事离职远去,通过交流感触更加深厚

所以,大家一定记得:学会一个知识要努力应用一遍。这样才能记得牢固;在学习中要不求甚解,完全知道这个知识也要知道为什么这么做

......

场景分析

场景1:小文件单文件压缩

  • 1、原始文件介绍:63.7M、 csv文件 、单个文件
  • 2、对比技术介绍:网上流传、使用缓冲区、使用管道、使用mmp
  • 3、对比结果展示:

方式1:网上流传(流传在坊间的神话,其实是带刺的玫瑰)

小王刚入职不久,有一天突然接到需求,要压缩文件,之前没写过,怎么办?这个时候会在网上搜到这个方法

执行结果(效率很吓人)

zipMethod=withoutBuffer

costTime=327000ms

代码如下:

public void zipFileWithoutBuffer(String outFile){
    long beginTime = System.currentTimeMillis();
    File zipFile = new File(outFile);
    File inputFile = new File(INPUT_FILE);
    try(ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFile))) {
        try (InputStream inputStream = new FileInputStream(inputFile)){
            zipOutputStream.putNextEntry(new ZipEntry(inputFile.getName()));
            int temp;
            while ((temp = inputStream.read()) != -1){
                zipOutputStream.write(temp);
            }
        }
        printResult(beginTime,"withoutBuffer");
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("error" + e.getMessage());
    } 
}

方式2:使用缓冲区

小王很开心,提交代码,翻转了需求状态,可验收。

小花是团队资深技术达人,走查代码发现一脸懵逼:网上搜的?这个会很慢,你再研究研究

小王又换了一种思路,借助缓冲区BufferedOutputStream

执行结果(快了很多)

zipMethod=withBuffer

costTime=5170ms

代码如下:

public void zipFileWithBuffer(String outFile){
    long beginTime = System.currentTimeMillis();
    File zipFile = new File(outFile);
    File inputFile = new File(INPUT_FILE);
    try(ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFile));
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(zipOutputStream)) {
        try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(inputFile))){
            zipOutputStream.putNextEntry(new ZipEntry(inputFile.getName()));
            int temp;
            while ((temp = bufferedInputStream.read()) != -1){
                bufferedOutputStream.write(temp);
            }
        }
        printResult(beginTime,"withBuffer");
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("error" + e.getMessage());
    } 
}

方式3:使用通道

小王怀着忐忑的心情,又一次召集大家走查代码。

小花:速度要求没那么高,这样做已经差不多了,代码可以提交了

其实最近研究kafka,接触过NIO,知晓:nio有种技术叫通道:Channel

执行结果(好快)

zipMethod=withChannel

costTime=1642ms

代码如下:

public void zipFileWithChannel(String outFile){
    long beginTime = System.currentTimeMillis();
    File zipFile = new File(outFile);
    File inputFile = new File(INPUT_FILE);
    try(ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFile));
        WritableByteChannel writableByteChannel = Channels.newChannel(zipOutputStream)) {
        try (FileChannel fileChannel = new FileInputStream(inputFile).getChannel()){
            zipOutputStream.putNextEntry(new ZipEntry(inputFile.getName()));
            fileChannel.transferTo(0,inputFile.length(),writableByteChannel);
        }
        printResult(beginTime,"withChannel");
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("error" + e.getMessage());
    } 
}

方式4:使用mmp

研究kafka过程中,不止知晓nio有种技术叫通道:Channel,还有种技术叫mmp

执行结果(好快)

zipMethod=withMmp

costTime=1554ms

代码如下:

public void zipFileWithMmp(String outFile){
    long beginTime = System.currentTimeMillis();
    File zipFile = new File(outFile);
    File inputFile = new File(INPUT_FILE);
    try(ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFile));
        WritableByteChannel writableByteChannel = Channels.newChannel(zipOutputStream)) {
        zipOutputStream.putNextEntry(new ZipEntry(inputFile.getName()));
        MappedByteBuffer mappedByteBuffer = new RandoMaccessFile(INPUT_FILE,"r").getChannel()
                .map(FileChannel.MapMode.READ_ONLY,0,inputFile.length());
        writableByteChannel.write(mappedByteBuffer);
        printResult(beginTime,"withMmp");
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("error" + e.getMessage());
    } 
}

场景2:大文件单文件压缩

  • 1、原始文件介绍:585M、 csv文件 、单个文件
  • 2、对比技术介绍:使用缓冲区、使用管道、使用mmp
  • 3、对比结果展示:
使用缓冲区使用通道使用mmp
costTime=46034mscostTime=11885mscostTime=10810ms

场景3:大文件多文件压缩

  • 1、原始文件介绍:585M、 csv文件 、5个文件
  • 2、对比技术介绍:使用缓冲区、使用管道、使用mmp
  • 3、对比结果展示:
使用缓冲区使用通道使用mmp
costTime=173122mscostTime=53982mscostTime=50543ms

分析结论

1、对比见下表

压缩场景网上流传使用缓冲区使用通道使用mmp
场景1:小文件单文件压缩(60M)327000ms5170ms1642ms1554ms
场景2:大文件单文件压缩(585M)--46034ms11885ms10810ms
场景3:大文件多文件压缩(5个585M)--173122ms53982ms50543ms
场景4:100K文件单文件压缩--28ms26ms24ms
场景5:5K文件单文件压缩 18ms20ms23ms
场景5:1K文件单文件压缩 15ms21ms24ms

结论:

  • 1)网上流传的方法不可取,效率最差
  • 2)使用缓冲区虽然性能还凑合,但和两种nio技术(通道和mmp)相比,还是差了很多,尤其是在中型文件(500M左右)的单文件压缩和多文件压缩
  • 中,对比更加明显
  • 3)通道技术和mmp技术对比相差不大,小型文件基本没影响,大型文件差距也在几秒之间
  • 4)文件大于10K时,推荐使用通道技术或者mmp技术进行文件压缩
  • 5)文件小于10K时,推荐使用缓冲区技术(比两种nio技术表现了更好的性能)
  • 6)如果有些团队在使用api,可以看看其源码是否使用了nio技术。如果不是,建议修改为文中方式

另外,操作文件操作时,都可以尝试使用nio技术,测试下其效率,理论上应该都是很可观的

背后机密

1、网上流传方法

FileInputStream的read方法如下:

public int read() throws IOException {
    return read0();}private native int read0() throws IOException;

这是调用本地方法与原生操作系统进行交互,从磁盘中读取数据。每读取一个字节数据就调用一次这个方法(一次交互很耗时)。

这个方法还是每次读取一个字节,假如文件很大,这个开销是巨大的

2、使用缓冲区

BufferedInputSream read方法如下:

public synchronized int read() throws IOException {
    if (pos >= count) {
        fill();
        if (pos >= count)
            return -1;
    }
    return getBufIfOpen()[pos++] & 0xff;}

这样虽然也是一次读一个字节,但不是每次都从底层读取数据,而是一次调用底层系统读取了最多buf.length个字节到buf数组中,然后从 buf中一次读一个字节,减少了频繁调用底层接口的开销。

3、使用通道

在复制大文件时,FileChannel复制文件的速度比BufferedInputStream/BufferedOutputStream复制文件的速度快了近三分之一,体现出FileChannel的速度优势。NIO的Channel的结构更加符合操作系统执行I/O的方式,所以其速度相比较于传统的IO而言速度有了显著的提高。

操作系统能够直接传输字节从文件系统缓存到目标的Channel中,而不需要实际的copy阶段(copy: 从内核空间转到用户空间的一个过程)

4、使用mmp

内存映射文件,是把位于硬盘中的文件看做是程序地址空间中一块区域对应的物理存储器,文件的数据就是这块区域内存中对应的数据,读写文件中的数据,直接对这块区域的地址操作,就可以,减少了内存复制的环节。所以说,内存映射文件比起文件I/O操作,效率要高,而且文件越大,体现出来的差距越大。

到此这篇关于一文探索Java文件读写更高效方式的文章就介绍到这了,更多相关 Java文件读写内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 一文探索Java文件读写更高效方式

本文链接: https://lsjlt.com/news/153770.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 一文探索Java文件读写更高效方式
    目录背景场景分析场景1:小文件单文件压缩方式1:网上流传(流传在坊间的神话,其实是带刺的玫瑰)方式2:使用缓冲区方式3:使用通道方式4:使用mmp场景2:大文件单文件压缩场景3:大文...
    99+
    2024-04-02
  • Python使用os模块实现更高效地读写文件
    目录使用 os.open 打开文件使用 os.read 读取文件使用 os.write 写入文件使用 os.open 打开文件 无论是读文件还是写文件,都要先打开...
    99+
    2024-04-02
  • 如何用 Java 实现高效的文件读写操作
    1. 使用缓冲流 缓冲流是一种可以将数据临时存储在缓冲区中的流。当需要读写数据时,它会先将数据读入或写入缓冲区,然后再从缓冲区读出或写入文件。这样可以减少对文件的读写次数,从而提高文件读写效率。 import java.io.*; p...
    99+
    2024-02-26
    Java 文件读写 性能优化
  • java利用缓冲区及流式对大文件进行高效读写
    当处理大文件时,使用适当的技术和方法可以提高读写性能和效率。下面是一些针对大文件读写的示例说明: 字符流缓冲区及分块读写  BufferedInputStream 和 BufferedOutputStream 大文件读取: try (F...
    99+
    2023-09-14
    java 数学建模 开发语言
  • Nodejsexcel(.xlsx)文件的读写方式
    目录Nodejs excel(.xlsx) 文件读写获取数据获取第一个 execle 工作簿表格1. 输出 json 格式2. 输出 csv 格式3. 输出 html 格式4.输出 ...
    99+
    2024-04-02
  • Java如何高效的读取一个超大文件
    这篇文章主要介绍“Java如何高效的读取一个超大文件”,在日常操作中,相信很多人在Java如何高效的读取一个超大文件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java如何...
    99+
    2024-04-02
  • 怎么用Java高效读取大文件
    这篇文章主要讲解了“怎么用Java高效读取大文件”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用Java高效读取大文件”吧!内存读取第一个版本,阿粉采用...
    99+
    2024-04-02
  • Java 中怎么提高文件读写速度
    这篇文章给大家介绍Java 中怎么提高文件读写速度,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java NIO的出现旨在提高文件的读写速度,当然IO用NIO重新实过,所以我们不用显示的调用NIO也能享受这种高效的文件...
    99+
    2023-06-17
  • Python文件读写及常用文件的打开方式
    目录编码格式文件的读写原理常用的文件打开模式文件的类型编码格式 常见的编码格式: Python的解释器使用的是Unicode(内存).py文件在磁盘上使用UTF-8(外存) 更改编...
    99+
    2024-04-02
  • Java高效读取大文件实例分析
    1、概述本教程将演示如何用Java高效地读取大文件。Java——回归基础。2、在内存中读取读取文件行的标准方式是在内存中读取,Guava和ApacheCommonsIO都提供了如下所示快速读取文件行的方法:Files.readLines(n...
    99+
    2023-05-30
  • java怎么读取文件内容并写入到另一文件
    在Java中,可以使用`FileReader`和`BufferedReader`来读取文件内容,并使用`FileWriter`和`B...
    99+
    2023-09-20
    Java
  • 异步的魅力:探索 Node.js 中文件读取的非阻塞方式
    ...
    99+
    2024-04-02
  • java 读取文件的几种方式
    在 Java 中有几种常用的方式来读取文件: 使用 FileInputStream 类以字节的方式读取文件。 使用 BufferedReader 在字符输入流上包装一个缓冲区,以行为单位读取文件。 使用 Scanner 类以分隔符为标志...
    99+
    2023-09-02
    java servlet 开发语言
  • Java读取文件的几种方式
    1. 使用流读取文件 public static void stream() { String fileName = "D:\\test.txt"; final String CHARSET_NAME = "UTF-8"; ...
    99+
    2023-09-09
    java 开发语言 servlet 前端
  • java中读文件的方式介绍
    本篇内容介绍了“java中读文件的方式介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 一、多种方式读文件内容。1、按字节读取文件内容2、...
    99+
    2023-06-03
  • Python中的文件读写方式有哪些?
    Python中的文件读写方式有多种,可以根据实际需要选择不同的方式。下面将介绍几种常用的文件读写方式,并给出代码示例。使用open()函数open()函数是Python提供的用于打开文件的内置函数。它可以接受文件名和打开模式作为参数,并返回...
    99+
    2023-10-22
    文件
  • Golang文件读取技巧:让你的程序更高效
    Golang是一门强大的编程语言,有着高效、简单、跨平台等优点。在Golang中,如何高效地读取文件是一个很重要的问题。本文将介绍一些Golang文件读取技巧,并提供具体的代码示例,希望能够帮助读者提高代码效...
    99+
    2024-01-19
    Golang 文件读取 高效程序
  • java读写html文件乱码解决方法
    JAVA读取文件,避免中文乱码。 public static String readFile(String filePathAndName) { String fileContent = ""; try { File f =...
    99+
    2015-05-06
    java 乱码
  • java— 读取JSON文件的多种方式
    大部分内容参考自: https://blog.csdn.net/csdn_halon/article/details/120287992 在开发过程中有时会遇到需要读取本地.json文件的需求,通常会自己写Reader代码去读,但是...
    99+
    2023-09-01
    java json Powered by 金山文档
  • java 读取json文件的2种方式
    1 背景介绍 研发过程中,经常会涉及到读取配置文件等重复步骤,也行是.conf文件,也许是.json文件,但不管如何他们最终都需要进入到jave的inputStream里面。下面以读取.json文件为例 2 FileInputStream读...
    99+
    2023-08-18
    java json linux
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作