1. 程式人生 > >C語言檔案操作與Python檔案操作的比較

C語言檔案操作與Python檔案操作的比較

無論是在C語言中還是在Python中,對檔案的操作都是直接實現了計算機內部與外部之間的互動;

通過將資料寫入檔案可以更好地實現資料的儲存,而不會在程式結束之後資料隨之消失,

而通過檔案的讀取操作則可以更好地避免自己講大量資料的手動輸入程式。

 

本篇文章主要介紹C語言以及Python中基本的對檔案的操作,

旨在可以通過類比來達到更好的理解兩種不同語言中的同種操作的不同語法的目的,

相比較而言每種方式都有每種方式的長處與短板,無非好壞。

****************************************************************************************************************************************

 

一:C語言中的對檔案的操作 

 主要介紹以下函式:
★fopen(path,model) + fclose(FILE*fp)
★fgetc(FILE*fp) + fputc(char c,FILE*fp)
★fgets(char *a,n,FILE *fp) + fputs(char *str,FILE *fp)

1)檔案的開啟與關閉

 FILE 是一個結構體指標變數,首先自定義一個檔案型別變數:FILE *fp (file point檔案指標)
 然後通過fopen()開啟檔案返回指標存進自定義的FILE變數中,
 緊接著可以使用一系列已給出的函式對該檔案型別的指標進行操作來實現檔案的讀取與儲存,
 最後需要關閉檔案 (這一步不可省略,舉個例子:當你首先以write模式開啟一個檔案,在沒有關閉該檔案的情況下如果再次通   過read模式開啟該檔案,那麼就會無法讀取到任何東西,然而在python中就有相應的語句可以不用手動輸入檔案結束語句)

 下面附上檔案的開啟(fopen)與關閉(fclose)的程式碼:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	FILE *fp,*fp1;
	if(!(fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","rb")))
	{
		printf("Open file error!\n");
		exit(0);
	}
	else
	{
		printf("Open Success! ");
	}
	fclose(fp);
	return 0;
}

 檔案的開啟函式fopen()需要傳入兩個引數,其函式原型為:FILE * fopen(const char * path, const char * mode)

 第一個引數是需要開啟的檔案目錄,第二個引數是需要以什麼樣的方式開啟檔案:

 最常用的開啟檔案的幾種方式:

 1> r :read 以只讀方式讀取檔案,在該模式下不允許寫入檔案的操作,該檔案必須存在,如果不存在不會建立新檔案;

 2>w :write 開啟只寫檔案,若檔案存在則長度清為 0,即該檔案內容消失,若不存在則建立該檔案;

 3>w+:write+ 開啟可讀/寫檔案,其餘與w一致,會自動建立不存在的檔案;

 4>a :add 追加模式(開啟只寫檔案),在檔案的後方進行資料新增(原先的EOF結束符保留),若檔案不存在,會建立該檔案;

 5>a+ :add+ 追加模式(開啟可讀/寫檔案),在檔案的後方進行資料新增(原先的EOF結束符被清除),也會建立不存在的檔案;

 

2)檔案的單個字元存取(fgetc()+fputc()) -> (file_getchar+file_putchar)

 讀取操作函式原型:fgetc(FILE*fp)

//fgetc()函式的使用舉例 

