文件
C程序,將文件看做是連續字節序列,其中每個字節都可以單獨讀取.這個與UNIX環境中的文件結構是一致的.但ANSI C為了與其他的OS環境兼容(比如Windows),提供了兩種文件視圖: 文本視圖和二進制視圖.
文本視圖和二進制視圖
二進制視圖中,文件中的每個字節都可以為程序訪問.但文本視圖中,程序中看到的內容與文件的內容可能不同.
例如MS-DOS文本文件用"\r\n"來表示行尾; Macintosh文本文件中用"\r"表示行尾; C程序使用"\n"表示行尾. So,如果C程序以文本視圖模式處理一個MS-DOS文本文件,在讀取文件時,就會將"\r\n"轉換為"\n",在寫入文件時,就會將"\n"轉換為"\r\n". Macintosh同理.
說白了,兩種視圖的實現是一樣的,只是在處理行尾或處理文件結尾時有點不同而已.采用某種視圖打開文件時,注意一下就是了.
文件結尾和換行
文件讀取數據的程序需要在達到文件結尾時停止.當到達文件結尾時,"getc()"函數會返回一個特殊值EOF.所以C程序只有在讀取超出文件結尾后,才會發現文件的結尾.
為了避免讀取空文件帶來的問題,應該對文件輸入使用入口條件循環(使用while或for,避免使用do...while)如下設計:
int ch; // Watching EOF
FILE* fp;
fp = fopen ("_FileName", "_Mode");
ch = getc (fp);
while (ch != EOF)
{
putchar (ch);
ch = getc (fp);
}
上面的例子可以看做是一個框架,來進行文件結尾的判斷.但ANSI C的兩種模式,對于文件結尾有不同的解釋.
如果文件以文本模式打開,C可以認出EOF標志文件結尾.如果以二進制模式打開,就會把EOF當做是文件中的一個字符.真正的文件結尾還在后面.文件的結尾,可能緊跟著EOF,當然,也可能用空字符填充文件使其大小為256(或其他數)的倍數.在DOS下不打印空字符.程序中包含了防止程序打印EOF字符的代碼.
MS-DOS的文本文件用二進制模式和文本模式打開,C程序將看到下面的內容:
二進制模式打開文件C程序看到的內容: line1\r\n line2\r\n line3\r\n ^Z | 文本模式打開文件C程序看到的內容: line1\n line2\n line3\n ^Z |
例子 : 逆序輸出一個文件內容
#include <stdio.h>
#include <stdlib.h>
#define MAC
#define CNTL_Z '\032' /* DOS Text File End Of File Flag */
#define SLEN 50
#define PATH
int main (void)
{
unsigned char file[SLEN];
unsigned char ch;
FILE* fp;
unsigned long count;
unsigned long last;
puts ("Enter Name Of File To Be Processed : ");
gets (file);
if ((fp = fopen (file, "rb")) == NULL)
{
printf ("Reverse Can't Open %s .\n", file);
exit (1);
}
fseek (fp, 0L, SEEK_END); /* Locate To End Of File */
last = ftell (fp);
for (count = 1L; count <= last; count++)
{
fseek (fp, -count, SEEK_END); /* Back 1 Byte */
ch = getc (fp);
if (ch != CNTL_Z && ch != '\r')
{
putchar (ch);
}
#if defined MAC || defined WIN32
/* Macintosh || Windows */
if (ch == '\r')
{
putchar ('\n');
}
else
{
putchar (ch);
}
#endif
putchar ('\n');
fclose (fp);
return 0;
}
}