一个关于写文件非常奇怪的问题?

时间:2022-02-09 21:46:57
CStdioFile file;
CString strTmp;
....
....
file.WriteString(strTmp);
file.WriteString(strTmp);
file.WriteString(strTmp);
为什么第一二次写没问题,第三次写就有问题了

13 个解决方案

#1


详细一点

#2


具体在什么情况下出错我至今也没总结出规律来
错误的现象是不但写会出错,读也会出错
错误发生的地方在这里
void CStdioFile::WriteString(LPCTSTR lpsz)
{
ASSERT(lpsz != NULL);
ASSERT(m_pStream != NULL);

if (_fputts(lpsz, m_pStream) == _TEOF)     //错在这里
AfxThrowFileException(CFileException::diskFull, _doserrno, m_strFileName);
}
进一步
int __cdecl fputs (
        const char *string,
        FILE *stream
        )
{
        REG2 int buffing;
        REG1 unsigned int length;
        REG3 unsigned int ndone;

        _ASSERTE(string != NULL);
        _ASSERTE(stream != NULL);

        length = strlen(string);
        _lock_str(stream);
        buffing = _stbuf(stream);
        ndone = _fwrite_lk(string,1,length,stream);//返回的数字与字符窜长度不符
        _ftbuf(buffing, stream);
        _unlock_str(stream);

        return(ndone == length ? 0 : EOF);
}
请哪位搞人指点一二,多谢了!

#3


CStdioFile fMenu;
CString strBuf,strFileName,strTmp;

if(!fMenu.Open("f:\\test.htm",CFile::modeReadWrite|CFile::shareDenyNone))
return;
strTmp.Format("this is a test");
fMenu.SeekToBegin();
fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);
fMenu.SeekToBegin();
while(fMenu.ReadString(strBuf))
{
   if(strBuf.Find("<body")>=0)
     break;
}


fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);

fMenu.Close();

test.htm是一个空的htm文件
以上语句有问题吗?
总是要出错
那位试一下好吗?

#4


try
{
    fMenu.WriteString(strTmp);
}
catch(CFileException e)
{
    // 在这里检查e可以得知错误信息
}
我猜可能是磁盘满了,因为它执行了这句:AfxThrowFileException(CFileException::diskFull, _doserrno, m_strFileName);

#5


对,我也是报这个错
可我硬盘还有2G呢?

各位帮个忙,这个问题困扰我好几天了

#6


你误会了,我只是对你所写的情况判断可能是磁盘满了,自己并没有试验。但是看了你的贴子后我试了一下,没有出现问题啊,能把情况和代码描述的更清楚点吗?

#7


to james_razor:
这样吧,我把我的htm文件发给你吧?
麻烦看一下了。

#8


到我的信箱james_razor@21cn.com,最好有源码。

#9


你不能直接用WriteString来写入一个CString变量,因为CString变量的长度不可知。
char buf[256];
memcpy(buf,"this is a test!");
file.WriteString(buf);
因为WriteString根据'\0'来判断串的结束,而CString不用'\0'来结束一个串,这样在你读的时候会报错!

#10


To Lansie(山河水):代码收到,正在调,有点意思,今天看来不能给你了。
To gamepolice():CString为什么不行?这里可是有一个LPCTSTR的转换的。

#11


请各位帮忙看一下?

#12


我劝你用CFile吧,CStdioFile打开的是流文件,流文件我用得很少,不太清楚特性,但是调试中发现只要前面有读操作,后面的写操作就要出问题。正常情况下,要么一直读,要么一直写。
例外的是,如果写操作前的读操作正好遇到了文件结尾,数据可以追加上去。这点_flsbuf.c中倒是写的很清楚:
/* Check that _IOREAD is not set or, if it is, then so is _IOEOF. Note
   that _IOREAD and IOEOF both being set implies switching from read to
   write at end-of-file, which is allowed by ANSI. Note that resetting
   the _cnt and _ptr fields amounts to doing an fflush() on the stream
   in this case. Note also that the _cnt field has to be reset to 0 for
   the error path as well (i.e., _IOREAD set but _IOEOF not set) as
   well as the non-error path. */
我尝试在写操作前屏蔽上次的读操作位
fMenu.m_pStream->_flag &= ~_IOREAD;
fMenu.Flush(); // 不调用这句数据无法写入
然后执行写操作,但是数据居然是追加在文件尾部的。
所以还是放弃努力吧。任何对CStdioFile的非常规操作都是危险的。何况还有CFile这个选择。

