2014-09-04 3 views
0

문자열의 일부를 파일의 다른 문자열로 덮어 쓰려고합니다.파일을 처리하여 문자열을 바꾸기

파일의 각 줄을 덮어 쓰려고합니다.

아래 코드를 작성했지만이 코드는 도움이되지 않습니다.

가정 해 파일을 여러 개의 선이 어디 선 컨테이너, 중 하나 --- 다음과 같이 변환해야 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

+1

파일의 내용을 한 줄씩 메모리에 읽으면 메모리에 변경된 사항은 사용자가 쓰기 작업을 수행하지 않는 한 파일에 반영되지 않습니다. 업데이트를 위해 파일을 열어야하므로 각 쓰기 후에 _and_을 읽은 후에 검색해야합니다. 읽기와 쓰기 또는 그 반대로 전환 할 때 두 I/O 작업 사이에 탐색 작업이 있어야합니다 (또는 C 표준 참조). 만약 당신이 메모리 맵핑 된 파일을 가지고 있다면 규칙은 다르다 ('fgets()'를 메모리 맵핑 된 파일과 함께 사용하지 않는 것부터 시작한다). –

+0

명확하게 설명해 주시겠습니까? – ashutosh

답변

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()': "텍스트 스트림의 경우 offset은 0이 될 것이고, 오프셋은 같은 파일과 연관된 스트림에서 ftell 함수에 대한 이전의 성공적 호출에 의해 반환 된 값이어야하며, SEEK_SET이어야한다. §7.21 .9.2 4 – chux

+0

@chux 맞습니다! 다시 코딩했습니다. –

+0

해결책이 멋지게 보입니다. 하지만 fp는 char * sample과 함께 이동하지 않습니다. 항상 0이 될 것입니다. 내가 틀렸다면 나를 바로 잡으세요. – ashutosh

0

파일 읽기는 파일 내용을 메모리 *로 복사하는 것과 같습니다. 원본이 아닌 내용의 사본을 수정하고 있습니다.

전체 파일의 내용을 메모리로 복사하고 내용을 변경 한 다음 전체 파일을 덮어 쓰거나 feekfputs과 같은 함수 호출을 사용하여 파일의 일부를 수정해야합니다. 텍스트 파일에 쓰는 방법은 다음 질문에 설명되어 있습니다. Write to .txt file?

* 메모리 매핑 파일과 같은 것을 사용하지 않는 한. 초보자는 이 아니며은 메모리 매핑 된 파일을 사용합니다. 사용하는 것은 간단하지 않습니다.

+0

"전체 파일 내용을 메모리에 복사하십시오."라는 말은 조금 과장됩니다. 많은 시스템에서 메모리 공간 (가상 메모리 공간조차도)은 파일 크기보다 작을 수 있습니다. – chux

+0

@chux 특별한 경우를위한 조기 최적화. 질문은 텍스트 파일에 관한 것이 었습니다. 심지어 라즈베리 파이에는 512 MB RAM이 있습니다. – Peter

관련 문제