2009-08-16 4 views
4

テキストファイルの内容を動的に割り当てられた文字配列にコピーする必要があります。Cでテキストファイルを文字列にコピーする方法は?

私の問題は、ファイルの内容のサイズを取得しています。 Googleはfseekftellを使用する必要があることを明らかにしていますが、ファイルは明らかにバイナリモードで開く必要があり、それはゴミだけです。

EDIT:テキストモードで開こうとしましたが、奇妙な数字が表示されます。あなたは、ファイルの末尾にカーソルを置き、ファイルを開くオフセットを格納し、かつの先頭に戻ることができ

long f_size; 
char* code; 
size_t code_s, result; 
FILE* fp = fopen(argv[0], "r"); 
fseek(fp, 0, SEEK_END); 
f_size = ftell(fp); /* This returns 29696, but file is 85 bytes */ 
fseek(fp, 0, SEEK_SET); 
code_s = sizeof(char) * f_size; 
code = malloc(code_s); 
result = fread(code, 1, f_size, fp); /* This returns 1045, it should be the same as f_size */ 
+0

ファイルをバイナリモードで開くと、その内容は変更されません。あなたが持っているコードを投稿すれば、起こりうる問題を見つけることができます。 –

+0

この質問を参照してください:http://stackoverflow.com/questions/410943/reading-a-text-file-into-an-array-in-c –

+0

これは私がやっていることとほとんど同じですか? – Javier

答えて

14

問題の根はここにある:

FILE* fp = fopen(argv[0], "r"); 

ARGV [0]あなたの実行可能プログラム、NOTパラメータです。それは確かにテキストファイルではありません。 argv [1]を試し、何が起こるかを見てください。

+3

うわー、ありがとう。今私は愚かな気がする。 – Javier

+3

@reyjaviki - 良い:-)それは私の次になるよ... – Roddy

0

:ここでは、コードのです(私は明確にするためのチェック簡単なエラーを省略しました)ファイルを作成し、差をつけます。

1

