C fopen和fgets返回奇怪的字符而不是文件内容

时间:2016-06-24 18:30:42

标签: c io fopen fgets cs50

我正在进行编码练习,我需要打开一个包含大量数据的数据文件。这是一个.raw文件。在构建我的应用程序之前,我在texteditor和hexeditor中打开'card.raw'文件。如果你在textEdit中打开它,你会看到'bit.ly/18gECvyÿÿJFIFHH€C€C¿Vƒ'作为第一行。 (该网址指的是Rick Roll作为教授的一个笑话。)

所以我开始构建我的应用程序以打开相同的'card.raw'文件。我正在做初步检查,看到应用程序打印到控制台时与我用TextEdit打开它时的“东西”相同。而不是打印出来,我看到当我用TextEdit打开它时(参见上面的文字),它启动并继续打印出如下所示的文本:

\ 377 \ 304'i \ 204 \ 206 \ 226 \ 262 \ 302 \ 3227 \ 205 \ 246 \ 266 \ 342GSc \ 224 \ 225 \ 245 \ 265 \ 305 \ 306 \ 325 \ 326Wgs \ 244 \ 346(瓦特\ 345 \ 362 \ 366 \ 207 \ 264 \ 304! \ 223 \ 227 \ 2678H \ 247 \ 250 \ 343 \ 344 \ 365 \ 377 \ 304

现在我不知道调用'\'和数字是什么(我要搜索什么来阅读更多内容?),为什么它打印而不是我在TextEdit中打开时看到的字符(unicode?),或者如果我可以将此输出转换为十六进制或unicode。

我的代码是:

    #include <stdio.h>
    #include <string.h>
    #include <limits.h>

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

        FILE* file;

        file = fopen("/Users/jamesgoldstein/CS50/CS50Week4/CS50Recovery/CS50Recovery/CS50Recovery/card.raw", "r");

        char output[LINE_MAX];

        if (file != NULL)
        {
            for (int i = 1; fgets(output, LINE_MAX, file) != NULL; i++)
            {
                printf("%s\n", output);
            }
        }

        fclose(file);

        return 0;
    }

更新&amp;简化代码使用fread()

#include <stdio.h>
#include <string.h>

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

    FILE* fp = fopen("/Users/jamesgoldstein/CS50/CS50Week4/CS50Recovery/CS50Recovery/CS50Recovery/card.raw", "rb");

    char output[256];

    if (fp == NULL)
    {
        printf("Bad input\n");
        return 1;
    }

    for (int i = 1; fread(output, sizeof(output), 1, fp) != NULL; i++)
    {
        printf("%s\n", output);
    }

    fclose(fp);

    return 0;
}

输出部分正确(这是开头的片段):

bit.ly/18gECvy

\ 377 \ 330 \ 377 \ 340 \ 221 \ 241 \ 26145 \ 301 \ 321 \ 341“#&amp; 23DE \ 3616BFRTUe \ 202CVbdfrtv \ 222 \ 242 “U \ 204 \ 206 \ 226 \ 262 \ 302 \ 3227 \ 205 \ 246 \ 266 \ 342GSc \ 224 \ 225 \ 245 \ 265 \ 305 \ 306 \ 325 \ 326Wgs \ 244 \ 346(W \ 345 \ 362 \ 366 \ 207 \ 264 \ 304! \ 223 \ 227 \ 2678H \ 247 \ 250 \ 343 \ 344 \ 365 \ 377 \ 304 = \ 311 \ 345 \ 264 \ 352 \ 354 7 \ 222 \ 315 \ 306 \ 324 + \ 342 \ 364 \ 273 \ 274 \ 205 $ z \ 262 \ 313g- \ 343wl \ 306 \ 375My:} \ 242o \ 210 \ 377 3(\266升\ 356 \ 307T饢“2 \ 377 \ 267 \212ǑP\ 2218 \ 344

开头的实际card.raw文件片段

bit.ly/18gECvyÿÿJFIFHH€C€C *** ƒÖ
    !1AQa$%qÅë°±45° - “#&amp;23DEÒ6BFRTUeÇCVbdfrtví¢

3 个答案:

答案 0 :(得分:2)

我认为您应该以模式"rb"打开.raw文件。 然后使用fread()

答案 1 :(得分:1)

您应该使用fread而不是fgets,因为后者实际上是为阅读文本文件而设计的,而这显然不是文本文件。

您的更新代码实际上确实存在我最初撰写的问题(但已经收回),因为您现在使用fread而不是fgets

for (int i = 1; fread(output, sizeof(output), 1, fp) != NULL; i++)
{
    printf("%s\n", output);
}

即。您正在打印output缓冲区,就好像它是一个以空字符结尾的字符串,而事实上并非如此。最好使用fwriteSTDOUT

但是,我认为问题的实质是尝试向终端显示任意字节(实际上不代表字符串)。终端可能会将某些字节序列解释为影响您所看到的内容的命令。此外,textEdit可能会确定该文件是某种字符编码并相应地解码字符。

  

现在我不知道调用'\'和数字是什么(我要搜索什么来阅读更多内容?)

对我来说,它们看起来像八进制转义序列。

  

为什么打印而不是字符(unicode?)

这与unicode无关。也许是你的终端模拟器决定那些字符是不可打印的,所以用转义序列替换它们。

简而言之,我认为您的方法(在视觉上比较您在文本编辑器中看到的内容与您在终端上看到的内容)是有缺陷的。您必须从文件中读取的代码看起来正确;我建议继续练习并检查结果,或者如果你真的想确定,请使用十六进制编辑器查看文件,并让程序输出它读取的字节值(作为数字) - 并将它们与您在十六进制编辑器中看到的内容。

答案 2 :(得分:1)

从文件"JFIF"的第一行({bit.ly/18gECvyÿÿJFIFHH€C€CƒVƒ)中出现字符串card.raw,似乎{{1是一个JPEG图像格式文件,在其开头插入了bit.ly URL。

在这种情况下,你会看到奇怪/特殊的字符,因为它根本不是通常的文本文件。

另外,正如davmac指出的那样,即使您正在处理实际的文本文件,您使用card.raw的方式也不合适。在C中处理纯文本文件时,最好的方法是一次读取整个文件而不是逐行读取,假设有足够的内存可用:

fgets

这样,你不必担心行长或类似的东西。