VC下fopen如何支持中文

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC下fopen如何支持中文相关的知识,希望对你有一定的参考价值。

参考技术A 1、fopen属于c语言函数
vc的话,使用封装好的CFile更方便
2、VC的fopen函数第一个参数是const
char*,一旦遇到中文文件名就难以应付了,如果中文是UTF8编码的话,我们还可以用下列代码将其转换为UNICODE,然后用_wfopen函数打开文件。
boolUTF8ToUnicode(constchar* UTF8, wchar_t* strUnicode)

DWORDdwUnicodeLen; //转换后Unicode的长度
TCHAR*pwText; //保存Unicode的指针
// wchar_t* strUnicode; //返回值
//获得转换后的长度,并分配内存
dwUnicodeLen = MultiByteToWideChar(CP_UTF8,0,UTF8,-1,NULL,0);
pwText = newTCHAR[dwUnicodeLen];
if(!pwText)

returnfalse;

//转为Unicode
MultiByteToWideChar(CP_UTF8,0,UTF8,-1,pwText,dwUnicodeLen);
//转为CString
wcscpy(strUnicode, pwText);
//清除内存
delete[]pwText;
returntrue;

使用:
wchar_tstrUnicode[260];
UTF8ToUnicode(streamName, strUnicode);
FILE* fid = _wfopen(strUnicode, L"rb");
// FILE* fid = fopen(streamName, "rb");//此为原来的方法,遇到中文不能正确打开

文件打开问题,文件删除后。 fopen 状态在 VC++ 中失败

【中文标题】文件打开问题,文件删除后。 fopen 状态在 VC++ 中失败【英文标题】:File open issue, after file deleted. fopen status is failing in VC++ 【发布时间】:2014-10-27 09:05:38 【问题描述】:

打开示例

#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])

    FILE * pFile;
    for(int i=0; i < 1000000; i++)
    
        bool ret = remove("C:\\abc.txt");
        pFile = fopen ("C:\\abc.txt","w");
        if (pFile!=NULL)
        
            fputs ("fopen example",pFile);
            fclose (pFile);
        
        else
        
            printf("%d fopen() fails \n", count);
        
    
    return 0;

这里调用remove后,调用pFile = fopen("C:\abc.txt","w");

有时即使在 C:\ 调用 remove 后 abc.txt 文件也不存在,但 fopen pFile 指针为空。

这有时会被复制,但并非总是如此。在此示例中,此问题被复制了 50/60 次。

请提出一些解决方案。

【问题讨论】:

您是否尝试过检查 errno 变量?系统可能会设置一些错误代码来帮助您解决此问题,您可以使用 perror 收集更多信息。也看看pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html 看起来像一个竞争条件。底层文件系统中可能的优化可以让remove 在真正清除所有内容并立即创建具有相同名称的文件之前返回。尝试在 remove 和 create 之间添加一个短暂的睡眠:它应该可以工作。 如果你想以“w”模式打开文件,请删除文件,我认为你不需要。 @SergeBallesta 我已经尝试过使用 Sleep 并且效果很好。但在我的原始应用程序中,我可能无法使用睡眠。上面的代码是一个测试应用程序,它证明 fopen 有时会失败,并且由于这个 fopen 问题,我的原始应用程序失败了。除了使用睡眠之外,还有其他解决方法吗? 删除文件并不一定会从磁盘中删除文件。您所看到的与机器上运行的反恶意软件或搜索索引器是一致的。当您创建文件时,它会立即生效,肯定是在您开始运行程序之前很短的时间。此类软件通过删除共享打开文件,试图将其对其他程序的影响降至最低。因此,您的 remove() 调用似乎可以正常工作(即使您从未实际检查过),但文件并没有消失。您可以通过先重命名文件来使其更具弹性,这不会被阻止。 【参考方案1】:

如果您已经确定这是底层文件系统中的竞争条件问题,则修复它的正确方法是(如 BLUEPIXY 建议的那样)简单地删除 remove 调用:

pFile = fopen ("C:\\abc.txt","w");

如果文件不存在则创建该文件,如果存在则将其截断为 0 大小,这正是您需要的。

【讨论】:

我正在使用一个包装函数,其中给出了 fopen 调用。如果文件被删除,它将以写入模式打开,否则以 rb+ 模式打开。因此,在应该删除并再次创建它的情况下,就会出现问题。此外,我检查了 remove() 函数的返回值以确认删除是否成功,令我惊讶的是,我发现有时 remove 返回成功值,进一步 fopen 失败,将“Permission denied”作为错误,有时 remove() 函数失败但fopen 是成功的。 remove() 似乎是不可靠的功能。 @Aakash : remove 本身并不是一个不可靠的功能。但是在 Windows 下,如果在打开的文件上调用它会失败(特殊访问模式除外),所以你有同样的竞争问题。恕我直言,您应该重新考虑您的算法以不进行删除调用。 在您的用例条件下这是不安全的。 感谢您提供的信息。我会检查其他方式。谢谢。【参考方案2】:

如果您需要在删除文件后确定创建文件,您可以延迟 fopen,直到您确认旧的“abc.txt”文件已删除。

为此,您需要引入一些循环来确认它,如下所示,

bool ret = remove("C:\\abc.txt");
FILE * rFile;
while(true)

    rFile = fopen ("C:\\abc.txt","r");
    if(rfile == null)
       break; //File Removed confirmed!!
    else
       sleep(100); //Loop around again...

pFile = fopen ("C:\\abc.txt","w");
if (pFile!=NULL)

【讨论】:

以上是关于VC下fopen如何支持中文的主要内容,如果未能解决你的问题,请参考以下文章

文件打开问题,文件删除后。 fopen 状态在 VC++ 中失败

在VC++中用fopen

如何将此 VC++ 6 代码转换为 VC++ 2008?

VC++ 依赖

std::bind 有多少个参数(VC 11 只支持 4 个)

Qt中如何添加并调用别人在VC6.0写的的类文件?