首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

读取超级大的单个文件,用这个方法一招搞定,你一定用的着

结论:大文本文件,远超内存,需要格外注意。

前言

生产服务器中经常产生很多文件,有些积年累月单个文件,体积越来越大。

本文使用多种编程语言,实现大文件的读取。

PHP的处理方式

大文件如果直接open,就会被整个写入内存,内存是吃不消的。比如4G的内存,10G的文件,这是处理不了的。也没有哪个文本编辑器可以用。

常用的file_get_contents函数,是将文件内容读入到字符串变量内。而字符串变量分配在内存,所以没有任何办法处理大文件。

一般的做法是使用fgets函数。该函数从文件内读取一行。函数格式如下:

string fgets ( resource [, int ] )

其中参数 $handle 是文件指针,从 $handle 指向的文件中读取一行并返回长度最多为 $length - 1 字节的字符串。

碰到换行符(包括在返回值中)、EOF 或者已经读取了 $length - 1 字节后停止(看先碰到那一种情况)。如果没有指定 $length,则默认为 1K,或者说 1024 字节。

实际用起来像下面这样。

此函数效率极高,一次最多读一行。而碰到整个文件都是一行的情况,则按照设定的 $length 按照长度依次读取。

Python的方式

从上述PHP的处理方法可以看到,关键点是按行读取,再按长度读取。python的处理方法一样,只是掺杂了一些语法糖。

python有一个“生成器”,解决大文件的读取,就靠这个玩意儿。

在python的函数(function)定义中,只要出现了yield表达式(Yield expression),那么事实上定义的是一个generator function, 调用这个generator function返回值是一个generator。

为什么genetor效率高呢,因为其与普通函数的有区别:

function每次都是从第一行开始运行,而generator从上一次yield开始的地方运行。

function调用一次返回一个(一组)值,而generator可以多次返回。

function可以被无数次重复调用,而一个generator实例在yield最后一个值或者return之后就不能继续调用了。

下面是使用带有yield关键字的读取大文件方法。

其实python还有更优雅便捷的写法,就是for循环读取。像下面这样:

或者不用重新定义函数,直接用for循环遍历。

底层使用的原理是一样的。

Golang的方式

Golang的想法也一样,它绝不把整个文件写入内存。bufio库就是读写文件的利器。

不多解释,直接上示例。

Golang为了统一场景,无论普遍的和特殊的,都考虑在内了。这就是bufio的厉害之处。

对于读写,数据被存储直到达到特定大小,通过这种方式触发的写操作更少。同时还减少了 sycall(系统调用)的数量,却可以使用更高效的方式使用底层硬件。

Linux下的工具

如果你在Linux处理该文本,那这完全不是问题。自带的很多工具,能够帮你处理这个简单的问题。比如 head,读取某文件的前多少行;tail,读取某文件的最后多少行。

如果只是要读文件,那么 less 是你最佳的选择。

文档内说的很清楚,less并不直接读入整个文档,因此处理起来,比vi/vim编辑器速度快的多。

打开之后,就可以上下翻页阅读了。

结语

本文通过多种编程语言,实现了大文件的读取。

掌握核心的方法后,使用哪种语言实现,都可以。

【本文由 @程序员小助手 发布,持续分享编程与程序员成长相关的内容,欢迎关注】

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200228A0NO2F00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券