fseekをテキストファイルとしても使用できます。ファイルの末尾に

  • fseek
  • ftellバック初め

  • fseek
  • をオフセットし、あなたは、ファイルのサイズを決定することはできません

    5

    ファイルのサイズを持っています固定幅のエンコーディングを使用している場合を除き、の文字にはデータが読み込まれません。

    たとえば、UTF-8の長さが8バイトのファイルは、長さが2文字から8文字までの任意の文字を使用できます。

    これはファイルAPIの制限ではなく、「バイナリデータのサイズ」から「文字数」への直接マッピングがないという自然な制限です。

    固定幅のエンコーディングを使用している場合は、バイト単位でファイルのサイズを1文字あたりのバイト数で分割できます。 ASCIIが最も明白な例ですが、あなたのファイルがUTF-16 でエンコードされている場合は、UTF-16コードポイントを "ネイティブ"内部文字タイプ(Java、。 NETとWindows)の場合、UTF-16が固定幅であるかのように割り当てる「文字」の数を予測できます。 (UTF-16はU + FFFF以上のUnicode文字が複数のコードポイントでエンコードされているために可変幅ですが、多くの開発者はこれを無視します)。

    +0

    私はそれを認識していませんでした...だから、ファイル全体を読んでカウンターを増やすべきですか?それはかなり遅くないでしょうか? – Javier

    +0

    また、fstat(2)を使用してください。 http://www.gnu.org/s/libc/manual/html_node/Reading-Attributes.html – scvalex

    +0

    @reyjavikviを参照してください:速くしたいですか、正確にしたいですか?可変幅のエンコーディングを使用している場合は、ファイルのデータを読み取ることなく、論理的には*行うことはできません。何か他のもの(オペレーティングシステムなど)がデータをキャッシュしてデータをキャッシュしない限り。 –

    0

    サンプルコードはありませんが、fstat )は、ファイルの大きさをあなたに伝えます。あなたは必要なメモリを割り当て、ファイルをスラップします。

    2

    あなたは、Linux(または他のUnixライクなオペレーティングシステム)のために開発している場合は、ファイルを開く前に、STATを使用してファイルサイズを取得することができますが:

    #include <stdio.h> 
    #include <sys/stat.h> 
    
    int main() { 
        struct stat file_stat; 
    
        if(stat("main.c", &file_stat) != 0) { 
         perror("could not stat"); 
         return (1); 
        } 
        printf("%d\n", (int) file_stat.st_size); 
    
        return (0); 
    } 
    

    編集:私は、コードを見るとわかるように、私は他のポスターとラインに取得する必要があります:

    プログラム・コールからの引数を取り、配列がこのように構成され

    プログラム自体の

    [0]名前
    [1]第一引数
    [2]第二引数与え
    与え [n]はn番目の引数

    あなたはまた、 '0' のargvアレイの以外のフィールドを使用しようとする前のargcを確認してください:

    if (argc < 2) { 
        printf ("Usage: %s arg1", argv[0]); 
        return (1); 
    } 
    
    2

    私はargv [0]がテキストファイルではないと確信しています。

    1

    argv [0]は実行可能ファイルへのパスで、argv [1]は最初に入力された入力です。 fp == 0であるかどうかを確認するなどの単純なエラーチェックを変更して追加してください。

    2

    は(これをコンパイルしていないが、私はこれをbazillion回をやったので、私はそれが、少なくとも近いですかなり確信して)これを試してみてください:

    char* readFile(char* filename) 
    { 
        FILE* file = fopen(filename,"r"); 
        if(file == NULL) 
        { 
         return NULL; 
        } 
    
        fseek(file, 0, SEEK_END); 
        long int size = ftell(file); 
        rewind(file); 
    
        char* content = calloc(size + 1, 1); 
    
        fread(content,1,size,file); 
    
        return content; 
    } 
    
    0

    別のアプローチは、読むことです一度に1つずつファイルを作成し、必要に応じてダイナミックバッファを拡張してください:

    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    
    #define PAGESIZE 128 
    
    int main(int argc, char **argv) 
    { 
        char *buf = NULL, *tmp = NULL; 
        size_t bufSiz = 0; 
        char inputBuf[PAGESIZE]; 
        FILE *in; 
    
        if (argc < 2) 
        { 
        printf("Usage: %s filename\n", argv[0]); 
        return 0; 
        } 
    
        in = fopen(argv[1], "r"); 
        if (in) 
        { 
        /** 
        * Read a page at a time until reaching the end of the file 
        */ 
        while (fgets(inputBuf, sizeof inputBuf, in) != NULL) 
        { 
         /** 
         * Extend the dynamic buffer by the length of the string 
         * in the input buffer 
         */ 
         tmp = realloc(buf, bufSiz + strlen(inputBuf) + 1); 
         if (tmp) 
         { 
         /** 
         * Add to the contents of the dynamic buffer 
         */ 
         buf = tmp; 
         buf[bufSiz] = 0; 
         strcat(buf, inputBuf); 
         bufSiz += strlen(inputBuf) + 1; 
         } 
         else 
         { 
         printf("Unable to extend dynamic buffer: releasing allocated memory\n"); 
         free(buf); 
         buf = NULL; 
         break; 
         } 
        } 
    
        if (feof(in)) 
         printf("Reached the end of input file %s\n", argv[1]); 
        else if (ferror(in)) 
         printf("Error while reading input file %s\n", argv[1]); 
    
        if (buf) 
        { 
         printf("File contents:\n%s\n", buf); 
         printf("Read %lu characters from %s\n", 
         (unsigned long) strlen(buf), argv[1]); 
        } 
    
        free(buf); 
        fclose(in); 
        } 
        else 
        { 
        printf("Unable to open input file %s\n", argv[1]); 
        } 
    
        return 0; 
    } 
    

    この方法では欠点があります。 1つは、ファイルの内容を保持するためのメモリが不足している場合は、すぐにそれを知ることができません。また、realloc()はコールするのが比較的コストがかかります。したがって、ページサイズを小さすぎないようにしたくありません。

    しかし、これにより、ファイルの大きさを事前に把握するためにfstat()またはfseek()/ ftell()を使用する必要がなくなります。

    関連する問題