C++ fwrite无法写入文本文件,不知道为什么?

3

我有一段代码,主要是从文件中读取数据并创建新的文件,并将源文件中的内容写入目标文件。它读取缓冲区并创建文件,但是fwrite函数没有将内容写入新创建的文件,我不知道为什么。
以下是代码。(我必须使用_sopen函数,这是遗留代码的一部分)

#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <string>
#include <share.h>
#include <sys\stat.h>


int main () {
  std::string szSource = "H:\\cpp\\test1.txt";
  FILE* pfFile;
  int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
  if (iFileId >= 0) 
     pfFile = fdopen(iFileId, "r");
   //read file content to buffer 
   char * buffer;
   size_t result;
   long lSize;
   // obtain file size:
   fseek (pfFile , 0 , SEEK_END);
   lSize = ftell (pfFile);
   fseek(pfFile, 0, SEEK_SET);
 //   buffer = (char*) malloc (sizeof(char)*lSize);
   buffer = (char*) malloc (sizeof(char)*lSize);

   if (buffer == NULL)
   {

       return false;
   }

   // copy the file into the buffer:
   result = fread (buffer,lSize,1,pfFile);   
   std::string szdes = "H:\\cpp\\test_des.txt";
   FILE* pDesfFile;
   int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
  if (iFileId2 >= 0) 
     pDesfFile = fdopen(iFileId2, "w+");

   size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile );
   printf("Error code: %d\n",ferror(pDesfFile));

   fclose (pDesfFile);

  return 0;
}

您可以创建主文件并尝试查看它是否适合您。
谢谢。

2
是的,sizeof(buffer)为4,它是一个指针。你需要在fwrite()调用中使用lSize。 - Hans Passant
有没有很好的理由以如此复杂的方式做这件事?这是某个任务的一部分吗?有没有特别的原因要这样做? - Gian
2
你确定_sopen()返回有效的文件描述符吗?我没有看到你正确地检查它(例如,即使_sopen没有成功,你也会fseek()文件)。而且为什么你在没有意义的情况下混合使用C和C++(或者至少我没有看到有意义的地方)?如果你要使用C ++,请使用ofstream来写入文件。 - m0skit0
是的,最终我可以将内容读入缓冲区。 - user63898
6个回答

2
将您的代码更改为以下内容,然后报告您的结果:
int main () {
  std::string szSource = "H:\\cpp\\test1.txt";
  int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
  if (iFileId >= 0) 
  {
    FILE* pfFile;
    if ((pfFile = fdopen(iFileId, "r")) != (FILE *)NULL)
    {
      //read file content to buffer 
      char * buffer;
      size_t result;
      long lSize;
      // obtain file size:
      fseek (pfFile , 0 , SEEK_END);
      lSize = ftell (pfFile);
      fseek(pfFile, 0, SEEK_SET);
      if ((buffer = (char*) malloc (lSize)) == NULL)
        return false;

      // copy the file into the buffer:
      result = fread (buffer,(size_t)lSize,1,pfFile);   
      fclose(pfFile);

      std::string szdes = "H:\\cpp\\test_des.txt";
      FILE* pDesfFile;
      int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
      if (iFileId2 >= 0) 
      {
        if ((pDesfFile = fdopen(iFileId2, "w+")) != (FILE *)NULL)
        {
          size_t f = fwrite (buffer, (size_t)lSize, 1, pDesfFile);
          printf ("elements written <%d>\n", f);

          if (f == 0)
            printf("Error code: %d\n",ferror(pDesfFile));

          fclose (pDesfFile);
        }
      }
    }
  }

  return 0;
}

[编辑]
对于其他帖子,为了展示fwrite的使用/结果-以下代码的输出是什么?
#include <stdio.h>

int main (int argc, char **argv) {
   FILE *fp = fopen ("f.kdt", "w+");

   printf ("wrote %d\n", fwrite ("asdf", 4, 1, fp));

   fclose (fp);
}

[/edit]


h:\cpp\fwrite_read\fwrite_read\fwrite_read.cpp(88) : 错误 C3861: 找不到标识符“_sclose” h:\cpp\fwrite_read\fwrite_read\fwrite_read.cpp(91) : 错误 C3861: 找不到标识符“_sclose” - user63898
抱歉,我不知道你在自己的环境中不熟悉 - 应该是_close而不是_sclose(顺便说一句,我也不是很熟悉,但我的谷歌搜索能力很强)。 - KevinDTimm
我得到了以下错误提示:在_sclose中Debug Assertion Failed Expression (_osfile(fh) & FOPEN) 附言: 相信我,我已经整天在Google上搜索了。 - user63898
当应该使用 _close 时,为什么会出现 _sclose 的错误? - KevinDTimm
我认为应该使用(f < (size_t)lSize)而不是(f == 0)进行测试以检查错误条件。 - crashmstr
显示剩余5条评论

