写文件后重命名问题

时间:2021-07-20 09:59:26

FILE* fp;
if( (fp = _fsopen( CW2A(m_strFilePath), "wb",_SH_DENYNO )) !=NULL )

    int writecount = 0;
    while (Number > 0)
    {  
writecount++;
        InternetReadFile(hInternetUrl, Temp, MAXBLOCKSIZE - 1, &Number); 
fwrite(Temp, sizeof (char), Number , fp); 
if ( WaitForSingleObject ( sParam->ExitEvent , 0 ) !=WAIT_TIMEOUT ) 

    fclose( fp ); 
    break;
}
if(sParam->iPos > 100)
{
sParam->iPos = 100;
}
TRACE(L"%s POS = %d\n",sParam->url,sParam->iPos);
    } 
    int bclose = fclose( fp ); 
}
rename(strFilePath,xxxxx);
此处调用用rename函数,将m_strFilePath重新命名。
有时候rename失败,提示另个程序在调用,无法结束。
我也看过fclose是成功的。
请问这是怎么回事?

26 个解决方案

#1


    int bclose = fclose( fp );     
rename(strFilePath,xxxxx);放里面!
}

#2


我使用WIN32 API创建、写文件,关闭后,立即用WIN32 MoveFile()改名,从没遇到问题。

#3


我把rename放到里面还是不行。还有,我这个是多线程在跑,不过开的一个线程就往不同的文件里面写入,这个应该不会影响吧?

#4


“多线程在跑”
要加锁了

#5


加锁是加在一开始写文件地方吗?还是锁在重命名地方?

#6


按说“一个线程就 往不同的文件里面写入”是,
m_strFilePath 应该是不同的,
怎么会 “提示另个程序在调用,无法结束” ?
既然已经“往不同的文件”写,为什么 还要 rename ?

还是“_fsopen( CW2A(m_strFilePath)” 问题,名称应该 是不一样的。
否则 一个线程 打开 后, 另一个 线程 就 不能 打开了。

这句“rename(strFilePath,xxxxx);”都是 固定的 名。

“m_strFilePath” 最好加上 线程 号。

#7


我是在做一个类似下载的东西,重命名是为了区分哪些文件是已经下载完毕,哪些是没有完毕的

#8


我也写过程序:多线程跑,各写各的文件,写完后,关闭文件并重命名;线程之间不需要锁保护。
我觉得是LZ代码哪里有个小逻辑问题。

1)写日志,把open/close/rename记录到日志;
2)程序运行时,不要在资源管理器里打开下载目录,不要点击相关文件;
3)rename失败后,加点代码{ sleep(1000); 重试rename; },看看能否成功。测试版本可以重试3\5次看看。最后rename如果还是失败,用procexp搜索文件,看看哪个进程打开了这个文件。

#9


测试版本也做过重试的动作,还是不能全部重命名成功。只是减少了出错的概率。另外提一下,我单独写多个文件时候没有问题。这个重命名失败,是我在跑其他线程时候,同时在跑写文件的线程才会出现。其他线程主要是做的解压7z文件,然后复制之类的操作。

#10


引用 9 楼 nanjingking 的回复:
测试版本也做过重试的动作,还是不能全部重命名成功。只是减少了出错的概率。另外提一下,我单独写多个文件时候没有问题。这个重命名失败,是我在跑其他线程时候,同时在跑写文件的线程才会出现。其他线程主要是做的解压7z文件,然后复制之类的操作。

其它线程与写文件线程之间有什么联系吗?

#11


从流程上看,应该没有联系。操作的是不同路径的文件。

#12


引用 11 楼 nanjingking 的回复:
从流程上看,应该没有联系。操作的是不同路径的文件。

"这个重命名失败,是我在跑其他线程时候,同时在跑写文件的线程才会出现。"==>两类线程一定有点什么联系。用什么API做7z解压?

#13


发的cmd命令,直接解压,没有直接调用api。这个有冲突吗?

#14


还是建议你在删除文件失败时立即用 Process Explorer 工具的 Find -> Find Handle or DLL 看看这个文件被哪些进程打开。

#15


对了,还可以用 sysinternal 的 File Monitor 工具跟踪文件访问情况。
Process Explorer 也是 sysinternal的系列工具之一。

#16


