Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用非ascii文件名调用_findfirst_C_Localization - Fatal编程技术网

使用非ascii文件名调用_findfirst

使用非ascii文件名调用_findfirst,c,localization,C,Localization,我有一个多字节的Windows项目,我试图访问一个文件,该文件的名称可以包含现代Windows允许的任何符号。但是,对于包含非ASCII字符(日语、瑞典语、俄语等)的文件名,我失败得很惨 例如: const char * filename_ = "C:\\testÖ.txt" struct _finddata_t fd; long fh = _findfirst(filename_, &fd); 此时\u findfirst()失败 支持所有可能的文件名的最佳解决方案是什么?我了解到\

我有一个多字节的Windows项目,我试图访问一个文件,该文件的名称可以包含现代Windows允许的任何符号。但是,对于包含非ASCII字符(日语、瑞典语、俄语等)的文件名,我失败得很惨

例如:

const char * filename_ = "C:\\testÖ.txt"
struct _finddata_t fd;
long fh = _findfirst(filename_, &fd);
此时
\u findfirst()
失败

支持所有可能的文件名的最佳解决方案是什么?我了解到
\u findfirst()
取决于程序启动时设置的系统区域设置。好的,我可以为某个文件更改它,但是在这种情况下,如何确定文件名所需的区域设置

该项目必须保持多字节

以前有人解决过这样的问题吗

我也尝试使用宽字符转换,但也没有运气。代码示例如下:

debug_prnt("DEBUG: Checking existance of a file: %s\n", filename_);
struct _wfinddata_t ff;
size_t requiredSize = mbstowcs(NULL, filename_, 0);
wchar_t * filename = (wchar_t *)malloc((requiredSize + 1) * sizeof(wchar_t));
if (!filename)
{
    debug_prnt("ERROR: Memory allocation failed\n");
    return FALSE;
}
size_t size = mbstowcs(filename, filename_, requiredSize + 1);
if (size == (size_t)(-1))
{
    debug_prnt("ERROR: Couldn't convert string--invalid multibyte character.\n");
    return FALSE;
}

long fh = _wfindfirst(filename, &ff);
if (fh > 0)
    debug_prnt("DEBUG: File exists\n");
else
    debug_prnt("DEBUG: File does not exist %ls\n", filename);
free(filename);

下面是一个简短但完整的Windows控制台应用程序,它使用您想要使用的功能

这个程序的作用是在当前工作文件夹中创建一个文件作为查找对象,然后在当前工作文件夹中列出扩展名为.txt的文件

对于搜索条件,我使用硬编码的宽字符串。在您的情况下,您可能需要将该字符串接受为多字节字符串,将其转换为宽字符,然后将其与
\u wfindfirst()
一起使用

但是,在我的设置中,
printf()
似乎存在文本转换问题,因此打印到控制台的非ASCII文本中有一个奇怪的字符。然而,调试器显示它很好

// multibyte_file_search.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <locale.h>
#include <io.h>

int _tmain(int argc, _TCHAR* argv[])
{
    const char * filename_ = "testÖ.txt";
    FILE *fp = fopen (filename_, "w");
    fclose(fp);

    // test out mbstowcs()
    wchar_t *wcsFileName_ = new wchar_t[512];
    int requiredSize = mbstowcs(NULL,filename_,0);
    size_t xsize = mbstowcs(wcsFileName_,filename_,512);
    printf ("mbstowcs() return %d\n", xsize);

    // do an actual directory search on the current working directory.
    printf ("\n\n Directory search begins.\n");
    struct _wfinddata_t ff = {0};
    char *csFileName_ = new char[512];
    strcpy (csFileName_, "*.txt");
    xsize = mbstowcs(wcsFileName_,csFileName_,512);  // convert search to wide character.
    intptr_t  fh = _wfindfirst(wcsFileName_, &ff);

    if (fh != -1) {
        do {
            wcstombs (csFileName_, ff.name, 512);
            printf (" ff.name %S and converted name %s \n", ff.name, csFileName_);
            wprintf (L"     ff.name %s and converted name %S \n", ff.name, csFileName_);
        } while (_wfindnext (fh, &ff) == 0);
        _findclose (fh);
    } else {
        printf ("No files in directory.\n");
    }

    return 0;
}
//multibyte\u file\u search.cpp:定义控制台应用程序的入口点。
//
#包括“stdafx.h”
#包括
#包括
#包括
#包括
#包括
int _tmain(int argc,_TCHAR*argv[]
{
const char*filename=“testÖ.txt”;
FILE*fp=fopen(文件名为“w”);
fclose(fp);
//测试MBCS()
wchar_t*wcsFileName_=新的wchar_t[512];
int requiredSize=mbstowcs(NULL,文件名为0);
size_t xsize=mbstowcs(wcsFileName,filename,512);
printf(“mbstowcs()返回%d\n”,xsize);
//在当前工作目录上执行实际目录搜索。
printf(“\n\n目录搜索开始。\n”);
结构_wfinddata_t ff={0};
char*csFileName=新字符[512];
strcpy(csFileName?“*.txt”);
xsize=mbstowcs(wcsFileName,csFileName,512);//将搜索转换为宽字符。
intptr_t fh=_wfindfirst(wcsFileName,&ff);
如果(fh!=-1){
做{
wcstombs(csFileName_uff.name,512);
printf(“ff.name%S和转换后的名称%S\n”,ff.name,csFileName_382;);
wprintf(L“ff.name%s和转换后的名称%s\n”,ff.name,csFileName_389;);
}而(wfinnext(fh,&ff)==0);
_findclose(fh);
}否则{
printf(“目录中没有文件。\n”);
}
返回0;
}

文档在
\u findfirst()
和variants上是,在我看来,您应该使用
\u wfindfirst()
。一般来说,对于Windows程序,这些天我坚持使用UNICODE和宽字符,因为Windows API需要它。为什么要使用strlen()?这意味着您原来的
filename\uu
包含
char
文本,而不是
wchar\t
文本,因此这可能是您的问题所在。strlen有错误。我已经在IBM论坛上找到了正确的长度计算,并在这里更新了代码,但仍然找不到该文件。我也在使用wfindfirst,但到目前为止运气不好。这是您实际使用的代码吗?这里的示例,对于带有
mbtowc()
mblen()
,显示了两个函数的重置,并且执行的方式与您正在执行的方式不同。我认为您应该使用
mbstowcs()
。我使用的是IBM示例,但在
mbstowcs
之后的
中没有使用
wcsFileName
。尝试提供实际文件名,而不是屏蔽文件名。嗯,我的
调试失败:检查文件的存在性:C:\testÖ.txt句柄:-1调试:文件不存在C:\testÖ.txt,errno:2
这里我在调用
\wfindfirst
后立即打印了文件
句柄和
errno
。祝你好运。伙计,如果你已经知道文件名,那么你就不需要_findfirst()。只需使用您已经知道的文件名_findfirst()是使用条件搜索目录,以生成目录中符合条件的文件列表。好的,我知道文件名,但在调用此函数时不知道它是否存在。我找到了解决办法。wcstombs是转换的STL实现,如果UTF-8字符串作为源发送到char指针内,则转换失败。Microsoft function工作得更好,所以您需要使用它。当它是UTF-8文本时,为什么您会询问多字节文本?请参阅其中的说明,并提到必须使用“MultiByteToWideChar()”。