【问题标题】:Differences between writing/reading binary/text in c在c中写入/读取二进制/文本之间的差异
【发布时间】:2014-11-17 06:21:55
【问题描述】:

我正在开发客户端发送/接收文件的客户端/服务器程序。这些文件可以是文本文件或二进制文件。但是,我不确定我需要进行哪些更改(如果有的话)以适应任何一种文件类型。基本上我希望在服务器端读取/写入文件而不关心它是什么类型的文件,我希望能够这样做而不检查它是什么类型的文件。像这样的代码会起作用吗?为什么或为什么不?

服务器sn-p:

//CREATING/WRITING TO A FILE
//we are ready to begin reading data from the client, and storing it 
int fd = open(pathname, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR);
while(nbytes < bytes)
{
    //only read the neccessary # of bytes: the remaining bytes vs max buffer size
    int min_buffer = (bytes - nbytes) < BUFFER_SIZE ? (bytes - nbytes) : BUFFER_SIZE;
    length = recv( client->client_socket, contents, min_buffer, 0);

    if(fd < 0) //the fd is bad, but we need to continue reading bytes anyway
    {
        nbytes += length;
        continue;
    }

    if(length <= 0)
        break;//string empty or error occurred...this error means the client closed?

    if(write(fd, contents, min_buffer) != min_buffer)
    {
        //printf("There was an error writing to the file.\n");
    }
    else
    {       
        nbytes += length;
    }
}


//READING A STORED FILE AND SENDING THE DATA TO CLIENT
int fd = open(pathname, O_RDWR, S_IRUSR | S_IWUSR);
if(fd >= 0)
{
    while(bytes > 0)
    {
        bytes = read(fd, buffer,  BUFFER_SIZE );

        if(bytes > 0)//we have read some bytes
        {
            //send the client the data
            write(client->client_socket, buffer, bytes);
        }
        else if(bytes < 0)
        {
            //some error occured
            write( client->client_socket, "ERROR: Could not read\n", 22);   
            return;
        }
    }
}

那么,如果客户端发送的是二进制文件而不是文本文件,这段代码会导致问题吗? (我们可以假设客户端知道预期的文件类型。)

注意:关于此的另一个令人困惑的细节是,有一些用 c 编写/读取二进制文件的教程似乎与常规文件没有任何真正的区别,这就是我在这里的原因。

【问题讨论】:

  • 只用“二进制”文件做所有事情。今天的文本文件只是二进制文件,在 Windows 中以文本模式打开时会进行一些特殊处理;您也可以在二进制模式下毫无问题地读取/写入它们。
  • @deviantfan 但是“二进制”和“文本”模式之间的区别是什么(就这段代码而言,我的意思是,不是按照定义)?此代码是否使用二进制模式?如果没有,我该如何切换?
  • 看起来你的编程是为 Linux (仅)?然后二进制文件和文本文件之间没有技术差异,只有文件。如果您的代码有效,它也可以与其他文件一起使用。 Windows 在文本文件模式下使用换行符做了一些奇怪的事情,MS 编写它的文档就好像二进制/文本之间存在一些根本区别,但除了 Windows 中的换行符之外,它完全一样。跨度>
  • 补充:如果你使用标准的 C fopenfclose 而不是 Linux 特定的 open 等,你可以指定以二进制或文本模式打开文件。这是因为 fopen 也应该可以在 Windows 上运行,但是您在 Linux 上的 fopen 中选择的内容不会改变任何内容(可以通过阅读源代码来验证)
  • 是的,我在这里只使用 Linux。多么可爱的答案,因为我不必一次进行任何重大更改。请将其发布为答案,我会接受。

标签: c sockets binaryfiles


【解决方案1】:

只需使用“二进制”文件即可。 Linux在操作系统级别的文件中的“文本”和“二进制”之间没有区别,只是其中包含字节的文件。 IE。期望文件包含所有可能的字节值,不要为不同类型的内容编写不同的代码。

Windows 中有所不同:Windows 中的文本模式意味着在写入/读取文件时,程序中的换行符 (\n) 会转换为 \r\n 或从 \r\n 转换。以二进制模式读取的书面文本文件将包含这两个字节,而不是原始的\n,反之亦然。 (另外,MS 在文档中并不是很清楚这是唯一的区别,它很容易让初学者感到困惑。)

如果您使用标准 C fopenfclose 而不是 Linux 特定的 open 等,您可以指定以二进制或文本模式打开文件(在 Linux 上也是如此)。这是因为使用 fopen 的代码应该可以在 Windows 和 Linux 上运行,而无需任何特定于操作系统的更改;但是在 Linux 上运行时你在 fopen 中选择什么并不重要(可以通过阅读 fopen 的源代码等来验证)

关于插座:
Linux:没有区别(再次)
Windows:也没有区别。只有字节,没有奇怪的换行转换。

【讨论】:

    【解决方案2】:

    我因二进制/文本文件问题而苦恼了一天。我正在将二进制数据输出到“文件”中(显然是文本文件……经过多年的 C 语言,我一直认为文件就是文件),并且不断在输出中插入虚假字符。我什至下载了一个新的编译器,但遇到了同样的问题。问题?当我使用 fprint 语句系列中的任何一个输出十六进制 A 时,正在插入十六进制 D。是的,换行符 - A - 被替换为回车/换行符 - DA。这是一个遗留的“生产线末端”问题,基于不同系统的开发方式。发现问题的难点在于意识到 A 不仅被解释为二进制字段,而且实际上被识别为换行符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-03
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      • 1970-01-01
      • 2013-05-28
      • 1970-01-01
      相关资源
      最近更新 更多