问题找到了。根据程序打出的时间来看,闭关文件句柄时间会比从电脑中看到此文件的最后修改时间要早。关闭了文件句柄,但是电脑还是将缓存的数据写入到文件中去。所以,为什么关闭后,直接重命名会失败,因为当时,电脑还是写文件。

#17


引用 14 楼 davidyu720 的回复:
还是建议你在删除文件失败时立即用 Process Explorer 工具的 Find -> Find Handle or DLL 看看这个文件被哪些进程打开。



试过了,显示是“non-existent process“。

#18


问题是:
fwrite(Temp, sizeof (char), Number , fp); 
这个 fp 不对应 打开时的 fp ?
试试:
fclose( fp ); 
fp=0;
最好 给 fp
加个 锁。

#19


引用 17 楼 nanjingking 的回复:
Quote: 引用 14 楼 davidyu720 的回复:

还是建议你在删除文件失败时立即用 Process Explorer 工具的 Find -> Find Handle or DLL 看看这个文件被哪些进程打开。



试过了,显示是“non-existent process“。

这很奇怪!non-existent process一般表示进程退出了,但进程退出后,OS会关闭进程打开的句柄的。

#20


引用 16 楼 nanjingking 的回复:
问题找到了。根据程序打出的时间来看,闭关文件句柄时间会比从电脑中看到此文件的最后修改时间要早。关闭了文件句柄,但是电脑还是将缓存的数据写入到文件中去。所以,为什么关闭后,直接重命名会失败,因为当时,电脑还是写文件。

怪了,难道fclose()会异步返回?fclose()返回值呢,成功了吗?

#21


fclose() 返回成功了,返回是0.

#22


引用 18 楼 schlafenhamster 的回复:
问题是:
fwrite(Temp, sizeof (char), Number , fp); 
这个 fp 不对应 打开时的 fp ?
试试:
fclose( fp ); 
fp=0;
最好 给 fp
加个 锁。

这位朋友,程序是多线程下载,如果加锁的话只能一个文件下载,不符合程序设计啊!

#23


还有一个小问题,请教大神们。GetLastError()这个函数,多线程调用时候,返回错误信息会不会错乱?

#24


引用 23 楼 nanjingking 的回复:
还有一个小问题,请教大神们。GetLastError()这个函数,多线程调用时候,返回错误信息会不会错乱?

不会。
GetLastError
The GetLastError function retrieves the calling thread's last-error code value. The last-error code is maintained on a per-thread basis. Multiple threads do not overwrite each other's last-error code. 

#25


问题已经找到,只是没有找到更好的解决办法,只能不停的重试了。就先关闭了。感谢davidyu720 ,schlafenhamster 支持,结贴了,分不多,请两位见谅。

#26


突然想起来:服务器上装了杀毒软件吗?禁用一下看看?

#1


    int bclose = fclose( fp );     
rename(strFilePath,xxxxx);放里面!
}

#2


我使用WIN32 API创建、写文件,关闭后,立即用WIN32 MoveFile()改名,从没遇到问题。

#3


我把rename放到里面还是不行。还有,我这个是多线程在跑,不过开的一个线程就往不同的文件里面写入,这个应该不会影响吧?

#4


“多线程在跑”
要加锁了

#5


加锁是加在一开始写文件地方吗?还是锁在重命名地方?

#6


按说“一个线程就 往不同的文件里面写入”是,
m_strFilePath 应该是不同的,
怎么会 “提示另个程序在调用,无法结束” ?
既然已经“往不同的文件”写,为什么 还要 rename ?

还是“_fsopen( CW2A(m_strFilePath)” 问题,名称应该 是不一样的。
否则 一个线程 打开 后, 另一个 线程 就 不能 打开了。

这句“rename(strFilePath,xxxxx);”都是 固定的 名。

“m_strFilePath” 最好加上 线程 号。

#7


我是在做一个类似下载的东西,重命名是为了区分哪些文件是已经下载完毕,哪些是没有完毕的

#8


我也写过程序:多线程跑,各写各的文件,写完后,关闭文件并重命名;线程之间不需要锁保护。
我觉得是LZ代码哪里有个小逻辑问题。

1)写日志,把open/close/rename记录到日志;
2)程序运行时,不要在资源管理器里打开下载目录,不要点击相关文件;
3)rename失败后,加点代码{ sleep(1000); 重试rename; },看看能否成功。测试版本可以重试3\5次看看。最后rename如果还是失败,用procexp搜索文件,看看哪个进程打开了这个文件。

