无法使用 CreateFile 函数打开文件

Posted

技术标签:

【中文标题】无法使用 CreateFile 函数打开文件【英文标题】:Unable to open file using CreateFile function 【发布时间】:2012-09-02 08:29:40 【问题描述】:

好的,我一直在关注本教程:http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=4422&lngWId=3

到目前为止,我已经完成了所有工作,直到我需要将程序加载到 .raw 音频文件中。

以下是相关代码:

LPSTR loadAudioBlock(const char* filename, DWORD* blockSize)

HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD size = 0;
DWORD readBytes = 0;
void* block = NULL;

//open the file

if((hFile = CreateFile((LPCWSTR)filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
    return NULL;

// get it's size, allocate memory, and then read it into memory

size = GetFileSize(hFile, NULL);
block = HeapAlloc(GetProcessHeap(), 0, size);
ReadFile(hFile, block, size, &readBytes, NULL);

CloseHandle(hFile);
*blockSize = size;
return (LPSTR)block;

然后是我调用它的主要函数:

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

HWAVEOUT hWaveOut; //device handle
WAVEFORMATEX wfx; //struct for format info
MMRESULT result; // for waveOut return values
LPSTR block;
DWORD blockSize;

// first let's set up the wfx format struct

wfx.nSamplesPerSec = 44100; // rate of the sample
wfx.wBitsPerSample = 16; //sample size
wfx.nChannels = 2; // 2 channels = stereo
wfx.cbSize = 0; // no extra info
wfx.wFormatTag = WAVE_FORMAT_PCM; //PCM format
wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

// then let's open the device

if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR)

    fprintf(stderr, "unable to open Wave Mapper device.\n");
    Sleep(1000);
    ExitProcess(1);


// if no errors then close it
printf("The Wave Mapper device was opened successfully!\n");

//load and play file
if((block = loadAudioBlock("ding.raw", &blockSize)) == NULL)

    fprintf(stderr, "Unable to load file\n");
    Sleep(1000);
    ExitProcess(1);

writeAudioBlock(hWaveOut, block, blockSize);
Sleep(1000);
waveOutClose(hWaveOut);
return 0;

每次我运行程序时,我都会得到:“无法加载文件”输出。我在与我的 exe 相同的目录中有“ding.raw”文件。我也尝试过将完整路径设置为“C://path”和“C:/path”,但是编译器只会给我更多关于无法加载 pdb 文件的错误。

有什么想法吗?我正在使用 Visual Studio 2012 Professional IDE 和编译器。

【问题讨论】:

CreateFile调用失败时,使用GetLastError看看你有什么错误。错误代码列表可以在here找到。 “Windows”操作系统使用反斜杠作为路径。所以完整路径应该是C:\\path\\ding.raw 我的怀疑是您将文件名中的普通字符串与宽字符串混合在一起(const char * 是普通字符串,而LPCWSTR 是宽字符串)。 如果我不使用 LPCWSTR,CreateFile() 函数会报错。最好的补救方法是什么? @Tyler - 演员只是告诉编译器不要抱怨,它不会修改参数。尝试将参数更改为const wchar_t* 并传递一个宽字符串L"C:/path/ding.raw" 【参考方案1】:

而不是使用标准 char 你应该使用例如_TCHARLPCTSTR 无处不在。这将使您传递的所有字符串和字符串指针都是正确的。

查看_tmainargv 参数,您会发现它使用_TCHAR 而不是char。这是因为 Windows 同时支持普通字符和 Unicode 字符,这取决于几个宏。参见例如here 了解更多信息。

因此,要解决可能是您的问题(因为您没有得到实际的错误代码,请参阅我对 GetLastError 的评论),您应该像这样更改函数:

void *loadAudioBlock(LPCTSTR filename, DWORD* blockSize)

    // ...

    if((hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
    return NULL;

    // ...

然后这样称呼它:

// ...

void *block;

if((block = loadAudioBlock(_T("C:\\path\\ding.raw"), &blockSize)) == NULL)

    fprintf(stderr, "unable to open Wave Mapper device, error code %ld.\n", GetLastError());
    Sleep(1000);
    ExitProcess(1);


// ...

如您所见,我还更改了返回类型,因为文件是二进制文件,没有任何可读文本。

【讨论】:

文件仍未打开。我只是得到这个错误代码:ERROR_FILE_NOT_FOUND 2 (0x2) 系统找不到指定的文件。所以这并没有多大帮助。 @TylerJarjoura 即使您提供文件的完整路径?当然是正确的斜线。【参考方案2】:
LPSTR loadAudioBlock(const char* filename, DWORD* blockSize)

     if((hFile = CreateFile(CA2T(filename), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
return NULL;

查看 ATL 转换宏:http://msdn.microsoft.com/en-us/library/87zae4a3%28v=vs.80%29.aspx 仅转换 const char* LPCWSTR 不起作用。

【讨论】:

编译器说“CA2W”是一个未声明的标识符。

以上是关于无法使用 CreateFile 函数打开文件的主要内容,如果未能解决你的问题,请参考以下文章

无法通过 CreateFile 打开设备,ERROR_INVALID_FUNCTION

使用CreateFile读写文件

CreateFile打开文件或者打开目录

Createfile打开磁盘的格式要求

delphi 怎么判断一个文本文件正在被使用

CreateFile,ReadFile等API详解(或者说MSDN的翻译)