2

sizeof(buffer)返回的是指针的大小,即4个字节,而不是缓冲区中项目的数量。

如果buffer是一个数组,则sizeof(buffer)可能有效,因为它返回数组中的字节数。


当我将命令更改为size_t f = fwrite(buffer, 1, lSize, pDesfFile);时,它返回给我22,但文件仍然是空的。 - user63898
@user63898 这个文件大小是否为0字节? - PJL
@user63898 你确认缓冲区已经成功创建了吗? - PJL
是的,如果(buffer == NULL),我也在调试器中看到了字符串内容,当它命中时:result = fread(buffer,lSize,1,pfFile)。我还尝试过:buffer =(char )malloc(sizeof(char) lSize)。 - user63898
@user63898,抱歉我是指填充而不是初始化。 - PJL
是的,它填满了,我编辑了我的测试源代码。也许是我的电脑出了什么问题。这让我疯狂。 - user63898

2
fwrite的第三个参数是sizeof(buffer),它是4个字节(一个指针)。相反,你需要传递要写入的字节数(lSize)。
更新:看起来你缺少指示文件应该读/写的标志:_O_RDWR
这对我来说可行...
   std::string szdes = "C:\\temp\\test_des.txt"; 
   FILE* pDesfFile; 
   int iFileId2;
   err = _sopen_s(&iFileId2, szdes.c_str(), _O_CREAT|_O_BINARY|_O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE); 
   if (iFileId2 >= 0)  
      pDesfFile = _fdopen(iFileId2, "w+");
size_t f = fwrite(buffer, 1, lSize, pDesfFile); fclose(pDesfFile);

看起来你还缺少指示文件应该是读/写的标志:_O_RDWR。我也切换到使用更安全的_sopen_s()形式。 - jschroedl

1

由于我找不到关于_sopen的信息,所以只能查看man open。它报告:

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

你的调用_sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);与这两个都不匹配,你似乎有标志和“某些东西”和模式/SH_DENY是什么?

man _sopen的结果是什么?

最后,在你fclose文件指针之后,你不应该关闭_sopen的文件描述符吗?

顺便说一句,你的最终行应该像这样:

if (iFileId2 >= 0) 
{
  pDesfFile = fdopen(iFileId2, "w+");
  size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile ); //<-- the f returns me 4
  fclose (pDesfFile);
}

由于您当前无论 O_CREAT 是否成功,都会写入文件。您在顶部也做了同样的事情,无论 RDONLY 文件的 fdopen 是否成功,都会处理读取(和写入)操作 :(


这是Windows函数IO.h中的内容,常量来自于#include <share.h>和<sys\stat.h>。 - user63898
之前它返回了22,现在又返回了4?请注意man fwrite中的描述:size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);,这意味着你正在尝试写入大小为1的4个或22个项目 - 具体取决于你正在运行的代码。 - KevinDTimm
@user63898 - 请发布您的实际代码 - 目前正在运行什么。 - KevinDTimm
1
所以,你的代码还是有问题的(你仍在使用sizeof(buffer))- 请看我的下一篇帖子。 - KevinDTimm
我尝试使用 size_t f = fwrite(buffer, 1, lSize, pDesfFile);,但它没有起作用。 - user63898
1
为什么你要这样做?请看我上面的评论(man fwrite)- 你做错了 - long和size_t不是同一个类型,你参数的顺序也错了 - 请使用下面的代码并从那里开始讨论。 - KevinDTimm

0

你正在使用混合的C和C++代码,这样会让人困惑。

sizeof运算符并没有做你期望的事情。


0

看起来@PJL@jschroedl找到了真正的问题,但是也有一般性的问题:

fwrite的文档说明:

fwrite返回实际写入的完整项数,如果发生错误,则可能少于count。此外,如果发生错误,则无法确定文件位置指示器。

所以如果返回值小于传入的count,请使用ferror查找出现了什么问题。

ferror例程(作为函数和宏实现)测试与流相关联的文件的读取或写入错误。如果发生错误,则流的错误指示器保持设置,直到关闭或倒回流,或者对其调用clearerr。

添加 printf("错误代码:%d\n",ferror(pDesfFile)); 它给了我0。 - user63898
是的,因为在这种情况下没有错误,因为您没有给出正确的大小来写入(使用原始代码)。如果实际上写文件时出现错误,这就是您可以使用的方法来找出原因。如果它不提供错误代码,则不在fwrite中! - crashmstr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接