8

これが私の問題を解決するための最良の方法であるかどうか疑問に思っています。

必要な情報が保持されているバイナリファイルの特定のオフセットの値を知っています...私がやりたいのは、オフセットにジャンプして、その場所から開始して特定のバイト数を読み取ることです。

グーグルを使用した後、私の最善の策は、fseek()を使用してオフセットの位置に移動し、次にfread()を使用してその位置からバイト数を読み取ることであるという結論に達しました。

私はこれを考えるのは正しいですか?もしそうなら、どのようにそうするのが最善ですか?つまり、2つを一緒に組み込む方法。

私が正しくない場合、代わりに何を提案しますか?

よろしくお願いします。

マット

編集

fread()のチュートリアルに従い、次のように調整しました。

    `#include <stdio.h>
    int main()
    {
      FILE *f;
      char buffer[11];
      if (f = fopen("comm_array2.img", "rt"))
      {
        fread(buffer, 1, 10, f);
        buffer[10] = 0;
        fclose(f);
        printf("first 10 characters of the file:\n%s\n", buffer);
      }
      return 0;
    }`

そこで、ファイル'comm_array2.img'を使用して、ファイルから最初の10文字を読み取りました。

しかし、私が理解していることから、これはファイルの先頭から始まります。ファイル内のある場所(オフセット)から行きたいです。

これはもっと理にかなっていますか?

編集番号2:

私は少しぼんやりしていたようです、そして必要なのは(私の試みからはそう思われるでしょう)上記のコードにあるfread()の前にfseek()を置くことだけです、そしてそれはその場所を探します次に、そこから読み取ります。

4

3 に答える 3

3

ファイル記述子の代わりにファイルストリームを使用している場合は、POSIXpread()システムコールに類似した(単純な)関数を自分で作成できます。

ファイル記述子1の代わりにストリームを使用して簡単にエミュレートできます。おそらく、次のような関数を自分で作成する必要があります(コメントで提案したものとは少し異なるインターフェイスがあります)。

size_t fpread(void *buffer, size_t size, size_t mitems, size_t offset, FILE *fp)
{
     if (fseek(fp, offset, SEEK_SET) != 0)
         return 0;
     return fread(buffer, size, nitems, fp);
}

pread()これは、との規則の間の妥当な妥協点fread()です。


関数呼び出しの構文はどのようになりますか?たとえば、オフセット732から読み取り、次にオフセット432(両方ともファイルの先頭から)から読み取り、ファイルストリームは。と呼ばれfます。

何バイト読むかを言わなかったので、毎回100バイトと仮定します。ターゲット変数(バッファー)はとでbuffer1ありbuffer2、両方とも十分に大きいと想定しています。

if (fpread(buffer1, 100, 1, 732, f) != 1)
    ...error reading at offset 732...
if (fpread(buffer2, 100, 1, 432, f) != 1)
    ...error reading at offset 432...

戻りカウントは、それぞれ100バイトの完全なユニットの数です。1(すべてを取得)または0(何かがうまくいかなかった)のいずれか。

そのコードを書く他の方法があります:

if (fpread(buffer1, sizeof(char), 100, 732, f) != 100)
    ...error reading at offset 732...
if (fpread(buffer2, sizeof(char), 100, 432, f) != 100)
    ...error reading at offset 432...

これは毎回100シングルバイトを読み取ります。テストでは、予想どおり、100個すべてを取得したことを確認します。この2番目の例で戻り値を取得すると、取得したデータの量を知ることができます。最初の読み取りが成功し、2番目の読み取りが失敗した場合は非常に驚くでしょう。他のプログラム(またはスレッド)は、への2つの呼び出しの間にファイルを切り捨てる必要がありましたfpread()が、もっと面白いことが起こることが知られています。


1エミュレーションは完全ではありません。この呼び出しは、とpread()の組み合わせでは提供されない保証されたアトミック性を提供します。ただし、ファイルの配置と読み取りを試みているときにファイルを同時に更新する複数のプロセスまたはスレッドがない限り、これが実際に問題になることはめったにありません。fseek()fread()

于 2012-03-25T19:57:17.893 に答える
1

多くの場合、気になるパーツ間の距離に依存します。気になる部分の間の数バイトをスキップ/無視するだけの場合は、スキップしfseekてスキップするよりも、そのデータを読み取って、読み取った内容を無視する方が簡単な場合がよくあります。これを行う一般的な方法は、気になるデータと気にしないデータのプレースホルダーの両方を保持する構造体を定義し、構造体を読み込んでから、気になる部分を使用することです。

struct whatever {
   long a;
   long ignore;
   short b;
} w;

fread(&w, 1, sizeof(w), some_file);

// use 'w.a' and 'w.b' here.

ただし、気になる部分の間に大きな距離がある場合は、fseek重要な部分に到達するために使用するという元のアイデアがより単純になる可能性があります。

于 2012-03-25T18:45:48.763 に答える
0

あなたの理論は正しいように聞こえます。開く、探す、読む、閉じる。

読み取りたいデータの構造体を作成し、構造体に割り当てられたメモリのread()へのポインタを渡します。ミスアライメントの問題を防ぐために、構造体に#pragma pack(1)などが必要になる可能性があります。

于 2012-03-25T18:32:56.033 に答える