簡體   English   中英

二進制到文本錯誤糾正

[英]Binary to textual error Correction

我一直在研究一個程序,該程序從學生的二進制文件對象讀取並將其寫入文本文件,但是使用的二進制文件也可以通過從文本文件讀取學生的數據來獲得。 我這樣做有兩個功能,文本到二進制的工作正常,但二進制到文本仍然給我錯誤,我不知道為什么。

那是我的代碼:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 typedef struct a {
 char name[15];
 char surname[15];
int age;
}sID; 

int Binarycopy(char *s1,char *s2)     
{
sID id;
  FILE *f;
  FILE *g;
  char names[15];
  char surnames[15];
  int age;

  f=fopen(s1,"r");
  g=fopen(s2,"wb");// text file giving data about students, gathering them      into a data type structure and then write them in a binary file.


  if(f==NULL)
  { printf("File is empty");
      return -1;
  }
  fscanf(f,"%s %s %d",names,surnames,&age);

  while(!feof(f)){

      strcpy(names,id.name);
      strcpy(surnames,id.surname);
      id.age=age;                //write data into the ID object

      fwrite(&id,sizeof(sID),1,g); //write the ID object inside g

      fscanf(f,"%s %s %d",names,surnames,&age);
  }

  fclose(g);
  fclose(f);

  return 1;
}


 int Textcopy(char *s1,char *s2) 
{
sID id;
FILE *f;
FILE *g;

f=fopen(s1,"rb");
g=fopen(s2,"w");

if(fread(&id,sizeof(sID),1,f)!=sizeof(sID))
{ printf("file is empty");
    return -1;
}
else
    while(1)
    { fprintf(g,"%s %s %d",id.name,id.surname,id.age);

    if(fread(&id,sizeof(sID),1,f)!=sizeof(sID))
    { 
        fclose(f);
            fclose(g);
        return 1;
    }}}

  int main(int argc, char *argv[])
 {
   char b[]={"-b"};
   char t[]={"-t"};
   if(argc<4)
   { printf("Not enough arguments");
       return -1;}

   if(strcmp(argv[1],b)==0)
    Binarycopy(argv[2],argv[3]);

   if(strcmp(argv[1],t)==0)
    Textcopy(argv[2],argv[3]);

   return 1;
  }

嘗試從二進制文件寫入文本文件時出現“文件為空”的情況,即使我的二進制文件不為空,我仍然不知道為什么

驗證存在許多問題,這些問題會阻止檢測何時出現文件打開,文件讀取,文件寫入和文件關閉錯誤。 在到達那里之前,如果需要常量,請#define常量或使用enum定義它們,例如

enum { NAMSZ = 15, MAXC = 512 };

(這樣一來,您就不會在代碼中散布魔術數字注意: scanf 字段寬度修飾符是一個例外-必須指定它們,並且不能使用變量或常量標簽)

