C++ 文件读写方案选型

严格来说, 有 3 种风格.

  1. UNIX 底层读写库
  2. c 语言 stdio 标准库
  3. iostream 流

一般的工程中, 底层读写库封装程度太低, 需要自己处理缓存和很多通用的异常场景. 不适合.

网络编程中, 缓存会导致很多负面作用, 可以考虑用底层的读写库.

1. 格式化输出对比

1.1 格式化输出的可配置性

iostream 采用 manipulator 来格式化, 格式化信息写死在代码中, 难以实现可配置. -- 软件工程中绝对的硬伤.

stdio 采用的 %d %s 等已经发展成一个 DSL, 并在很多语言中通用. http://en.wikipedia.org/wiki/Printf_format_string#Programming_languages_with_printf

1.2 上下文无关

iostream 中, 通过改变流的状态来实现格式化输出, 而流的状态是全局的. 需要时刻小心,防止影响了后面的代码.

stdio 是上下文无关的.

1.3 缓冲区溢出

stdio 问题在于, 不是类型安全的, 而且存在缓冲区溢出的安全风险. 正确而安全的做法如下

#include <stdio.h>

int main()
{
    const int max = 80;
    char name[max];

    char fmt[10];
    sprintf(fmt, "%%%ds", max - 1);
    scanf(fmt, name);
    printf("%s\n", name);
}

1.4 类型安全与 64 位兼容性

stdio 的标准库, 需要明确知道待输出数据的类型, 并选择合适的 %d, %ld.

格式化字符串与参数类型不匹配会造成难以发现的 bug.

如果考虑到同时在 32 和 64 位机器上支持正确打印, %d 的选取更加头疼.

《The Linux Programming Interface》的作者建议(3.6.2节)先统一转换为 long 类型再用 "%ld" 来打印;对于某些类型仍然需要特殊处理,比如 off_t 的类型可能是 long long。

http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#64-bit_Portability

printf 无法像打印 int 那样用 printf 来直接打印 自定义对象。

1.5 性能

  1. 即使只使用了解释程序的一个功能,也要全部装载。如上面的例子,我们要装载整个包,包括解释浮点数和字符串那部分程序段,无法减少程序的长度。  2. 虽然printf族函数已经优化得很好,但是,它是在运行期间进行解释,如果能在编译期间分析格式字符串里的变量,根据不同的类型调用各自的函数处理,运行会快得多,而且C++编译期间的类型检查会有助于我们发现错误.

在线 ACM/ICPC 判题网站上,如果一个简单的题目发生超时错误,那么把其中 iostream 的输入输出换成 stdio,有时就能过关。
  3. 对于C++来说,printf不能被扩展是它最大的缺点。我们不能通过重载函数对它进行扩展,因为重载函数要有不同类型的参数,而printf族函数把类型信息隐藏在可变参数表和格式字符串中。

2. 线程安全

stdio 的函数是线程安全的,

而且 C 语言还提供了 flockfile(3)/funlockfile(3) 之类的函数来明确控制 FILE* 的加锁与解锁。

cout << a << b; 是两次函数调用,相当于 cout.operator<<(a).operator<<(b)。

两次调用中间可能会被打断进行上下文切换,造成输出内容不连续,插入了其他线程打印的字符。

3. 内存泄露

时间: 2024-10-26 22:26:07

C++ 文件读写方案选型的相关文章

【Win 10 应用开发】文件读写的三种方案

本文老周就跟伙伴们探讨一下关于文件读写的方法.总得来说嘛,有三种方案可以用,而且每种方案都各有特色,也说不上哪种较好.反正你得记住老祖宗留给我们的大智慧——事无定法,灵活运用者为上. OK,咱们开始吧. 先说第一个方案:使用 FileIO类. 这个类属于RT库API,它公开了一堆静态方法,可以直接调用,快捷方便,就像.net里面的File类一样.在使用FileIo类的时候,需要一个引用已知文件的StorageFile实例,而且FileIo只能操作已经存在的文件,它不会自动创建文件,这一点要注意.

基础入门_Python-模块和包.深入Celery之常用架构/方案选型/必知必会?

