c中流和直接I / O之间的区别

时间:2015-07-12 13:59:30

标签: c file-io

在C中,我相信(如果我错了,请纠正我)有两种不同类型的输入/输出函数direct和stream分别导致二进制和ASCII文件。

在检索(读/写)和打印数据方面,流(ASCII)和直接(二进制)I / O有什么区别?

2 个答案:

答案 0 :(得分:1)

Streams是一种读取和写入数据的便携方式。它们提供灵活高效的I / O方式。 Stream是一个文件或物理设备(如监视器),它使用指向流的指针进行操作。 这是BUFFERED,也就是说,通过某个临时存储区域(缓冲区)从文件中读取或写入固定的chunk。但是,在刷新或写出缓冲区之前,写入缓冲区的数据不会出现在文件(或设备)中。 (\n这样做)。

在直接或低级I / O中 -

这种形式的I / O是UNBUFFERED - 每个读/写请求导致直接访问磁盘(或设备)以获取/放置特定数量的字节。 没有格式化设施 - 我们正在处理信息字节。 这意味着我们现在使用二进制(而不是文本)文件。

答案 1 :(得分:1)

不,是的,有点,也许......

  

在C中,...有两种不同类型的输入/输出函数,direct和stream,分别产生二进制和ASCII文件。

在标准C中,只有文件流FILE *。在POSIX C中,有可能被称为' direct'文件访问功能,主要使用文件描述符而不是文件流。 AFAIK,Windows还提供备用I / O功能,主要使用句柄而不是文件流。所以"不" - 标准C具有一种I / O功能;但是POSIX(和Windows)提供了替代方案。

在标准C中,您可以使用以下方法创建二进制文件和文本文件:

FILE *bfp = fopen("binary-file.bin", "wb");
FILE *tfp = fopen("regular-file.txt", "w");

在Windows(以及可能与Windows兼容的其他系统)上,您可以明确地打开文本文件:

FILE *tcp = fopen("regular-file.txt", "wt");

因此,该标准区分了文本和二进制文件,但文件流可用于访问任一类型的文件。此外,在Unix系统上,文本文件和二进制文件之间没有区别;他们将受到同样的待遇。在Windows上,文本文件将其CRLF(回车,换行)行结束映射到输入上的换行符,并将新行映射到输出上的CRLF行结尾。二进制文件不会发生这种转换。

请注意,Linux上还有一个概念'direct I/O',使用O_DIRECT标志激活,这可能不是您想要的。它是文件描述符I / O的改进。

  

在检索(读/写)和打印数据方面,流(ASCII)和直接(二进制)I / O有什么区别?

有很多问题。

  • 首先,文本文件和二进制文件之间的二分法与流I / O和直接I / O之间的二分法是分开的。

  • 使用流I / O,在处理文本文件时将行结尾从本机(例如CRLF)映射到换行符,而不处理二进制文件时没有这样的映射。

  • 使用文本I / O,假设数据中没有空字节'\0'。在一行中间的这些字节弄乱了期望读取为空的文本处理代码。对于二进制I / O,预期所有256个字节值;由于空字节而中断的代码被破坏。

  • 使这复杂化是用于编码文本文件的不同代码集之间的区别。如果您有单字节代码集,例如ISO 8859-15,则通常不会显示空字节。如果你有一个多字节代码集,如UTF-8,那么通常会出现空字节。但是,如果你有一个宽字符代码集,如UTF-16(无论是big-endian还是little-endian),那么你经常会在文件正文中得到零字节 - 它不能被读取或写入字节流,而不是16位单元的流。

  • 流I / O和直接I / O之间的主要区别在于流库缓冲输入和输出的数据,除非您使用setvbuf()覆盖它。也就是说,如果您反复读取用户代码中的单个字符(例如getchar()),则流库首先从文件中读取一块数据,然后从块中一次发出一个字符,仅当前一个块完全交付时,返回到文件以获取更多数据。相比之下,直接I / O一次读取一个字节将为每个字节进行系统调用。当然,内核将缓冲I / O(它也会为流I / O执行此操作 - 因此这里有多层缓冲,这是O_DIRECT I / O尝试尽可能避免的一部分) ,但每个字节的系统调用开销相当大。

通常,您可以使用文件描述符对访问进行更细粒度的控制;你可以使用文件描述符进行操作,这些操作对于流是不可行的,因为流接口功能根本不能涵盖这种可能性。例如,在文件描述符上设置FD_CLOEXECO_CLOEXEC意味着当程序执行另一个时,系统会自动关闭文件描述符 - 流库根本不涵盖这个概念,更不用说控制它了。获得细粒度控制的成本是您必须编写更多代码 - 或者至少是编写执行流库函数处理的代码的不同代码。