【问题标题】:C binary files vs. ascii filesC 二进制文件与 ascii 文件
【发布时间】:2015-04-08 02:41:09
【问题描述】:

所以我是 C 的新手。我需要编写一个程序,将整数的二进制文件作为输入,用 malloc 分配一个足够大的数组,然后使用 read() c 函数将每个整数存储在二进制文件中文件在其在数组中的相应位置。我的问题是我不知道如何区分两者。当我打印出存储在这个分配的数组空间中的数据时,它只显示作为字符串的二进制数据的 Ascii 值。 因此,例如,如果我有二进制数 0000 0001,则位置 [0]-[7] 的数组将是该二进制数中每个位的每个 ascii 值。

基本上我试图读取每一行并将该行存储在 1 个数组位置中的二进制信息的 int 表示,因此与上面的示例一样,所需的结果将是: [0] - 1. 我需要做一些转换算法吗?我相信有一种方法可以让 c 识别它的二进制信息,而不是 ascii,因为有 2 种不同的文件类型:二进制和 ASCII。任何帮助将不胜感激,在此先感谢!

P.s 我只能使用这些函数调用:open、close、read、malloc、fstat、printf

else
    {
            fileDescriptor = open(argv[1], O_RDONLY, 0);
            if (fileDescriptor == -1){
                    printf("File Not Found\n");
                    exit(1);
            }
            else{
                    if (fstat(fileDescriptor, &fileStat) < 0){
                            printf("Trouble pulling statistics of file\n");
                            exit(1);
                    }
                    else
                    {
                            numBytes = fileStat.st_size;
                            filePointer = (char*)  malloc(numBytes);
                    n = read(fileDescriptor, filePointer, (numBytes * sizeof(int)));

                            if( n < 0 ){
                                    printf("Problem reading the file\n");
                                    exit(1);
                            }
                                    numerator = 0;
                                    numCount = 0;
                                    average = 0;

                                    while(*filePointer != NULL)
                                    {
                                    numerator += *filePointer;
                                    printf("data in array: %d\n", *filePointer);
                                    filePointer++;
                                    numCount++;
                                    }
                            average = (double) numerator / (double) numCount;
                            printf("Average: %f\n", average);

                            printf("Total Numbers: %d\n", numCount);
                    }
            }

【问题讨论】:

  • 你说你有一个二进制文件,然后谈到从文件中读取行。 “行”是一个文本概念,二进制文件没有行,只有二进制数据。您正在使用 POSIX(打开/读取)文件函数,它不区分文本和二进制文件 - 文件只是一个字节序列,您可以将这些字节视为二进制或 ASCII 文本或 UTF-8文本或其他任何内容。
  • 好的,这很有帮助。我只是很困惑,然后我应该如何逐步遍历我的 filePointer 变量指向的数组以获取相关信息。我打印出来,当我想要整数表示时,每个位置的数据仍然只是每个位的 ascii 值。在这种情况下,访问每个位置整数以计算平均值。 filePointer 是指向 char 类型的指针吗?
  • 你做了很多不必要的 else 缩进,这降低了代码的可读性。请注意,在所有 if 语句中,如果条件为真,则返回或退出,因此 else { 是不必要的。

标签: c binary


【解决方案1】:

您的 read() 可能会出错,因为您尝试读取 numBytes 整数,但整数不是字节。如果您正确检查了读取的返回值,您会看到文件不是 numBytes * sizeof(int) 大。如果文件确实包含整数,而不是 ASCII 数字字符串,那么您可以通过以下方式访问整数:

int *pInt= (int *)filePointer;
while (pInt < filePointer+numBytes) { printf("%d,", *pInt); pInt++;}

如果文件包含 ASCII 数字字符串,则需要一个分隔符来指示一个数字的结束位置和下一个数字的开始位置,并且可以写入:

char *s= filePointer;
while (s<filePointer+numBytes) {
    int num= 0;
    while (s<filePointer+numBytes && '0'<= *s && *s<='9') {
        num= num*10 + *s-'0';
        s++;
    }
    while (s<filePointer+numBytes && !('0'<= *s && *s<='9')) s++; // skip separator(s)
}

【讨论】:

  • 这很接近,它有很大的帮助!但现在它似乎无法处理负整数。一旦在内存位置旋转的指针命中负整数,while 循环条件就会评估,其余整数永远不会命中。从文件中读取的字节数是正确的,所以它必须在这里。在我的例子中,我有 13 个整数,所以 52 个字节,我打印出来检查,numBytes 实际上是 52。关于什么可能导致这个小故障的任何想法?非常感谢!
  • 我想通了,我不小心让 while 循环被指向的值控制,而不是指针本身
【解决方案2】:

如果您尝试从二进制文件(不是 ASCII 文件)中获取每个位并将其存储在一个数组中,那么您可以使用下面的代码来做到这一点。

如果您想了解更多关于 ASCII 和二进制文件的区别,请阅读帖子https://stackoverflow.com/a/28301127/3095460

ASCII 文件也是二进制文件,只是字符是用 ascii 字符集编码的,每个字符在内存中只占一个字节。例如,如果要将整数 10000 放入二进制文件中,它只需要 4 个字节(二进制中 int 的大小),但 ascii 文件需要 5 个字节。所以从 ascii 文件中读取 10000 将读取 5 个字节以获得 10000 并解码为整数,但二进制文件只需读取 4 个字节。

所以要读取二进制文件,您需要一个二进制文件编辑器。否则普通编辑器将解码二进制文件并显示我们肉眼无法理解的内容,直到您仔细查看字节。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(){

    int fd;
    char out;
    struct stat fileStat;
    int* binArray;
    int bin_size = 0, i = 0, j = 0;

    if( (fd = open("binfile",O_RDONLY)) != -1) {
        if ( fstat(fd, &fileStat) == 0 ){
            if (fileStat.st_size != 0 &&
                ( binArray = (int*) malloc( fileStat.st_size * 8 )) != NULL) {
                for(i = 0; i < fileStat.st_size; ++i) {
                    if( read(fd, &out, sizeof(char)) == 1 ) {
                        for(j = 7; j >= 0; --j) {
                            binArray[bin_size++] = (out >> j) & 0x01;
                            printf("%d",binArray[bin_size-1]);
                        }
                    }
                }
            }
            else {
                fprintf(stderr,"Trouble Allocating Memory\n");
            }
        }
        else {
           fprintf(stderr,"Trouble pulling statistics of file\n");
        }
    }
    else {
       fprintf(stderr,"Trouble Opening the File\n");
    }
    close(fd);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-02
    • 2018-10-04
    • 2015-03-13
    • 1970-01-01
    • 1970-01-01
    • 2013-01-15
    相关资源
    最近更新 更多