Hatena::ブログ(Diary)

しんちゃんの日記

2017-06-19 巨大なファイルを逆順で表示するCプログラム

ネットで1000万行のファイルを読み込ませて逆順にしたいとか言うのを(perlで)みたので、Cで1500万行近くまで対応してみた。


やり方としては一回EOFまでfputs回して、ftellで位置情報を配列に記録。
配列の逆から位置情報読み込んでfseekで移動を繰り返す。
記録時間が最初かかるけど、配列の大きさからビビっていたほどはメモリも消費しない。
(1400万行3.1GBの文字ファイルに対し、4GBメモリの0.6%)

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char *argv[])
{
    for(int i = 1; i < argc; i++)
    {
        FILE *fp;

        if((fp = fopen(argv[i],"r")))
        {
            const int BUF = 1024 * 4;
            char s[BUF];
            long *fpos;
            int k = 0;
            
            puts(argv[i]);
            fpos = malloc(sizeof(long)*15000000);
            if (fpos == NULL) exit(0);
            fpos[++k] = ftell(fp);
            while((fgets(s,BUF - 1, fp)))
            {
                fpos[++k] = ftell(fp);
            }
            int j = 1;
            fseek(fp,fpos[--k],SEEK_SET);
            while(fgets(s,BUF - 1,fp)) 
            {
                if(k > 0)
                {
                    printf("%4d:%s", j++, s);
                    fseek(fp,fpos[--k],SEEK_SET);
                }
            }
            free(fpos);
            fclose(fp);
        }
        else
        {
            printf("ファイル[%s]がありません\n",argv[i]);
            return -1;
        }
    }
    return 0;
}