从 .dat 二进制文件中读取数据

Reading data from a .dat binary file

我有一个 .dat 文件需要读取并为人们打印记录 具有指定为命令行参数的属性。文件格式如下。每个人的记录都以一个无符号的 32 位整数开头,其中包含有关此人的各种信息:

位数

0-4 : 名字的长度 (key=first)

5-9 : 中间名的长度 (key=middle)

10-14 : 姓氏的长度 (key=last)

15-21 岁:年龄(关键=年龄)

22:性别(0=男,1=女)(键=性别)

23-28 : state (0 to 49 in alphabet order) (key=state)

29 : 目前已婚 (0=false, 1=true) (key=married)

30 : 全职工作 (0=false, 1=true) (key=employed)

31 : 上过大学 (0=false, 1=true) (key=college)

我想我应该先读取整个 32 位(4 个字节),然后从 32 位整数中逐位读取。我是 fread 和 fseek 的新手,所以我真的不知道我是否在正确的轨道上,我们将不胜感激。到目前为止,这是我的代码。

  int main(int argc, char *argv[]) {

  char *buf;
  long lSize;
  size_t result;

  FILE *fp;
  fp = fopen("/u1/junk/people.dat","r");
  if(fp == NULL) {
    printf("Error: can't open file to read\n");
    return -1;
  }
  else {
    printf("File people.dat opened successfully to read\n");
  }


  //obtian file size
  fseek(fp, 0, SEEK_END);
  lSize = ftell(fp);
  rewind(fp);

  //allocate memory to contain the whole file
  buf = (char*) malloc (sizeof(char)*lSize);

  while (!feof(fp)) {
    fread(buf, 4, 1, fp);
    fseek(fp, i, SEEK_CUR);
    fread(buf, 32, 1, fp);
    printf("%s\n", buf);
    i+=32;
  }

  fclose(fp);
  return 0;  
}

这是未经测试的,但希望能让您了解 "mask and shift" 技术。您可以阅读更多相关信息: What are bitwise shift (bit-shift) operators and how do they work?Bitfield manipulation in C

假设您读取了无符号 32 位整数:

unsigned long myint;
fread(&myint, sizeof(myint), 1, fid);

现在,shift 和 mask 以提取值。

// bits 0-4 (5 bits)
unsigned long firstNameLength = myint & 0xF1;

// bit 31
unsigned long attendedCollege = (myint & 0x0000000E) << 31;
#include <stdio.h>

// define first 32 bits of record
struct personRecord
{
    unsigned first    :5;
    unsigned middle   :5;
    unsigned last     :5;
    unsigned age      :7;
    unsigned sex      :1;
    unsigned state    :6;
    unsigned married  :1;
    unsigned employed :1;
    unsigned college  :1;
};

// prototypes
void processRecord(FILE* fp, char* buf);


int main(int argc, char *argv[])
{

    struct personRecord key;

    FILE *fp;
    fp = fopen("/u1/junk/people.dat","r");
    if(fp == NULL)
    {
        printf("Error: can't open file to read\n");
        return -1;
    }

    // implied else, fopen successful

    printf("File people.dat opened successfully to read\n");



    while ( 1 == fread( &key, 4, 1, fp ) )
    {
        processRecord(fp, key);
    }

    fclose(fp);
    return 0;
} // end function: main



void processRecord(FILE* fp, personRecord key)
{
      int result;
      int bufFirst[key.first] = {'[=10=]'};
      ...

      // use  lengths to determine how much more  bytes to read for each field
      result = fread( bufFirst, key.first, 1, fp );
      if ( result == key.first )
      { // then successful acquire first name
          ...
      }
      ...
      // first, middle, last,

      // use lookup table to get state name from state field
      char * pState = alphabeticalState[key.state];

      // do something with the extracted info
      ...
} // end function: processRecord


const char * alphabeticalStates[] =
{
    "alabama";
    ...
    "washington";
    "wisconsin";
};