#include <stdio.h>
#include <stdlib.h>
int main()
{
	FILE *fp,*fp1;
	if(!(fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","r")))
	{
		printf("Open file error!\n");
		exit(0);
	}
	//原文字檔案中存有資料:123456789
	char ch;
	ch = fgetc(fp);
	printf("%c",ch);
	printf("%c",ch);
	printf("%c",ch);
	//輸出結果為:111 
	printf("\n");
	//比較下面的輸出與上面不同的原因 
	ch = fgetc(fp);
	printf("%c",ch);
	ch = fgetc(fp);
	printf("%c",ch);
	ch = fgetc(fp);
	printf("%c",ch);
	//輸出結果為:234 
	fclose(fp);
	return 0;
}

 寫入操作函式原型:fputc(char c,FILE*fp)

 檢查一下下面的程式碼,思考有沒有什麼錯誤?

//fputc()函式的使用舉例 

#include <stdio.h>     //getchar()函式在這裡面 
#include <stdlib.h>    //包含exit()函式 
int main()
{
	FILE *fp,*fp1;
	if(!(fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","w")))    //這裡更換開啟模式為write 
	{
		printf("Open file error!\n");
		exit(0);
	}
	//原文字檔案中存有資料:123456789
	fputc('1',fp);
	//下面迴圈讀取資料進行顯示 
	char ch = fgetc(fp);
	while(ch!=EOF)    //EOF?下面會講到 
	{
		putchar(ch);	//在函式庫stdio.h中
		ch = fgetc(fp);
	}
	fclose(fp);
	return 0;
}

    沒看出來?

 ★錯誤在於第一次向檔案中寫資料的時候,檔案沒有關閉,而且第二次再次對檔案進行不同操作的時候沒有宣告檔案開啟方式為read。

   下面稍作修改:

//fputc()函式的使用舉例 

#include <stdio.h>     //getchar()函式在這裡面 
#include <stdlib.h>    //包含exit()函式 
int main()
{
	FILE *fp,*fp1;
	if(!(fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","w")))    //這裡更換開啟模式為write 
	{
		printf("Open file error!\n");
		exit(0);
	}
	//原文字檔案中存有資料:123456789
	fputc('1',fp);
	//下面迴圈讀取資料進行顯示(這個時候檔案中只有一個數據:1)
	fclose(fp);
	//操作方式改變的時候需要再次宣告開啟方式再進行操作 
	if(!(fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","r")))    //這裡更換開啟模式為read
	{
		printf("Open file error!\n");
		exit(0);
	}
	char ch = fgetc(fp);
	while(ch!=EOF)    //EOF?下面會講到 
	{
		putchar(ch);	//在函式庫stdio.h中
		ch = fgetc(fp);
	}
	fclose(fp);
	return 0;
}

EOF馬上在後面就會提到,這裡先思考怎樣通過迴圈將一連串字元輸入檔案呢?(答案見下面)

#include <stdio.h>     //getchar()在這個庫檔案中
#include <stdlib.h>    //exit()
#include <conio.h>     //getch()
int main()
{
	FILE *fp;
	if(!(fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","w")))
	{
		printf("Open file error!\n");
		exit(0);
	}
	char ch;
	do
	{
		//ch = getch();    //不回顯 
		ch = getchar();    //回顯 
		fputc(ch,fp);
	}while(ch!=' ');    //輸入空格停止迴圈讀取 
	fclose(fp);
	if(!(fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","r")))
	{
		printf("Open file error!\n");
		exit(0);
	}
	ch = fgetc(fp);
	while(ch!=EOF)
	{
		putchar(ch);	//在庫檔案stdio.h中
		ch = fgetc(fp);
	}
	fclose(fp);
	return 0;
}

Addition:EOF?

簡單來說EOF是一個巨集定義:#define EOF -1,在這裡起到用來結束檔案的作用。

不明白的話我來舉個例子:

如果你想通過輸入單個字元來迴圈寫入檔案一些資料,那麼當自己不想輸入的時候應該怎麼辦呢?

是不是首先想到了設定一個識別符號,當輸入的字元遇到這個字元就會返回,當然這也是可以的,

但是再深入想一想:在C語言中程式在讀取檔案的時候是如何判斷檔案什麼時候截止呢?這就涉及到了EOF結束標記,該標記位於檔案的末尾處,下面通過程式碼看一下如何使用:

#include <stdio.h>     
#include <stdlib.h>    
int main()
{
	FILE *fp;
	if(!(fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","w")))   
	{
		printf("Open file error!\n");
		exit(0);
	}
	char ch;
	while((ch=getchar())!=EOF)
	{
		fputc(ch,fp);
	}
	return 0;
}

這裡在輸入截止的時候換行在新的一行開頭按下:Ctrl+z 即可輸入EOF表示檔案截止;

在讀取檔案的時候也可以按照這個方法來進行判斷檔案是不是結束了(就像最初提到EOF的那個demo一樣)。

★這裡再提一下中文編碼的識別亂碼問題:

一個很好的解決辦法是直接修改本地檔案的編碼為ANSI (可以通過Notepad++記事本修改)

具體關於ANSI編碼可以參考另一篇博主的文章:https://blog.csdn.net/xiangxianghehe/article/details/77574965

 

3)實現字串的存取(fgets()+fputs())

1>讀取函式原型:int fgets(char *a,n,FILE *fp)   -> 讀取n-1個字元

引數解讀:

第一個引數是需要存讀取到的資料的一個數組指標,需要讀取的檔案在第三個引數位置指明,第二個引數值指明讀取字元的數量。

★在讀取字串的時候遇到換行符時函式會返回NULL,可以通過這一點來對每行進行操作,例如將一個檔案中的資訊按照每行讀取的方式寫入另一個檔案。

while(fgets(buffer,512,fp)!=NULL)
        printf("%s\n",buffer);

//這個迴圈每讀取到一個換行符的時候就會執行迴圈內部的語出,輸出換行之前讀取到的字串

* buffer 緩衝區(只是借用這個單詞定義變數名)

2>寫入函式原型:int fputs(char *str,FILE *fp)

#include <stdio.h>     
#include <stdlib.h>    
int main()
{
	FILE *fp;
	if(!(fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","w")))   
	{
		printf("Open file error!\n");
		exit(0);
	}
	fputs("12121",fp);
	printf("Write Complete!"); 
	fclose(fp);
	return 0;
}

3>將一個檔案中的資訊貼上到另一個檔案中

//將一個檔案中的資訊以附加方式存到另一個檔案中 

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define SIZE 512
int main()
{
	FILE *fp,*fp1;
	char buffer[SIZE];
	if(!(fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","w")))
	{
		printf("Open file error!\n");
		exit(0);
	}
	char ch;
	printf("Input Data: \n"); 
	do
	{
		//ch = getch();    //不回顯 
		ch = getchar();    //回顯 
		fputc(ch,fp);
	}while(ch!=' ');    //輸入空格停止迴圈讀取 
	fclose(fp);
	if(!(fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","r")))
	{
		printf("Open file error!\n");
		exit(0);
	}
	printf("\nTraverse Data: \n"); 
	ch = fgetc(fp);
	while(ch!=EOF)
	{
		putchar(ch);	//在庫檔案stdio.h中
		ch = fgetc(fp);
	}
	printf("\n");
	fclose(fp);
	fp = fopen("C:\\Users\\dell\\Desktop\\Python\\test.txt","r"); 
//	while(fgets(buffer,SIZE,fp)!=NULL)
//        printf("%s\n",buffer);    //第一次讀取一遍過後可以理解為fp中的讀取位置已經到了最後,再次讀取將不會讀取到任何資料 
    fp1 = fopen("C:\\Users\\dell\\Desktop\\Python\\test1.txt","a");
    while(fgets(buffer,SIZE,fp)!=NULL)
    fputs(buffer,fp1);
    fclose(fp);
    fclose(fp1);
    printf("Add-copy Complete!"); 
	return 0;
}

 

 

 

二:Python中對檔案的操作

1)檔案的開啟file.open()+檔案的關閉file.close()+檔案的讀取file.read()+檔案的寫入file.write()

1>在python中可以直接使用open()函式進行檔案的開啟與編碼方式的指定:

file = open("C:\\Users\\dell\\Desktop\\Python\\test.txt","w",encoding="utf-8")

各個引數的含義幾乎與C語言中的一致,最後一個引數是指定編碼格式為UTF-8;

這裡如果沒有指定編碼格式,預設為:encoding='cp936' (code page 936 -> GBK)

★encode:編碼  decode:解碼

2>這裡的file型別我們來檢視一下:

print(type(file))

結果:<class '_io.TextIOWrapper'>  文字輸入輸出流(可以通過相應的read()函式進行讀取)

3>文字的讀取:

file.read()    #預設檔案資料為:123abc

=> 如果檔案中有換行的話換行符會被轉換為\n輸出!

結果:'123abc'

4>文字的寫入:

f.write("124578\n454578414")

=> 那麼這裡的\n是否會被識別為換行符呢?=>答案是會被識別為換行

2)不手動使用file.close()的語句

with open("C:\\Users\\dell\\Desktop\\Python\\test1.txt","w",encoding="utf-8") as file:
    file.write("457878")

=> 注意冒號!

3)迴圈操作讀取的資料(使用到自定義操作函式process())

f = open("C:\\Users\\dell\\Desktop\\Python\\test.txt",encoding="utf-8")
char = f.read(1)
while(char):
    process(char)
    char = f.read(1)
f.close()

 

 

 

 

 

# 基本操作已經大致介紹完了,如果後期發現不足會繼續在下方更新。

****************************************************************************************************************************************

 

             最快的腳步不是跨越,而是繼續,最慢的步伐不是小步,而是徘徊。
 

****************************************************************************************************************************************