2014-09-04 61 views
0

我想用文件中的其他字符串覆蓋字符串的某些部分。c中的文件處理替換字符串

我想覆蓋文件的每一行。

我寫了下面的代碼,但這不行,請幫忙。

假設文件有多個線,其中線containe之一:--- abcdefghioverwritefxyz89760

應該如下轉變: - abcdefghichangemadexyz89760

char lineFileRecord [150]; 

fp = fopen("abc.txt","r+"); 

while (fgets (lineFileRecord , 150 , fp) != NULL) 
{ 
    char* sample; 
    sample = strstr(lineFileRecord, "overwritef"); 

    //overwritef and changemade both have same size 

    if(sample != NULL) 
    { 
     strncpy(sample, "changemade",10); // is the the correct way. 

    } 
} 

以上代碼不會取代內容。的文件。 如果我錯了,請糾正我。

感謝您的回覆。

+3

您需要將更改後的數據以正確的偏移量寫回文件。 – GWW 2014-09-04 15:09:01

+1

當文件的內容逐行讀入內存時,除非您採取措施寫入內容,否則內存中所做的任何更改都不會反映迴文件。請注意,您必須打開文件以進行更新,並且在每次寫入後必須在每次讀取之後尋找;當您在讀取和寫入之間切換或反之亦然時,兩個I/O操作之間必須執行查找操作(或等效操作 - 請參閱C標準)。如果你有一個內存映射文件,規則將會不同(從''你不會使用'fgets()'和一個內存映射文件'')。 – 2014-09-04 15:18:45

+0

你能解釋清楚嗎? – ashutosh 2014-09-04 15:29:04

回答

1

您總是在特定位置讀取/寫入文件。要進行這些更改,您需要跳回,覆蓋並跳回。

char lineFileRecord[150]; 
FILE* fp = fopen("abc.txt","r+"); 
long posWrite = 0; 
long posRead; 

while (fgets(lineFileRecord , 150 , fp) != NULL) 
{ 
    char* sample; 
    sample = strstr(lineFileRecord, "overwritef"); 

    //overwritef and changemade both have same size 

    if (sample != NULL) 
    { 
     // 1. Update your current lineFileRecord in memory. 
     strncpy(sample, "changemade", 10); 

     // 2. Remember where you were reading. 
     posRead = ftell(fp); 

     // 3. Jump back in the file to the beginning of your current lineFileRecord. 
     // This position was saved the previous time step 6 was executed. 
     fseek(fp, posWrite, SEEK_SET); 

     // 4. Now overwrite your file on disk! You were only changing the memory of 
     // of your program. And as you should know, memory and disk are 
     // different things. You need to overwrite the full lineFileRecord, 
     // because ftell() does not give a clean byte position in text files. 
     // THANKS @chux!!! 
     fwrite(lineFileRecord, 1, strlen(lineFileRecord), fp); 

     // 5. Finally jump forward to where you are reading. 
     fseek(fp, posRead, SEEK_SET); 
    } 

    // 6. Save the file position for the next overwrite. 
    long posWrite = ftell(fp); 
} 

備註:停止在你的代碼中使用TAB,它會弄亂縮進;總是使用空格!

+1

在文本文件中使用'fseek()'的計算值是一個問題。最好在'fgets()'之前使用'ftell()'來知道從哪裏開始寫入。 'fseek()':「對於文本流,任何一個偏移量應該爲零,或者偏移量應該是一個先前成功調用ftell函數返回的值,這個函數在與同一個文件關聯的流上,並且應該是SEEK_SET。 .9.2 4 – chux 2014-09-04 15:51:19

+0

@chux你說得對!我重新編寫了代碼。 – 2014-09-04 16:33:57

+0

解決方案看起來很好。 但fp不會隨char *樣本一起移動。它將始終爲零。 如果我錯了,請糾正我。 – ashutosh 2014-09-05 12:02:55

0

讀取文件與將文件內容複製到內存*相同。您正在修改內容的副本,而不是原件。

您應該將整個文件的內容複製到內存中,更改該內容,然後覆蓋整個文件,或使用函數調用如feekfputs來修改文件的某些部分。如何寫入文本文件在這個問題中進行了解釋:Write to .txt file?

*除非您使用類似內存映射文件的內容。作爲初學者,做不是使用內存映射文件,它們不是微不足道的使用。

+0

「將整個文件的內容複製到內存」有點矯枉過正。在許多系統上,內存空間(甚至虛擬內存空間)可能小於文件大小。 – chux 2014-09-04 16:44:20

+0

@chux特殊情況下的過早優化。問題是關於文本文件。即使是Raspberry Pi也有512 MB RAM。 – Peter 2014-09-04 16:47:48