⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbf2ascii.c

📁 应用平台 UNIX 一个转换DBF数据库文件的数据到ASCII文本文件的Shell程序.这个包含SCO UNIX下的目标程序和C源程序.
💻 C
字号:
/* * A simple DBF-To-Ascii converter * * A DBF file is read. On output, the first line contains the field * headers, the second line contains the data format for each field, * and the following lines contain a record each. * * For the DBF format, see http://www.wotsit.demon.co.uk/ * * Frank Pilhofer <fp@fpx.de> */#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>/* * macros to extract short/long integers from character arrays. In * the DBF structure, multi-byte integers are not always aligned. * We assume LSB first (Little Endian, used on the i386). */#define GETSHORT(c) (((short)((unsigned char *)c)[0])|(((short)((unsigned char *)c)[1])<<8))#define GETLONG(c)  ((int)GETSHORT(c)|(int)(GETSHORT(c+2)<<16))char delimiter[256] = "\t";char copyfields[256];/* * field description */typedef struct _dbf_field {  char name[12];  int  type;  int  length;  int  dcount;  union {    int  deleted;    char *string;    char date[9];    int  logical;    long integer;  } data;  struct _dbf_field *next;} dbf_field;/* * Database description */typedef struct {  unsigned char type;  struct {    unsigned char yy;    unsigned char mm;    unsigned char dd;  } lastmod;  unsigned long numrecs;  unsigned short hsize;  unsigned short rsize;  dbf_field *fields;} dbf;/* * trucate a character field - remove whitespace */char *truncfield (char *data){  char *x=data, *y=data, *z;  while (*y && isspace(*y)) y++;  while (*y) {    while (*y && !isspace(*y)) *x++ = *y++;  z=x;    while (*y && isspace(*y))  *x++ = *y++;  if (!*y) x=z;  }  *x = *y;  return data;}/* * kill a linked list of fields */voidkillfields (dbf_field *fields){  dbf_field *next;  while (fields) {    switch (fields->type) {    case 'C':    case 'F':    case 'N':      free (fields->data.string);      break;    }    next = fields->next;    free (fields);    fields = next;  }}voidkilldbf (dbf * db){  if (db) {    killfields (db->fields);    free (db);  }}/* * read fields from dbf file */dbf_field *getfields (FILE *input){  dbf_field *head=NULL, *tail=NULL, *item;  char desc[32];  int c;  while (42) {    if ((desc[0] = fgetc (input)) == 0x0d)      break;    if (feof (input)) {      fprintf    (stderr, "error: unexpected EOF while reading header\n");      killfields (head);      return NULL;    }    if (fread (desc+1, 1, 31, input) < 31) {      fprintf    (stderr, "error: unexpected EOF while reading header\n");      killfields (head);      return NULL;    }    if ((item = (dbf_field *) malloc (sizeof (dbf_field))) == NULL) {      fprintf (stderr, "error: could not allocate field data\n");      killfields (head);      return NULL;    }    strncpy (item->name, desc, 11);    item->name[11] = '\0';    item->type     = desc[11];    item->length   = (int) desc[16];    item->dcount   = (int) desc[17];    item->next     = NULL;    truncfield (item->name);    switch (item->type) {    case 'C':    case 'F':    case 'N':      if ((item->data.string = (char *) malloc (item->length+1)) == NULL) {	fprintf (stderr, "error: could not allocate field data\n");	killfields (head);	free (item);	return NULL;      }      break;    case 'D':    case 'L':    case 'I': /* Visual FoxPro: 32bit Integer, LSB First */      break;    default: /* going to be ignored */      break;    }    if (head == NULL) {      head = tail = item;    }    else {      tail->next = item;      tail = tail->next;    }  }  /*   * should be terminated by a null byte   */  if ((c = fgetc (input)) != 0) {    ungetc (c, input);  }  return head;}dbf *getdbf (FILE *input){  unsigned char dbfheader[32];  dbf * db;  if ((db = (dbf *) malloc (sizeof (dbf))) == NULL) {    fprintf (stderr, "error: could not allocate database info structure\n");    return NULL;  }  if (fread (dbfheader, 1, 32, input) < 32) {    fprintf (stderr, "error: could not read DBF header\n");    free (db);    return NULL;  }  db->type       = dbfheader[0];  db->lastmod.yy = dbfheader[1];  db->lastmod.mm = dbfheader[2];  db->lastmod.dd = dbfheader[3];  db->numrecs    = GETLONG(dbfheader+4);  db->hsize      = GETSHORT(dbfheader+8);  db->rsize      = GETSHORT(dbfheader+10);  /*   * sensibility check: test day and month   */  if (db->lastmod.mm < 1 || db->lastmod.mm > 12 ||      db->lastmod.dd < 1 || db->lastmod.dd > 31) {    fprintf (stderr, "error: this does not look like a DBF file\n");    free (db);    return NULL;  }  /*   * encrypted flag   */  if (dbfheader[15] != 0) {    fprintf (stderr, "error: encrypted DBF file\n");    free (db);    return NULL;  }  if ((db->fields = getfields (input)) == NULL) {    free (db);    return NULL;  }  fseek (input, db->hsize, SEEK_SET);  return db;}/* * check that all requested fields are printable */voidcheckfields (FILE *output, dbf_field *iter){  int count=1;  while (iter) {    if (copyfields[count]) {      switch (iter->type) {      case 'C':      case 'D':      case 'F':      case 'N':      case 'L':      case 'I':	break;            default:	fprintf (stderr, "warning: can't handle field `%s' type `%c' (ignored)\n",		 iter->name, iter->type);	copyfields[count] = 0;	break;      }    }    iter = iter->next;    count++;  }}/* * show titles of fields */voidshowtitle (FILE *output, dbf_field *iter, int deleted){  int count=1, flag=0;  if (deleted) {    fprintf (output, "del");    flag++;  }  while (iter) {    if (copyfields[count++]) {      fprintf (output, "%s%s", (flag++)?delimiter:"", iter->name);    }    iter = iter->next;  }  fprintf (output, "\n");}voidshowtypes (FILE *output, dbf_field *iter, int deleted){  int count=1, flag=0;  if (deleted) {    fprintf (output, "C1");    flag++;  }  while (iter) {    if (copyfields[count++]) {      fprintf (output, "%s", (flag++)?delimiter:"");      switch (iter->type) {      case 'C': fprintf (output, "C%d",    iter->length); break;      case 'D': fprintf (output, "D");                    break;      case 'F': fprintf (output, "F%d",    iter->length); break;      case 'N': fprintf (output, "N%d.%d", iter->length, iter->dcount); break;      case 'L': fprintf (output, "L");                    break;      case 'I': fprintf (output, "I");                    break;      default:  fprintf (output, "%c", iter->type);       break;      }    }    iter = iter->next;  }  fprintf (output, "\n");}/* * read a record */intreadrecord (FILE *input, dbf_field *iter, int dotrunc){  int deleted=0;  char temp[4];  int c, i;  if ((c = fgetc (input)) == 0x1a)    return -1;  if (feof (input))    return -1;  if (c == '*')    deleted = 1;  while (iter) {    switch (iter->type) {    case 'C':    case 'F':    case 'N':      if ((fread (iter->data.string, 1, iter->length, input)) < iter->length)	return -2;      iter->data.string[iter->length] = '\0';      if (dotrunc) truncfield (iter->data.string);      break;    case 'D':      if ((fread (iter->data.date, 1, 8, input)) < 8)	return -2;      iter->data.date[8] = '\0';      if (dotrunc) truncfield (iter->data.date);      break;    case 'L':      c = fgetc (input);      if (feof (input))	return -2;      switch (c) {      case 'Y': case 'y': case 'T': case 't': iter->data.logical = 'T'; break;      case 'N': case 'n': case 'F': case 'f': iter->data.logical = 'F'; break;      default:                                iter->data.logical = '?'; break;      }      break;    case 'I':      if ((fread (temp, 1, 4, input)) < 4)	return -2;      if (GETLONG(temp) < 0) {         iter->data.integer = GETLONG(temp);      }      iter->data.integer = GETLONG(temp);      break;    default: /* just flush */      for (i=0; i<iter->length && !feof (input); i++)	c = fgetc (input);      if (feof (input))	return -2;      break;    }    iter = iter->next;  }  return deleted;}voiddumprecord (FILE *output, dbf_field *iter, int deleted, int isdel, int dotrunc){  int count=1, flag=0;  if (deleted) {    fprintf (output, "%s", (isdel) ? "*" : ((dotrunc) ? "" : " "));    flag++;  }  while (iter) {    if (copyfields[count++]) {      fprintf (output, "%s", (flag++)?delimiter:"");      switch (iter->type) {      case 'C':      case 'F':      case 'N':	fprintf (output, "%s", iter->data.string);	break;	      case 'D':	fprintf (output, "%s", iter->data.date);	break;	      case 'L':	fprintf (output, "%c", iter->data.logical);	break;      case 'I':	fprintf (output, "%ld", iter->data.integer);	break;      default:	break;      }    }    iter = iter->next;  }  fprintf (output, "\n");}intmain (int argc, char *argv[]){  int c, dotrunc=0, deleted=0, title=0, types=0, count, left, right;  FILE *infile=stdin;  char *blah;  dbf *db;  optarg = NULL;  memset (copyfields, 1, 256);  while ((c = getopt (argc, argv, "s:tdnf:ph")) != -1) {    switch (c) {    case 's':      strcpy (delimiter, optarg);      break;    case 'f':      memset (copyfields, 0, 256);      blah = optarg;      if (*blah == '-') {	right = atoi (++blah);	for (count=1; count<=right; count++)	  copyfields[count] = 1;	while (isdigit(*blah)) blah++;	while (*blah == ',')   blah++;      }      while (isdigit(*blah)) {	left = atoi (blah);	while (isdigit(*blah)) blah++;	if (*blah=='-') {	  right = atoi(++blah);	  for (count=left; count<=right; count++)	    copyfields[count] = 1;	  while (isdigit(*blah)) blah++;	}	else {	  copyfields[left] = 1;	}	while (*blah == ',') blah++;      }      break;    case 't':      dotrunc=1;      break;    case 'd':      deleted=1;      break;    case 'n':      title=1;      break;    case 'p':      types=1;      break;    case 'h':    default:      fprintf (stderr, "usage: dbf2ascii [-s separator] [-t] [-p] [-d] [-n] [-flist] file\n");      return 1;    }  }  if (optind < argc && argv[optind][0] != '-') {    if ((infile = fopen (argv[optind], "r")) == NULL) {      fprintf (stderr, "error: cannot open `%s'\n", argv[optind]);      return 6;    }  }  if ((db = getdbf (infile)) == NULL) {    return 2;  }  checkfields (stdout, db->fields);  if (title) {    showtitle (stdout, db->fields, deleted);  }  if (types) {    showtypes (stdout, db->fields, deleted);  }  for (count=1; ; count++) {    if ((c = readrecord (infile, db->fields, dotrunc)) == -1)      break;    if (c == -2) {      fprintf (stderr, "error: unexpected EOF while reading record %d\n",	       count);      return 5;    }    if (c == 0 || deleted) {      dumprecord (stdout, db->fields, deleted, c, dotrunc);    }  }  /*   * done   */  if (optind < argc && argv[optind][0] != '-') {    fclose (infile);  }  killdbf (db);  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -