ASCII파일의 삭제 및 수정에 관해서....

고승현의 이미지

C 프로그램을 하다보면,

설정 파일 등과 같이 ASCII형태의 파일들에 어떤 문자열을 삽입하고, 삭제, 수정등을 해야 하는 경우가 있습니다.
binary 형식의 파일 이라면, 삽입할 때 record형식으로 삽입하고, 수정 이나 삭제 시에도, 해당 레코드에 접근해서 삭제나 접근을 하면됩니다.

하지만 위와 같은 파일의 경우에는 record형식의 접근이 어렵습니다.

이럴 때 파일의 어느 부분을 삭제하고 수정할 때 어떻게 하시는지요?

제 경우에는 삽입할 때는 추가 모드로 연후에 파일의 제일 마지막에 추가 시킵니다.
삭제 할 때는 원본 파일과 임시 파일 두개를 열어서
원본 파일에서 fgets로 한줄씩 받아서 제가 원하는 문자열과 비교해 나가면서 같은 문자열이 아닌경우에는 임시파일에 저장합니다. 그러다가 같은 문자열을(삭제할 문자열) 만난 경우 임시 파일에 저장하지 않고, 다음 문자열을 받습니다.
파일의 끝까지 받은 후에는 원본 파일을 삭제하고, 임시파일을 원본 파일로 교체합니다.

수정할 때는 삭제할 때와 비슷하고, 같은 문자열을 만난 경우에만 임시 파일에 바꿀 문자열을 삽입합니다.

이 방법 말고 다른 방법이 있나요?
lex , yacc 등을 이용하면, 파싱등이 쉽게 이루어진다고 하던데...

아직 컴파일러와 파일처리에 대해서 공부를 못해서 방법 등이 생각 나지 않는군요.

아래는 아파치 서버의 가상 호스트 부분만을 프로그램에서 삽입하고, 삭제하는 함수 입니다.
이곳에서는 삽입할 때 "#+++id+++", "#---id---" 이런식으로 구분해서 집어 넣고 삭제 할 때 이것을 이용해서 삭제를 하는데요. 이 것 보다 편하거나, 효율적으로 프로그램을 할 수 있는 방법이 있을까요?

int append_virtual_host(char *user_name, char *domain, char *ip, char *user_dir)
{
        FILE *fp;
        fp = fopen("virtual_host.txt", "a");
        fprintf(fp,
"#+++%s+++
<VirtualHost %s>
        ServerAdmin %s@%s
        DocumentRoot /%s/%s/public_html
        ServerName %s.%s
        ErrorLog /usr/local/apache/logs/%s.%s-error_log
        CustomLog /usr/local/apache/logs/%s.%s-access_log common
</VirtualHost>
#---%s---\n",
        user_name, ip, user_name, domain, user_dir, user_name, user_name, domain, user_name, domain, user_name, domain, user_name);

        fclose(fp);
        return 1;
}

int delete_virtual_host(char *user_name)
{
        char *buf, *str1, *str2;
        FILE *fr, *fw;
        buf = (char *)memset((char *)malloc(1024+1), 0x00, 1024+1);
        str1 = (char *)memset((char *)malloc(32), 0x00, 32);
        str2 = (char *)memset((char *)malloc(32), 0x00, 32);

        fr = fopen(VHOST_FNAME, "r");
        fw = fopen(VHOST_TMPNAME, "w");
        sprintf(str1, "#+++%s+++\n", user_name);
        sprintf(str2, "#---%s---\n", user_name);

        while(fgets(buf,1024,fr)!=NULL)
        {
                if(strcmp(str1,buf)==0)
                {
                        while(fgets(buf,1024,fr)!=NULL)
                        {
                                if(strcmp(str2, buf)==0)
                                        break;
                                memset(buf, 0x00, 1024+1);
                        }
                        /* 상위 while문 빠져나감 */
                        if(buf==NULL)
                                break;
                } else
                {
                        fputs(buf, fw);
                        memset(buf, 0x00, 1024+1);
                }
        }
        fclose(fr);
        fclose(fw);
        unlink(VHOST_FNAME);
        rename(VHOST_TMPNAME, VHOST_FNAME);

        return 1;
}

:roll:

jj의 이미지

C에서 일일히 구현하는건, 일단 시간도 많이 걸리고, 실수하기 쉬울것 같군요.

저라면, awk, sed 같은 유닉스 기본 유틸리티를 system으로 끌어쓰겠습니다.

KeepItSimple~

--
Life is short. damn short...

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.