#13


我试了好象没问题嘛

#1


详细一点

#2


具体在什么情况下出错我至今也没总结出规律来
错误的现象是不但写会出错,读也会出错
错误发生的地方在这里
void CStdioFile::WriteString(LPCTSTR lpsz)
{
ASSERT(lpsz != NULL);
ASSERT(m_pStream != NULL);

if (_fputts(lpsz, m_pStream) == _TEOF)     //错在这里
AfxThrowFileException(CFileException::diskFull, _doserrno, m_strFileName);
}
进一步
int __cdecl fputs (
        const char *string,
        FILE *stream
        )
{
        REG2 int buffing;
        REG1 unsigned int length;
        REG3 unsigned int ndone;

        _ASSERTE(string != NULL);
        _ASSERTE(stream != NULL);

        length = strlen(string);
        _lock_str(stream);
        buffing = _stbuf(stream);
        ndone = _fwrite_lk(string,1,length,stream);//返回的数字与字符窜长度不符
        _ftbuf(buffing, stream);
        _unlock_str(stream);

        return(ndone == length ? 0 : EOF);
}
请哪位搞人指点一二,多谢了!

#3


CStdioFile fMenu;
CString strBuf,strFileName,strTmp;

if(!fMenu.Open("f:\\test.htm",CFile::modeReadWrite|CFile::shareDenyNone))
return;
strTmp.Format("this is a test");
fMenu.SeekToBegin();
fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);
fMenu.SeekToBegin();
while(fMenu.ReadString(strBuf))
{
   if(strBuf.Find("<body")>=0)
     break;
}


fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);
fMenu.WriteString(strTmp);

fMenu.Close();

test.htm是一个空的htm文件
以上语句有问题吗?
总是要出错
那位试一下好吗?

#4


try
{
    fMenu.WriteString(strTmp);
}
catch(CFileException e)
{
    // 在这里检查e可以得知错误信息
}
我猜可能是磁盘满了,因为它执行了这句:AfxThrowFileException(CFileException::diskFull, _doserrno, m_strFileName);

#5


对,我也是报这个错
可我硬盘还有2G呢?

各位帮个忙,这个问题困扰我好几天了

#6


你误会了,我只是对你所写的情况判断可能是磁盘满了,自己并没有试验。但是看了你的贴子后我试了一下,没有出现问题啊,能把情况和代码描述的更清楚点吗?

#7


to james_razor:
这样吧,我把我的htm文件发给你吧?
麻烦看一下了。

#8


到我的信箱james_razor@21cn.com,最好有源码。

#9


你不能直接用WriteString来写入一个CString变量,因为CString变量的长度不可知。
char buf[256];
memcpy(buf,"this is a test!");
file.WriteString(buf);
因为WriteString根据'\0'来判断串的结束,而CString不用'\0'来结束一个串,这样在你读的时候会报错!

#10


To Lansie(山河水):代码收到,正在调,有点意思,今天看来不能给你了。
To gamepolice():CString为什么不行?这里可是有一个LPCTSTR的转换的。

#11


请各位帮忙看一下?

#12


我劝你用CFile吧,CStdioFile打开的是流文件,流文件我用得很少,不太清楚特性,但是调试中发现只要前面有读操作,后面的写操作就要出问题。正常情况下,要么一直读,要么一直写。
例外的是,如果写操作前的读操作正好遇到了文件结尾,数据可以追加上去。这点_flsbuf.c中倒是写的很清楚:
/* Check that _IOREAD is not set or, if it is, then so is _IOEOF. Note
   that _IOREAD and IOEOF both being set implies switching from read to
   write at end-of-file, which is allowed by ANSI. Note that resetting
   the _cnt and _ptr fields amounts to doing an fflush() on the stream
   in this case. Note also that the _cnt field has to be reset to 0 for
   the error path as well (i.e., _IOREAD set but _IOEOF not set) as
   well as the non-error path. */
我尝试在写操作前屏蔽上次的读操作位
fMenu.m_pStream->_flag &= ~_IOREAD;
fMenu.Flush(); // 不调用这句数据无法写入
然后执行写操作,但是数据居然是追加在文件尾部的。
所以还是放弃努力吧。任何对CStdioFile的非常规操作都是危险的。何况还有CFile这个选择。

#13


我试了好象没问题嘛