#9


测试版本也做过重试的动作,还是不能全部重命名成功。只是减少了出错的概率。另外提一下,我单独写多个文件时候没有问题。这个重命名失败,是我在跑其他线程时候,同时在跑写文件的线程才会出现。其他线程主要是做的解压7z文件,然后复制之类的操作。

#10


引用 9 楼 nanjingking 的回复:
测试版本也做过重试的动作,还是不能全部重命名成功。只是减少了出错的概率。另外提一下,我单独写多个文件时候没有问题。这个重命名失败,是我在跑其他线程时候,同时在跑写文件的线程才会出现。其他线程主要是做的解压7z文件,然后复制之类的操作。

其它线程与写文件线程之间有什么联系吗?

#11


从流程上看,应该没有联系。操作的是不同路径的文件。

#12


引用 11 楼 nanjingking 的回复:
从流程上看,应该没有联系。操作的是不同路径的文件。

"这个重命名失败,是我在跑其他线程时候,同时在跑写文件的线程才会出现。"==>两类线程一定有点什么联系。用什么API做7z解压?

#13


发的cmd命令,直接解压,没有直接调用api。这个有冲突吗?

#14


还是建议你在删除文件失败时立即用 Process Explorer 工具的 Find -> Find Handle or DLL 看看这个文件被哪些进程打开。

#15


对了,还可以用 sysinternal 的 File Monitor 工具跟踪文件访问情况。
Process Explorer 也是 sysinternal的系列工具之一。

#16


问题找到了。根据程序打出的时间来看,闭关文件句柄时间会比从电脑中看到此文件的最后修改时间要早。关闭了文件句柄,但是电脑还是将缓存的数据写入到文件中去。所以,为什么关闭后,直接重命名会失败,因为当时,电脑还是写文件。

#17


引用 14 楼 davidyu720 的回复:
还是建议你在删除文件失败时立即用 Process Explorer 工具的 Find -> Find Handle or DLL 看看这个文件被哪些进程打开。



试过了,显示是“non-existent process“。

#18


问题是:
fwrite(Temp, sizeof (char), Number , fp); 
这个 fp 不对应 打开时的 fp ?
试试:
fclose( fp ); 
fp=0;
最好 给 fp
加个 锁。

#19


引用 17 楼 nanjingking 的回复:
Quote: 引用 14 楼 davidyu720 的回复:

还是建议你在删除文件失败时立即用 Process Explorer 工具的 Find -> Find Handle or DLL 看看这个文件被哪些进程打开。



试过了,显示是“non-existent process“。

这很奇怪!non-existent process一般表示进程退出了,但进程退出后,OS会关闭进程打开的句柄的。

#20


引用 16 楼 nanjingking 的回复:
问题找到了。根据程序打出的时间来看,闭关文件句柄时间会比从电脑中看到此文件的最后修改时间要早。关闭了文件句柄,但是电脑还是将缓存的数据写入到文件中去。所以,为什么关闭后,直接重命名会失败,因为当时,电脑还是写文件。

怪了,难道fclose()会异步返回?fclose()返回值呢,成功了吗?

#21


fclose() 返回成功了,返回是0.

#22


引用 18 楼 schlafenhamster 的回复:
问题是:
fwrite(Temp, sizeof (char), Number , fp); 
这个 fp 不对应 打开时的 fp ?
试试:
fclose( fp ); 
fp=0;
最好 给 fp
加个 锁。

这位朋友,程序是多线程下载,如果加锁的话只能一个文件下载,不符合程序设计啊!

#23


还有一个小问题,请教大神们。GetLastError()这个函数,多线程调用时候,返回错误信息会不会错乱?

#24


引用 23 楼 nanjingking 的回复:
还有一个小问题,请教大神们。GetLastError()这个函数,多线程调用时候,返回错误信息会不会错乱?

不会。
GetLastError
The GetLastError function retrieves the calling thread's last-error code value. The last-error code is maintained on a per-thread basis. Multiple threads do not overwrite each other's last-error code. 

#25


问题已经找到,只是没有找到更好的解决办法,只能不停的重试了。就先关闭了。感谢davidyu720 ,schlafenhamster 支持,结贴了,分不多,请两位见谅。

#26


突然想起来:服务器上装了杀毒软件吗?禁用一下看看?