tags:

views:

88

answers:

4

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;
}
A: 

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.

The OPEN_EXISTING usage for readback will be OK.

btw once this is fixed the WriteFile calls causes an access violation, as you are trying to write more bytes that your array contains.

Steve Townsend
so what do i do? Create_New?
Abid
@Abid, that would work - check the docs here: http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx
Steve Townsend
A: 

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:

This parameter can be NULL only when the lpOverlapped parameter is not 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.

You should probably use sizeof(buff) and sizeof(buff2) instead.

Michael Burr
+2  A: 

According to MSDN, lpNumberOfBytesWritten paremeter can be NULL only when the lpOverlapped parameter is not NULL. So the calls should be

DWORD nWritten;
WriteFile(hin, buff, 40, &nWritten, NULL);

and

DWORD nRead;
ReadFile(hout, buff2, 40, &nRead, NULL);

Also, rename hin and hout.

Abyx
+1  A: 

Hi. 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 point for your program is where the machine code starts executing, and with the Microsoft toolchain it's specified by the /entry linker option.

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.

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).

// 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

#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 compile with a C++ compiler, at least not without reinterpret casts, e.g. dialog procedures.

// 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.

Area you really targeting Windows 9.x with an app using dynamically linked MFC?

Instead, do ...

int main()

... which is standard, or use the Microsoft language extension ...

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.

Apart from being totally unnecessary (presumably, you're not really targeting Windows 9.x, are you?), it hides your intention and hurts the eyes.

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.

When using <windows.h>, with UNICODE defined as it should be, the filename argument should be specifed as L"Abid.txt".

Cheers & hth.,

Alf P. Steinbach
While I agree with the sentiment of your points: 1. "stdafx.h" is necessary with the default project settings (of precompiled headers) and the compiler will panic if it can't find it. 2. char buff[20] = ['q', '2', '3']; ??? When were []'s legal in an initializer list? It is {}.
Chris Becke
@Chris: regarding your points (presumably) about using the Visual Studio IDE, no, "stdafx.h" is not even necessary in Visual Studio. It's simply there by default for certain kinds of Visual Studio projects. Just turn off precompiled headers in the project settings. Also, there's no such thing as the compiler panicking. Regarding the typo, thanks.
Alf P. Steinbach
@Chris: also, the name does not have to be "stdafx.h", you can specify any file you want on the command line / project options.
Skizz
When giving prescriptive advice that removes the default precompiled header: include the settings that will enable the project to run without it.
Chris Becke
@Chris: the settings depend on the IDE. One would have to ask the OP which IDE, if any, he's using, and whether his code was generated by Visual Studio (likely), or by some other IDE, or whether he just copied something he'd seen. Chances are that some pat advice about the Visual Studio IDE would be right on. And here at SO people are rewarded for spouting that kind of nonsense. It's good because SO attracts different people than the older forums, but it's bad because it discourages thinking, just using recipes. Happily the Visual C++ *compiler* does not use precompiled headers by default.
Alf P. Steinbach