C++ 读取文件 Win32 API
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4010709/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ReadFile Win32 API
提问by Abid Ali
i want to read a file.. but.. when i debug my program it runs but a pop up appears and says system programming has stopped working and in the console, it`s written that Press enter to close the program. my code is ::
我想读取一个文件..但是..当我调试我的程序时,它运行但出现一个弹出窗口并说系统编程已停止工作,并且在控制台中,它写道按回车键关闭程序。我的代码是 ::
// System Programming.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "iostream"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hin;
HANDLE hout;
TCHAR buff[20]= {'q','2','3'};
TCHAR buff2[20]={'a','v'};
hin = CreateFile(_T("Abid.txt"),GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if(hin == INVALID_HANDLE_VALUE)
{
cout<<"error";
}
WriteFile(hin,buff,40,0,NULL);
CloseHandle(hin);
hout = CreateFile(_T("Abid.txt"),GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if(hout == INVALID_HANDLE_VALUE)
{
cout<<"error";
}
ReadFile(hout,buff2,40,0,NULL);
CloseHandle(hout);
return 0;
}
回答by Abyx
According to MSDN, lpNumberOfBytesWritten paremeter can be NULL only when the lpOverlapped parameter is not NULL. So the calls should be
根据 MSDN,lpNumberOfBytesWritten 参数只有在 lpOverlapped 参数不为 NULL 时才能为 NULL。所以电话应该是
DWORD nWritten;
WriteFile(hin, buff, 40, &nWritten, NULL);
and
和
DWORD nRead;
ReadFile(hout, buff2, 40, &nRead, NULL);
Also, rename hinand hout.
此外,重命名hin和hout。
回答by Cheers and hth. - Alf
Others have already answered your question. This is about the code.
其他人已经回答了你的问题。这是关于代码的。
// Your code:
// System Programming.cpp : Defines the entry point for the console application.
//
Just remove that comment. It isn't true. :-) The entry pointfor your program is where the machine code starts executing, and with the Microsoft toolchain it's specified by the /entry
linker option.
删除那个评论就行了。这不是真的。:-) 程序的入口点是机器代码开始执行的地方,在 Microsoft 工具链中,它由/entry
链接器选项指定。
Note that Microsoft's documentation is generally confused about entry points, e.g. it has always, one way or other, documented incorrect signature for entry point.
请注意,Microsoft 的文档通常对入口点感到困惑,例如,它总是以一种或其他方式记录了入口点的错误签名。
It's one of the most infamous Microsoft documentation errors, and, given that it's persisted, in various forms, for 15 years, I think it says something (not sure exactly what, though).
这是最臭名昭著的 Microsoft 文档错误之一,鉴于它以各种形式持续存在 15 年,我认为它说明了一些事情(但不确定到底是什么)。
// Your code:
#include "stdafx.h"
You don't need this automatically generated header. Instead use <windows.h>
. A minimal way to include <windows.h>
for your program would be
您不需要这个自动生成的标题。而是使用<windows.h>
. 包含<windows.h>
在您的程序中的最小方法是
#undef UNICODE
#define UNICODE
#include <windows.h>
For C++ in general you'll want to also make sure that STRICT
and NOMINMAX
are defined before including <windows.h>
. With modern tools at least STRICT
is defined by default, but it doesn't hurt to make sure. Without it some of declarations won't compilewith a C++ compiler, at least not without reinterpret casts, e.g. dialog procedures.
一般来说,对于 C++,您还需要确保STRICT
和NOMINMAX
在包含<windows.h>
. 现代工具至少STRICT
是默认定义的,但确保没有坏处。没有它,一些声明将无法使用 C++ 编译器进行编译,至少在没有重新解释强制转换的情况下无法编译,例如对话过程。
// Your code:
#include "iostream"
using namespace std;
Almost OK.
差不多好了。
Do this:
做这个:
#include <iostream>
using namespace std;
The difference is where the compiler searches for headers. With quoted name it searches in some additional places first (and that's all that the standard has to say about it). With most compilers those additional places include the directory of the including file.
不同之处在于编译器搜索标头的位置。使用带引号的名称,它首先在其他一些地方进行搜索(这就是标准所要说明的全部内容)。对于大多数编译器,这些附加位置包括包含文件的目录。
// Your code:
int _tmain(int argc, _TCHAR* argv[])
Oh no! Don't do this. It's a Microsoft "feature" that helps support Windows 9.x. And it's only relevant when you're using MFC linked dynamically and you're targeting Windows 9.x; without MFC in the picture you'd just use the Microsoft Unicode layer.
不好了!不要这样做。这是 Microsoft 的一项“功能”,有助于支持 Windows 9.x。只有当您使用动态链接的 MFC 并且您的目标是 Windows 9.x 时,它才相关;如果图片中没有 MFC,您只需使用 Microsoft Unicode 层。
Area you really targeting Windows 9.x with an app using dynamically linked MFC?
您是否真的针对 Windows 9.x 使用动态链接 MFC 的应用程序?
Instead, do ...
相反,做...
int main()
... which is standard, or use the Microsoft language extension ...
...这是标准的,或使用 Microsoft 语言扩展 ...
int wMain( int argc, wchar_t* argv[] )
... if you want to handle command line arguments the "easy" way.
...如果您想以“简单”的方式处理命令行参数。
// Your code:
{
HANDLE hin;
HANDLE hout;
TCHAR buff[20]= {'q','2','3'};
TCHAR buff2[20]={'a','v'};
The TCHAR
stuff is just more of that MFC in Windows 9.x support stuff.
这些TCHAR
东西更多的是 Windows 9.x 中的 MFC 支持的东西。
Apart from being totally unnecessary (presumably, you're not really targeting Windows 9.x, are you?), it hides your intention and hurts the eyes.
除了完全没有必要(大概,您并不是真正针对 Windows 9.x,是吗?),它还隐藏了您的意图并伤害了眼睛。
Did you mean ...
你的意思是 ...
char buff[20] = {'q', '2', '3'};
... perhaps?
... 也许?
// Your code:
hin = CreateFile(_T("Abid.txt"),GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if(hin == INVALID_HANDLE_VALUE)
{
cout<<"error";
}
As others have mentioned, OPEN_EXISTING
isn't logical when you're creating the file, and the count pointer argument can't be 0 for your usage.
正如其他人所提到的,OPEN_EXISTING
在创建文件时不合逻辑,并且计数指针参数不能为 0 供您使用。
When using <windows.h>
, with UNICODE
defined as it should be, the filename argument should be specifed as L"Abid.txt"
.
使用 时<windows.h>
,UNICODE
按原样定义,文件名参数应指定为L"Abid.txt"
.
Cheers & hth.,
干杯 & hth.,
回答by Michael Burr
The problem is that you're passing a NULL pointer in for the lpNumberOfBytesWritten
/lpNumberOfBytesread
parameter. While this is an optional parameter, there's a condition:
问题是您正在为lpNumberOfBytesWritten
/lpNumberOfBytesread
参数传递一个 NULL 指针。虽然这是一个可选参数,但有一个条件:
This parameter can be NULL only when the lpOverlapped parameter is not NULL
只有当 lpOverlapped 参数不为 NULL 时,该参数才能为 NULL
Also, you may have the size of your buffers wrong:
此外,您的缓冲区大小可能有误:
WriteFile(hin,buff,40,0,NULL); // says that buff has 40 bytes
ReadFile(hout,buff2,40,0,NULL); // says that buff2 has 40 bytes
But if you're compiling for ANSI instead of UNICODE, these will only be 20 bytes in size.
但是,如果您为 ANSI 而不是 UNICODE 进行编译,则这些大小只有 20 个字节。
You should probably use sizeof(buff)
and sizeof(buff2)
instead.
您可能应该使用sizeof(buff)
andsizeof(buff2)
代替。
回答by Steve Townsend
Assuming your initial code attempts to create the file as a new file, then you cannot use OPEN_EXISTING
, you have to use OPEN_ALWAYS
(or some other creational variant) on this call.
假设您的初始代码尝试将文件创建为新文件,那么您不能使用OPEN_EXISTING
,您必须OPEN_ALWAYS
在此调用中使用(或某些其他创建变体)。
The OPEN_EXISTING
usage for readback will be OK.
OPEN_EXISTING
回读的用法是可以的。
btw once this is fixed the WriteFile
calls causes an access violation, as you are trying to write more bytes that your array contains.
顺便说一句,一旦修复此问题,WriteFile
调用会导致访问冲突,因为您正在尝试写入数组包含的更多字节。