3

でのファイル オープン モードに問題がありますfopen()

私の場合、カーソルを自由に探したいのですが、場合によってはそれを超えるEOFこともあります。さらに、既存のファイルを切り捨てるのではなく、追加したいと考えています。a+モードでファイルを開こうとしました。ただし、ファイルカーソルを自由にシークできません。を超えてカーソルをシークするたびにEOF、新しい到着データは、指定した位置ではなく、ファイルの最後に追加されます。モードで開いた場合w+、既存のファイルは切り捨てられます。この問題の完全な解決策はありますか?


アップデート:

明確に指定されていない点の 1 つは、ファイルが常に存在するとは限らないことです。その場合、新しいファイルを作成する必要があります。

実際、構成ファイルを処理したいのです。このように実装するのが良い習慣かどうかはわかりません。または、最初に空の構成ファイルを配置する必要があります。したがって、ファイルが存在しない場合は気にする必要はありませんか?

以下はコード スニペットです。

FILE *f = fopen(FILE_PATH, "wb+");
struct record r;
if (f) {
    if (fread((void *)&r, 1, sizeof(struct record), f) {
        /* File exists, do the normal flow */
    } else {
        if (feof(f)) {
            /* File is newly created, do some initialization */
        }
    }
} else {
    /* issue a warning */
}
4

3 に答える 3

6

存在しない可能性のあるファイルを 2 段階で処理する必要があります。最初にファイルがあると想定し、次にそのファイルがないことを処理します。

if ((f = fopen(filename, "rb+") == 0)
    f = fopen(filename, "wb+");
if (f == 0)
    ...report error...

この"rb+"モードでは、存在しないファイルを開くことはできません (ただし、それ以外の場合は、必要に応じて動作します)。ファイルが存在しない場合は、"wb+"代わりに必要なことを行います (ただし、ファイルが存在するが書き込み権限がない場合など、失敗する可能性があります)。2 回の試行で TOCTOU (Time of Check、Time of Use) 攻撃を受けていないことを祈る必要があります。

別のアプローチでは、3 引数バージョンのopen()システム コールと適切なフラグを使用してファイル ディスクリプタを開き、次に を使用fdopen()してファイル ディスクリプタからファイル ストリームを作成します。

#include <fcntl.h>

int fd;
if ((fd = open(filename, O_RDRW | O_CREAT, 0644)) >= 0)
    f = fdopen(fd, "rb+");

open()フラグを使用すると、かなり正確に制御できます。

于 2012-05-13T18:41:05.060 に答える
2

ファイルモードは明確に文書化されています( Unix/Linux/OS X でfopen試してください)。man 3 fopen

r+ 読み取りおよび書き込み用に開きます。ストリームはファイルの先頭に配置されます。

于 2012-05-13T18:04:25.980 に答える
-1

こんにちは、「w+」を使用して fseek で読み書きできます。私は小さなデモ プログラムを作成し、最初にデータをファイルに書き込み、fseek を使用して各データ間隔を数バイトにしてから読み取ります。

#include <stdio.h>
#include <unistd.h>

#define FILE_PATH "seek_test.txt"
#define STEP_SIZE 64

void set_data(FILE* fp)
{
    int i = 0;
    fseek(fp, 0, SEEK_SET);

    for ( ; i < 20; ++i)
    {
        fprintf(fp, "%d", i);
        fseek(fp, STEP_SIZE, SEEK_CUR);
    }
}

void get_data(FILE* fp)
{
    int i = 0;
    fseek(fp, 0, SEEK_SET);

    for ( ; i < 20; ++i)
    {
        fscanf(fp, "%d", &i);
        fprintf(stderr, "Cur Step: %5ld, value = %4d\n", i * STEP_SIZE, i);
        fseek(fp, STEP_SIZE, SEEK_CUR);
    }
}

int main(int argc, char* argv[])
{
    FILE* fp = fopen(FILE_PATH, "w+");
    if (fp == NULL)
    {
        printf("fopen Error\n");
        exit(0);
    }

    set_data(fp);
    get_data(fp);

    return 0;
}

=============================== 結果は次のようになります。

現在のステップ: 0、値 = 0

現在のステップ: 64、値 = 1

現在のステップ: 128、値 = 2

現在のステップ: 192、値 = 3

現在のステップ: 256、値 = 4

現在のステップ: 320、値 = 5

現在のステップ: 384、値 = 6

現在のステップ: 448、値 = 7

現在のステップ: 512、値 = 8

現在のステップ: 576、値 = 9

現在のステップ: 640、値 = 10

現在のステップ: 704、値 = 11

現在のステップ: 768、値 = 12

現在のステップ: 832、値 = 13

現在のステップ: 896、値 = 14

現在のステップ: 960、値 = 15

現在のステップ: 1024、値 = 16

現在のステップ: 1088、値 = 17

現在のステップ: 1152、値 = 18

現在のステップ: 1216、値 = 19

=============================

于 2012-05-14T06:21:38.197 に答える