How to open a file?

Alright, I'm back.

I have a question about how to open files.

I have been watching this one Indian guy explaining how to open a file (video is here at https://www.youtube.com/watch?v=-iMGhSlvIR0). However, in his video, he uses fopen(), which is unsecure according to Visual Studio. Visual Studio recommends I use fopen_s(), which I do.

Now, I try to open the file, but it just so happens that it gives me an assertion error when I try to actually read something (because the FILE* struct returns NULL for some reason, and thus the fread() basically reads nothing and gives a breakpoint).

When I try to debug it, I find that I need to use a perror() function that only prints to the console log, which I don't have (and miserably tried to redirect to a .txt file with stderr and stdout).

My code is below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//opens files
void openFile(HWND hWnd) {

    tagOFNA ofn;

    const int maxInt = 100;

    char fileName[maxInt];

    memset(&ofn, 0, sizeof(tagOFNA));
    
    ofn.lStructSize = sizeof(tagOFNA);
    ofn.hwndOwner = hWnd;
    ofn.lpstrFile = fileName;
    ofn.lpstrFile[0] = '\0';
    ofn.nMaxFile = maxInt;
    ofn.lpstrFilter = "PRTD files\0*.prtd\0";
    ofn.nFilterIndex = 1;

    GetOpenFileNameA(&ofn);

    displayFile(ofn.lpstrFile, hWnd);

}

void displayFile(char* name, HWND hWnd) { //I pass the name and window to this function

    FILE* file;
    stdout > (FILE*)"log.txt";
    stderr > stdout;
    file = (FILE*)fopen_s(&file, name, "rb");
    if (file != NULL) {

        fseek(file, 0, SEEK_END);
        int _size = ftell(file);
        rewind(file);
        char* data = new char(_size + 1);
        fread(data, _size, 1, file);
        data[_size] = '\0';

        MessageBoxA(hWnd, data, "hi", MB_OK);

    } else {

        perror("Error: ");
        MessageBoxA(hWnd, "bruh", "bruh moment error", MB_OK); //always happens

    }

}


Can I fix this, or do I have to do an entirely different method?

Much appreciated.

Edit: Before anybody starts hogging on the functions, they are declared already.
Last edited on
Do you intend to learn C++? You've presented a pure C program here.

The fact that you had to perform this unsafe type conversion
file = (FILE*)fopen_s(&file, name, "rb");
Should have warned you that you were doing something wrong.

As any reference page tells you
https://en.cppreference.com/w/c/io/fopen
fopen_s doesn't return a FILE*
Last edited on
Step 1 is not ignoring your return results.
https://docs.microsoft.com/en-us/windows/win32/api/commdlg/nf-commdlg-getopenfilenamea

Specifically,
msdn wrote:

If the buffer is too small, the function returns FALSE and the CommDlgExtendedError function returns FNERR_BUFFERTOOSMALL. In this case, the first two bytes of the lpstrFile buffer contain the required size, in bytes or characters.


Blindly stumbling forward assuming all is well will lead to trouble.

> perror("Error: ");
Step 2 is telling us what your actual reason for failure is.
Was it "file not found", or something else?

1
2
    stdout > (FILE*)"log.txt";
    stderr > stdout;

What do you imagine is happening here?
This isn't the shell, where you can redirect one stream to another.
It's just two useless comparisons.

Oh, and learn how to use the debugger.
At least as far as being able to
- set a breakpoint
- examine variables
- single step the code.

At least you'll be able to see what you've got.

@mbozzi I don't mean to be rude or anything, but I was following the video that I have linked. That was why some things are kidna weird and I need help.

The file thing was giving me an error when I tried to get the return value of fopen_s() as his tutorial was direct assignment, so I did that, which led to an "unsuitable type conversion from errno_t to FILE*" (whatever errno_t is, never dealt with it in my life). Thus typecast. Yeaaahhh, need some guidance on that one.
@salem c
I have put the following to get error information:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool check = GetOpenFileNameA(&ofn);
    DWORD err;
    if (!check) {
        err = CommDlgExtendedError();
        if (err == FNERR_BUFFERTOOSMALL) {
            MessageBoxA(hWnd, "buffer too small", "bruh moment error", MB_OK);
        } else if (err == FNERR_FILENAMECODES) {
            MessageBoxA(hWnd, "file name codes?", "bruh moment error", MB_OK);
        } else if (err == FNERR_INVALIDFILENAME) {
            MessageBoxA(hWnd, "invalid file name", "bruh moment error", MB_OK);
        } else if (err == FNERR_SUBCLASSFAILURE) {
            MessageBoxA(hWnd, "sub class failure", "bruh moment error", MB_OK);
        }
    }


aaaaand, nothing pops up except the one error in displayFile().

I'll use the debugger a bit more rigorously with this one.
Last edited on
You're not being rude! The right call looks like
1
2
FILE* file;
errno_t e = fopen_s(&file, name, "rb");


errno_t is the type of errno, C's global thread-local error number.
Pass it to strerror to fill a buffer with an error description. Certain functions specified by POSIX and the C standard may modify it to indicate success or failure.
Last edited on
@mbozzi Ok. Whoa there pardner.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void displayFile(char* name, HWND hWnd) {

    FILE* file;
    errno_t success = fopen_s(&file, name, "rb");
    if (file != NULL) {

        fseek(file, 0, SEEK_END);
        int _size = ftell(file);
        rewind(file);
        char* data = new char[_size + 1];
        fread(data, _size, 1, file);
        data[_size] = '\0';

        MessageBoxA(hWnd, data, "hi", MB_OK);

    } else {

        char errorMsg[50];
        strerror_s(errorMsg, 50, NULL);
        MessageBoxA(hWnd, errorMsg, "bruh moment error", MB_OK);

    }

}


Put this into my code, and voila! It works. I can sleep earlier now (2:37am lol). But now (somehow) it has returned my very precious "pee" from the file! Thank you.

Edit: Just realized that the "new char" portion was wrong (I put round brackets instead of square brackets, causing a heap corruption). Fixed it to make sure I don't screw others over need they copy the code.
Last edited on
Topic archived. No new replies allowed.