10

私は以下の機能を知っています:

size_t fread(void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);

バイト単位でのみ読み取ります。私の目標は、一度に 12 ビットを読み取り、それらを配列に取り込むことです。どんな助けや指針も大歓迎です!

4

6 に答える 6

7

最初のコメントに追加すると、一度に 1 バイトずつ読み取って (char 変数を宣言してそこに書き込む)、ビットごとの演算子 >> と << を使用してビットごとに読み取ることができます。詳細はこちら: http://www.cprogramming.com/tutorial/bitwise_operators.html

于 2012-07-27T01:24:50.223 に答える
3

何年も前に、ハフマン エンコーダー用にいくつかの I/O ルーチンを C で書きました。これは、バイト単位ではなくビット単位で読み書きできる必要があります。私は read(2) と write(2) に似た関数を作成しました。これは、ストリームから 13 ビットを読み取る (たとえば) ように要求される可能性があります。たとえば、エンコードするには、バイトがコーダーに供給され、可変数のビットが反対側に現れます。読み取りまたは書き込み中の現在のバイトへのビットポインターを持つ単純な構造がありました。終了するたびに、完了したバイトをフラッシュし、ポインターをゼロにリセットしました。残念ながら、そのコードはとうの昔になくなってしまいましたが、オープン ソースのハフマン コーダーを分解して、そこで問題がどのように解決されたかを確認するのはよい考えかもしれません。同様に、base64 コーディングは 3 バイトのデータを取り、それらを 4 に変換します (またはその逆)。

于 2012-07-27T03:59:47.680 に答える
3

ファイルを少しずつ読み書きする方法をいくつか実装しました。ここにあります。ユースケースで実行可能かどうかに関係なく、自分で決定する必要があります。私は (今のところ) ベテランの C 開発者ではありませんが、できる限り読みやすく最適化されたコードを作成しようとしました。

内部的には、「bitCursor」を使用して、まだ完全なバイトに収まらない前のビットに関する情報を格納します。who データ フィールドがあります。dはデータを格納し、sはサイズ、またはカーソルに格納されているビット数を格納します。

次の 4 つの機能があります。

  • newBitCursor () は、デフォルト値
    {0,0} を持つ bitCursor オブジェクトを返します。このようなカーソルは、ファイルへの、またはファイルからの一連の読み取り/書き込み操作の開始時に必要です。
  • fwriteb (void *ptr, size_t sizeb, size_t rSizeb, FILE *fp, bitCursor *c) は、ptr に格納されている値の右端 sizeb ビットを fp に書き込みます。
  • fcloseb (FILE *fp, bitCursor *c) は、残りのバイトを書き込みます。以前の書き込みで、書き込む必要のあるすべてのデータが正確にカプセル化されていなかった場合は、おそらくほとんどの場合に当てはまります...
  • freadb (void *ptr, size_t sizeb, size_t rSizeb, FILE *fp, bitCursor *c) は、sizeb ビットを読み取り、それらをビットごとにORして *ptr にします。(したがって、 *ptr を0として初期化するのはあなたの責任です)

詳細については、コメントを参照してください。楽しんで!

編集:私がそれを作ったとき、私はリトルエンディアンを想定していたことを今日知りました!:P おっと!私がまだどれだけ初心者であるかを理解するのはいつでもいいことです;D.

編集: GNU の Binary File Descriptors

于 2016-03-30T19:30:22.980 に答える
2

ファイル ポインターから最初の 2 バイトを読み取り、ビットシフト演算子を使用して、プラットフォームのエンディアン(x86 はリトルエンディアン) にa_file応じて、最小バイトまたは最大バイトのビットをチェックします。

ビットにはデータ型がないため、実際にはビットを配列に入れることはできません。非効率な配列に 1 と 0 を保持するよりも、2 バイトを 2 要素の配列 (たとえば、 型unsigned char *) に保持し、それらの 2 バイトを 4096 (2^ 12) 関心のある値。

fread複雑なことに、後続の読み取りで、 12 ビットごとにポインターを通過させたい場合は、前の読み取りの残りのビットを使用して新しい 12 ビット値を構築し、1バイトだけを読み取ることになります。残りがない場合は、2 バイトを読み取る必要があります。

マッピング関数は、前の読み取りからビットが使用された 2 番目のケースに対処する必要があります。これは、2 バイトが異なるマッピングを必要とするためです。これを効率的に行うには、読み取りカウンターのモジュラスを使用して 2 つのマッピングを交換します。

于 2012-07-27T01:36:15.893 に答える
1

2バイトを読み取り、ビット単位の演算を実行すると、次に2バイト目を読み取るときに実行されます。ビット単位の演算を適用すると、期待どおりに戻ります。。。。

于 2012-07-27T04:27:37.980 に答える
0

あなたの問題については、2 バイトを読み取るこのデモ プログラムを見ることができますが、実際の情報は 12 ビットのみです。

fwrite() は、サイズ引数をバイトとして取り、int型の標準ライブラリ関数です。したがって、正確に12ビットを読み取ることはできません。作成したファイルを以下のように作成し、以下のように読み取ると、問題が解決します。

そのファイルがあなたによって書かれていない特別なファイルである場合は、そのファイルに提供されている標準に従って読み取ることができます。

#include<stdio.h>
#include<stdlib.h>
struct node
 {
   int data:12;

 }NODE;
int main()
{
   FILE *fp;
   fp=fopen("t","w");
   NODE.data=1024;
   printf("%d\n",NODE.data);
   fwrite(&NODE,sizeof(NODE),1,fp);
   NODE.data=0;
   NODE.data=2048;
   printf("%d\n",(unsigned)NODE.data);
   fwrite(&NODE,sizeof(NODE),1,fp);
   fclose(fp);
   fp=fopen("t","r");
   fread(&NODE,sizeof(NODE),1,fp);
   printf("%d\n",NODE.data);
   fread(&NODE,sizeof(NODE),1,fp);
   printf("%d\n",NODE.data);
   fclose(fp);
}
于 2012-07-28T12:15:17.150 に答える