简单介绍: 说明: 此模块是一个专注于分布式消息传递的异步任务队列,所谓任务就是消息,消息中的有效载荷中包含要执行的任务需要的全部数据 几大特性: 1. Celery易于使用和维护,且不需要配置文件,默认配置启动时自动写入消息代理. 2. Celery高可用,连接丢失或失败时客户端或消费者会自动重试,并且可通过消息代理的双主/主从模式来提高高可用性 3. Celery快速,单个进程每分钟可处理百万任务,且优化后可保持往返延迟在亚毫秒级别 4. Celery灵活,几乎所有部分都支持扩展或单独使用,

Linux文件读写机制及优化方式

导读 Linux是一个可控性强的,安全高效的操作系统.本文只讨论Linux下文件的读写机制,不涉及不同读取方式如read,fread,cin等的对比,这些读取方式本质上都是调用系统api read,只是做了不同封装.以下所有测试均使用open, read, write这一套系统api. 缓存 缓存是用来减少高速设备访问低速设备所需平均时间的组件,文件读写涉及到计算机内存和磁盘,内存操作速度远远大于磁盘,如果每次调用read,write都去直接操作磁盘,一方面速度会被限制,一方面也会降低磁盘使用寿

[转载] MySQL高可用方案选型参考

原文: http://imysql.com/2015/09/14/solutions-of-mysql-ha.shtml?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io 本次专题是 MySQL高可用方案选型,这个专题想必有很多同学感兴趣. 高可用的意义以及各种不同高可用等级相应的停机时间我就不必多说了,直接进入主题. 可选MySQL高可用方案 MySQL的各种高可用方案,大多是基于以下几种基础来部署的: 基于主从复制:

手把手教你_android自动化实践方案选型

接到一个android自动化的任务,看了看手中的家伙:ranorex,appium,uiautomator 当然先捡商用的试试,简单呀,可以录制回放,不过不是抱特别大的期望,这个爷比较娇气,要是android工程中有第三方库可能就会instrument失败.这次运气不错,instrument成功了,录制了一下常用的操作,一切OK.想想还要准备一些啥: 先说手势:搜搜帮助: public void Swipe( Location startLocation, GestureDirection di

MongoDB报表实例方案选型

MongoDB报表实例方案选型 背景介绍 在我们的生产环境使用的是复制集,为了将数据库服务器的业务压力分摊,我们将数据库拆分到了不同的复制集上运行. 我们在MongoDB复制集上运行应用程序,有时候有报表需求,常规用途是获得用户行为的分析,还有其他商业定制指标数据:有搜索引擎的查询需求,使用Solr从oplog.rs获取增量数据更新产品信息的索引. 这些报表查询和搜索引擎的查询需求,尽量不能影响到线上的业务正常运行,因此不能直接在生产数据库上运行报表.经过开发和运维讨论之后,在项目成立之初,计划

Python(3):文件读写与异常

访问路径: 文件读写必然涉及到文件会放在某个路径下.在python里,可以通过引入os包来实现切换当前访问的路径: 1 # 假设我在 /home/zyq/KiDe/Python/test 文件夹中有一个文件 test.txt 那么我可以通过以下命 令定位到该文件夹: 2 >>>import os 3 >>>os.chdir('/home/zyq/KiDe/Python/test') 4 # 此时可以通过 os.getcwd() 来得到当前的工作目录. 5 # 此时可以通

MySQL高可用方案选型参考

本次专题是 MySQL高可用方案选型,这个专题想必有很多同学感兴趣. 高可用的意义以及各种不同高可用等级相应的停机时间我就不必多说了,直接进入主题. 可选MySQL高可用方案 MySQL的各种高可用方案,大多是基于以下几种基础来部署的: 基于主从复制: 基于Galera协议: 基于NDB引擎: 基于中间件/proxy: 基于共享存储: 基于主机高可用: 在这些可选项中,最常见的就是基于主从复制的方案,其次是基于Galera的方案,我们重点说说这两种方案.其余几种方案在生产上用的并不多,我们只简单

C++文件读写简单实例

转自:http://www.cnblogs.com/me115/archive/2010/09/20/1831555.html C++文件流: fstream // 文件流 ifstream // 输入文件流 ofstream // 输出文件流 //创建一个文本文件并写入信息 //同向屏幕上输出信息一样将信息输出至文件 #include #include void main() { ofstream f1("d:\\me.txt"); //打开文件用于写,若文件不存在就创建它 if(!