2012-07-29 43 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]是字節數組(不是某些字符集的字符),所以它可以處理任何值(包括不可打印,甚至爲零)。