如果我需要每秒读取文件 0...5 次,是不是值得保持文件描述符打开?

Posted

技术标签:

【中文标题】如果我需要每秒读取文件 0...5 次,是不是值得保持文件描述符打开?【英文标题】:Is it worth to keep file descriptors open in case i need to read the file 0...5 times per second?如果我需要每秒读取文件 0...5 次,是否值得保持文件描述符打开? 【发布时间】:2012-09-07 12:53:30 【问题描述】:

我用 C++ 开发跨平台音频编辑器,它以每秒 0...5 次的速度读取媒体文件(在播放模式下或在屏幕上重新绘制声音时)。该实现打开一个文件并在对该文件的所有读取操作之间保持打开描述符。

我认为即使打开文件也不禁止任何文件操作对用户更友好。我会允许用户在播放时删除该文件(如果他/她愿意)。在下一次尝试从该文件读取下一个块失败后,程序将停止播放。

在现代 Windows / Linux / Mac OS 系统上,open()/close() 操作成本高吗?

但是打开()/关闭()巨大的 MP3 文件会很困难,因为 MP3 的“seek()”可能很昂贵(在需要的块之前读取所有块的标题)。

【问题讨论】:

你试过测量自己吗? 当然,使用 MP3 您不需要读取所有标题 - 您可以查找文件中的特定偏移量,查找帧开始幻数,然后从那里播放?如果用户在播放时编辑文件,改变文件的大小,那么他们应该期望播放中至少有一个亮点,并且可能让播放器跳到曲调中的不同位置(如果他们已经切掉了开始,例如)。 另外:即使打开/查找/读取速度很慢,您也可以通过每秒不执行 5 次来缓解这种情况。缓冲尽可能多的数据,以提高文件访问速度。允许在播放期间修改文件对您来说很友好(例如,如果您在播放 MP3 文件时不能修改其 ID3 标签,这很烦人,因为那时您会发现它们是错误的),但您将拥有这样做需要付出一些代价。 【参考方案1】:

许多专业音频应用程序(或至少一些)在播放期间保持文件打开并在不播放时关闭文件 - 在需要重绘时打开和搜索的速度足够快。但是,Pro 音频应用程序本身不能与 MP3 等格式一起使用——它们总是首先转换为未压缩的格式。 其中一个的原因是 MP3 的采样精确搜索时间要差得多。理论上,如果没有任何变化,MP3 阅读库可以关闭文件并重新打开它停止的地方,但我认为 MP3 库不支持这一点。相比之下,未压缩的文件非常快速且易于查找。

回到您的问题:您是否要在每次屏幕重绘时重新打开并重新搜索,并且在播放期间经常重新搜索?好吧,你可以,而且与保持打开状态相比,它甚至可能不是屏幕重绘的拖累。现代机器肯定可以在播放过程中保持足够的缓冲,特别是如果它只是一个文件,所以这也是可行的。如果你真的想这样做,你应该做一些测试,看看性能受到什么影响,看看你是否真的想为此减慢用户的机器速度。

你还问什么更“友好”?您建议用户可以在另一个应用程序中“更改”文件,但是如何以及为什么?例如,如果您的程序试图在用户“更改”它的那一刻重新打开,会发生什么?更改可能涉及用另一个文件替换它,但许多应用程序通过首先删除原始文件,然后写入替换(或将替换移动到位)来“替换”文件。那么如果您的应用程序试图在错误的时刻打开文件会发生什么?它会说,“哦,文件不见了,我现在停止播放。”更糟糕的是,当仅部分写入替换时,程序会打开。呸。我可以想象更糟糕的情况,但这是一个开始。

如果您需要写入文件(例如对于 ID3 标签),这通常可以通过以 RW 模式打开文件(或重新打开已打开的文件描述符)来完成,因为它通常涉及覆盖数据或修改文件的结尾。我不建议在播放过程中进行任何更改播放样本数量、播放样本位置等的操作,除非您非常仔细地计划,因为情况充满了竞争条件。如果你这样做了,你应该在你自己的应用程序中这样做,因为这些比赛更容易控制。

所以也许这是值得的,但我强烈建议不要这样做。如果另一个应用程序写得不好,可能会发生不好的事情。

【讨论】:

谢谢!我发现这个回复非常有用,我会同意所有这些想法。我分析了 Audacity 的工作,看看它如何使用打开文件的未压缩副本,所以我知道这是常见的做法,我应该转向它。 MP3 和 FLAC 随机搜索有时太久以至于我的音频层说:“好的,我等不及下一个块了,停止!” :) 特别是对于很长(大约一个小时)的文件(-; 但有时你不想等待一分钟来转换大的音频文件,而是更愿意直接打开它,比如说,从 mp3 复制一小段。我想这必须是一个选项。 很高兴有帮助。我担心其中一些会显得有点生硬。

以上是关于如果我需要每秒读取文件 0...5 次,是不是值得保持文件描述符打开?的主要内容,如果未能解决你的问题,请参考以下文章

iPhone - 核心运动旋转率

使用 Python 检查 Telnet 是不是仍然连接

内存映射文件的性能特点

2021高频PHP面试题(值得收藏)

在python中每秒将鼠标位置写入文件100次

如何创建一个简单的计时器,使用setInterval每秒执行一次有趣的事情?