2012-07-29 44 views
1
/* 
Low Level I/O - Read and Write 
Chapter 8 - The C Programming Language - K&R 
Header file in the original code is "syscalls.h" 
Also BUFSIZ is supposed to be defined in the same header file 
*/ 

#include <sys/types.h> 
#include <sys/uio.h> 
#include <unistd.h> 

#define BUFSIZ 1 

int main() /* copy input to output */ 
{ 
    char buf[BUFSIZ]; 
    int n; 

    while ((n = read(0, buf, BUFSIZ)) > 0) 
     write(1, buf, n); 

    return 0; 
} 

当我输入“∂ΣΣ®†¥¥¥˚πΔ~~∫∫√tu tu 886661〜EOF”作为输入时,复制相同的内容。 如此多的非ASCII字符被同时存储?unix读取和写入功能

BUFSIZ是要传输的字节数。 BUFSIZ如何限制字节传输如果对于任何值,任何东西都可以从输入复制到输出?

char buf [BUFSIZ]如何存储非ASCII字符?

+0

今天的非ASCII字符通常编码为UTF-8,所以一个字符可以被设置为高位的*多个*字节编码。 – 2012-07-29 07:47:01

+0

通常,BUFSIZ在''中定义,通常是512以上的两个幂。在这种情况下,将其定义为1是合法的(但不寻常)。您显示的代码不需要''或''; ''就足够了。 – 2012-07-29 08:55:56

回答

4

您可以通过小的块,直到EOF阅读:

while ((n = read(0, buf, BUFSIZ)) > 0) 

这就是为什么。你逐字逐字地将输入复制到输出。如何将其转换回unicode,是控制台的问题,而不是你的。我想,它不会输出任何东西,直到它可以将数据识别为符号。

+0

我还不是很清楚它是如何读取这么多字符的。 “886661〜EOF”包含许多字符,BUFSIZ仅指定1个字节的传输器。那么如何用1字节存储容纳阵列buf? – 2012-07-29 07:58:32

+1

仔细阅读。你一次只需要1个字节,但只要需要就可以完成。想象一下,你有一盒苹果。非常沉重,所以你尽可能多地拿着,把它搬到厨房,然后回到箱子里。冲洗并重复,直到盒子空了。所以,你可以处理的苹果数量 - 这是一个缓冲区大小。这可能很少,但迟早你会移动所有的苹果。 – KAction 2012-07-29 08:37:24

+0

例如,字符'∂'(U + 2202)在UTF-8中表示为3个八位字节(字节):“0xe2 0x88 0x82”。您的程序从标准输入中逐个读取这些字节,然后逐个将它们写入标准输出。然后,您的终端仿真器将三个字节重新组合为一个“∂”字符并显示出来。 – 2012-07-29 09:09:38

0

由于您在循环中调用读取,直到遇到错误中的'文件结束',您在每次读取调用后都会在buf中精确地显示1个字符。之后,通过写入系统调用打印字符。保证read系统调用不会超过它在最后一个参数中指定的值。例如,如果您传递10,则读取将继续并尝试复制读取的数据超出数组范围。

至于你喂的字符 - 这些似乎是扩展的ASCII字符(代码128-255),所以这里没有问题。

0

当您从标准输入读取呼叫时,您正在从管道读取数据,该数据会绑定到终端或另一个程序。编写者(终端或其他程序)和你的程序之间有一个缓冲区。当这个缓冲区是下溢阅读器(你的程序)在读取时被阻塞。当缓冲区溢出时比写入端(终端等)在写入时阻塞。

反之亦然,当您向写入管道的标准输出写入数据时,将绑定到终端或另一个程序。

所以如果你的程序是由shell从终端运行的,那么你的程序输入和输出将被绑定到(伪)终端。 (伪)终端是可以将用户的按键转换为字符并将一些编码字符串(ISO8859-1,UTF-8等)转换为屏幕上的符号的程序。

  1. 字符存储在终端程序中,然后按EOL的EOF。这是终端的典型模式。按下输入键后,字节被写入绑定到程序的管道。
  2. BUFSIZ是您尝试从每个操作的输入中读取的字节数。返回值是操作完成时真正读取的字节数。因此,BUFSIZ是程序可以从管道读取的最大字节数。
  3. char [BUFSIZ]是字节数组(不是某些字符集的字符),所以它可以处理任何值(包括不可打印,甚至为零)。