無需將typedef struct a {...聲明typedef struct a {... ,您不必使用a ,而只需使用struct的typedef

typedef struct {
    char name[NAMSZ];
    char surname[NAMSZ];
    int age;
} sid;

我給您提供了鏈接, 為什么while(!feof(file))總是錯誤? 相反,聲明一個足以容納每一行並使用fgets讀取每一行的緩沖區,然后使用sscanf (或只是指針和循環)從該行中解析所需的值,例如

int binarycopy (char *s1, char *s2)
{
    sid id = { .name = "" };
    FILE *f, *g;
    char buf[MAXC] = "";

    f = fopen (s1, "r");
    g = fopen (s2, "wb");

    if (f == NULL || g == NULL) {
        fprintf (stderr, "binarycopy: file open failed.\n");
        exit (EXIT_FAILURE);
    }

    while (fgets (buf, MAXC, f)) {
        if (sscanf (buf, "%14s %14s %d", id.name, id.surname, &id.age) == 3) {
            if (fwrite (&id, sizeof id, 1, g) != 1) {
                fprintf (stderr, "error: fwrite error.\n");
                exit (EXIT_FAILURE);
            }
        }
        else {
            fprintf (stderr, "binarycopy error: invalid line format.\n");
            exit (EXIT_FAILURE);
        }
    }

    fclose (f);
    if (fclose (g) == -1) {
        fprintf (stderr, "error: on stream close.\n");
        exit (EXIT_FAILURE);
    }

    return 1;
}

注意: 后對fclose進行驗證。可能會發生流錯誤,否則不會報告此錯誤。始終在寫后對fclose進行驗證)

雖然您應該序列化寫入上述二進制文件的數據(例如,檢查每個名稱的strlen ,寫入長度,然后輸入的字符數和使用期限,出於學習目的,您可以編寫一個struct-at-a-時間,但請注意:由於填充方面的差異,不能保證數據文件可以在其他體系結構或編譯器上工作。您可以在同一編譯器上編寫並讀取結構,但是知道序列化數據是正確的方法。

供您閱讀,只需執行相反的操作即可。 fread一個struct數據的價值,並寫出一行到文本文件,如

int textcopy (char *s1, char *s2)
{
    sid id;
    FILE *f;
    FILE *g;

    f = fopen (s1, "rb");
    g = fopen (s2, "w");

    if (f == NULL || g == NULL) {
        fprintf (stderr, "textcopy: file open failed.\n");
        exit (EXIT_FAILURE);
    }

    while (fread (&id, sizeof id, 1, f) == 1)
        fprintf (g, "%s %s %d\n", id.name, id.surname, id.age);

    fclose (f);
    if (fclose (g) == -1) {
        fprintf (stderr, "error: on stream close.\n");
        exit (EXIT_FAILURE);
    }

    return 1;
}

main()驗證您的選項。 如果沒有得到-b-t處理錯誤。 另外,也不需要使用strcmp ,只需檢查argv[1]的第二個字符(例如argv[1][1] )是否為'b''t' ,例如

int main (int argc, char *argv[])
{
    if (argc < 4) {
        printf ("Not enough arguments");
        return 1;
    }

    if (argv[1][1] == 'b')
        binarycopy (argv[2], argv[3]);
    else if (argv[1][1] == 't')
        textcopy (argv[2], argv[3]);
    else
        fprintf (stderr, "error: unrecognized option.\n");

    return 0;
}

綜上所述,您可以執行以下操作:

#include <stdio.h>
#include <stdlib.h>

enum { NAMSZ = 15, MAXC = 512 };

typedef struct {
    char name[NAMSZ];
    char surname[NAMSZ];
    int age;
} sid;

int binarycopy (char *s1, char *s2)
{
    sid id = { .name = "" };
    FILE *f, *g;
    char buf[MAXC] = "";

    f = fopen (s1, "r");
    g = fopen (s2, "wb");

    if (f == NULL || g == NULL) {
        fprintf (stderr, "binarycopy: file open failed.\n");
        exit (EXIT_FAILURE);
    }

    while (fgets (buf, MAXC, f)) {
        if (sscanf (buf, "%14s %14s %d", id.name, id.surname, &id.age) == 3) {
            if (fwrite (&id, sizeof id, 1, g) != 1) {
                fprintf (stderr, "error: fwrite error.\n");
                exit (EXIT_FAILURE);
            }
        }
        else {
            fprintf (stderr, "binarycopy error: invalid line format.\n");
            exit (EXIT_FAILURE);
        }
    }

    fclose (f);
    if (fclose (g) == -1) {
        fprintf (stderr, "error: on stream close.\n");
        exit (EXIT_FAILURE);
    }

    return 1;
}


int textcopy (char *s1, char *s2)
{
    sid id;
    FILE *f;
    FILE *g;

    f = fopen (s1, "rb");
    g = fopen (s2, "w");

    if (f == NULL || g == NULL) {
        fprintf (stderr, "textcopy: file open failed.\n");
        exit (EXIT_FAILURE);
    }

    while (fread (&id, sizeof id, 1, f) == 1)
        fprintf (g, "%s %s %d\n", id.name, id.surname, id.age);

    fclose (f);
    if (fclose (g) == -1) {
        fprintf (stderr, "error: on stream close.\n");
        exit (EXIT_FAILURE);
    }

    return 1;
}

int main (int argc, char *argv[])
{
    if (argc < 4) {
        printf ("Not enough arguments");
        return 1;
    }

    if (argv[1][1] == 'b')
        binarycopy (argv[2], argv[3]);
    else if (argv[1][1] == 't')
        textcopy (argv[2], argv[3]);
    else
        fprintf (stderr, "error: unrecognized option.\n");

    return 0;
}

輸入文件示例

$ cat dat/nameage.txt
John Smith 30
Mary Jane 35
Dan Kane 55
Annie Adams 40

使用/輸出示例

復制到二進制文件:

$ ./bin/filecopytb -b dat/nameage.txt dat/nameagecpy.bin

復制到文本:

$ ./bin/filecopytb -t dat/nameagecpy.bin dat/nameagecpy.txt

相比:

$ diff dat/nameage.txt dat/nameagecpy.txt

二進制文件的十六進制轉儲:

$ hexdump -Cv dat/nameagecpy.bin
00000000  4a 6f 68 6e 00 00 00 00  00 00 00 00 00 00 00 53  |John...........S|
00000010  6d 69 74 68 00 00 00 00  00 00 00 00 00 00 00 00  |mith............|
00000020  1e 00 00 00 4d 61 72 79  00 00 00 00 00 00 00 00  |....Mary........|
00000030  00 00 00 4a 61 6e 65 00  00 00 00 00 00 00 00 00  |...Jane.........|
00000040  00 00 00 00 23 00 00 00  44 61 6e 00 00 00 00 00  |....#...Dan.....|
00000050  00 00 00 00 00 00 00 4b  61 6e 65 00 00 00 00 00  |.......Kane.....|
00000060  00 00 00 00 00 00 00 00  37 00 00 00 41 6e 6e 69  |........7...Anni|
00000070  65 00 00 00 00 00 00 00  00 00 00 41 64 61 6d 73  |e..........Adams|
00000080  00 00 00 00 00 00 00 00  00 00 00 00 28 00 00 00  |............(...|

文字貓:

$ cat dat/nameagecpy.txt
John Smith 30
Mary Jane 35
Dan Kane 55
Annie Adams 40

仔細檢查一下,如果您還有其他問題,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM