Hello, I'm playing with win API functions readFile and WriteFile.
Is it possible to open file using CreateFile in binary mode just like using fopen standard C function.
I tried with function WriteFile to write string to a file but it seems that file is opened in textual mode. What I'm trying to do is to open file in binary mode and then to write strings so that cannot be opened and examined with Notepad.

Thank you very much

Recommended Answers

All 13 Replies

There's no way to specify the orientation of a file opened by CreateFile, it's always binary. ReadFile and WriteFile work with raw bytes.

>What I'm trying to do is to open file in binary mode and then to write
>strings so that cannot be opened and examined with Notepad.
Printable characters in the character set will always be readable by Notepad, whether you're using binary or text orientation. If you want your strings to be unreadable, you need to encrypt them somehow rather than just write them straight to the file:

#include <windows.h>

int main ( void )
{
  HANDLE out = CreateFile ( "test.txt", FILE_WRITE_DATA, 0, NULL,
    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  char s[] = "This is a test";
  int i, j;
  int n;

  for ( i = 0, j = sizeof s - 1; i <= j; i++, j-- ) {
    s[i] ^= s[j] ^ 194837U;
    s[j] ^= s[i] ^ 3876U;
  }

  WriteFile ( out, s, sizeof s, &n, NULL );
  CloseHandle ( out );

  return 0;
}

However, you can directly write numbers and other non-string data without the encryption, and it will be unrecognizable when opened with Notepad:

#include <windows.h>

int main ( void )
{
  HANDLE out = CreateFile ( "test.txt", FILE_WRITE_DATA, 0, NULL,
    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  int i = 12345;
  int n;

  WriteFile ( out, &i, sizeof i, &n, NULL );
  CloseHandle ( out );

  return 0;
}

Thanks Narue, I understand now

please, can you check if this is a correct way of reading file:
first, file is open for both writing and reading

hFile = CreateFile("MYFILE.TXT",           // open MYFILE.TXT 
                GENERIC_WRITE | GENERIC_READ,              
                FILE_SHARE_READ,           // share for reading 
                NULL,                      // no security 
                OPEN_ALWAYS,             // existing file only 
                FILE_ATTRIBUTE_NORMAL,     // normal file 
                NULL);                     // no attr

second I want to read contents of a file and display it on screen (I know that file contents are sentences (strings) like
"This is first sentence"
"This is second sentence"
so this is code for reading:

while(ReadFile(hFile, buf, sizeof buf, &dw_bytes_read, NULL) && dw_bytes_read != 0)
	{
		WriteFile(hStdOut, buf, dw_bytes_read, &dw_bytes_written, NULL);
	}

I had one nasty problem, At first I tried this:

while(ReadFile(hFile, buf, sizeof buf, &dw_bytes_read, NULL)){...

but program ended up in an infinite loop (not like fwrite in C) and that way with dw_bytes_read it appears to work fine.
Can you suggest me other, better, way of doing this if this is not OK

Thanks

Couldn't you just do something like this? Remeber if this sucks I am not good at the API ;)

#include <windows.h>
#include <iostream>

int main()
{
    char buf[30] = {'\0'};  //Null terminate
    LPVOID lpMsgBuf; 
    DWORD byteWritten = 0;
    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    BOOL ReadFileReturn;
    
    HANDLE hFile = CreateFile("MYFILE.TXT",    // open MYFILE.TXT 
                GENERIC_WRITE | GENERIC_READ,              
                FILE_SHARE_READ,               // share for reading 
                NULL,                          // no security 
                OPEN_EXISTING,                   // existing file only 
                FILE_ATTRIBUTE_NORMAL,         // normal file 
                NULL);                         // no attr

    ReadFileReturn = ReadFile(hFile,buf,30,&byteWritten,NULL);    
    if(ReadFileReturn)
    {
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                      NULL,
                      GetLastError(),
                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                     (LPTSTR) &lpMsgBuf,
                      0,
                      NULL);
        WriteFile(hStdOut,buf,sizeof buf,NULL,NULL);
        
    }
    else
    {
        WriteFile(hStdOut,"It Failed",sizeof "It Failed",NULL,NULL);
        
    }
    std::cin.get();
    return 0;
}

;

>OPEN_ALWAYS, // existing file only
OPEN_ALWAYS creates the file if it doesn't exist. If you want CreateFile to fail if the file doesn't exist, use OPEN_EXISTING.

>but program ended up in an infinite loop
That's because with the way you open the file, reaching end-of-file still returns success.

>Can you suggest me other, better, way of doing this if this is not OK
Well, there's nothing wrong with it, so it all boils down to style preference.

>Couldn't you just do something like this?
Sure, but where's the loop? ;)

What I'm trying to do is to open file in binary mode and then to write strings so that cannot be opened and examined with Notepad.

I am not sure if writing strigs in binary mode is a good idea.
Either you will end up writing the memory locations to the file, which would not be useful in the second time around when you open it or you will end up writng human readable stuff any way.

I think what you are looking for is some encrypting mechanism so that you could hide the strings from the others.

----------------------

Programming ( Assignment / Project ) Help

>I am not sure if writing strigs in binary mode is a good idea.
Only if you write the file with CreateFile and WriteFile, then read it using a FILE* opened with text orientation. Then it's possible to have conversion issues depending on the contents of the strings. But as long as the file is consistently read and written as binary, there's no problem.

>Either you will end up writing the memory locations to the file
No, you wouldn't. WriteFile takes a pointer and writes the contents of that pointer, so the only way to get WriteFile to write the addresses is if you had an array of pointers representing the strings and passed it like this:

char *lines[N];

...

WriteFile ( h, lines, N * sizeof *lines, &n, NULL );

Thank you all for replies. Usually I do all file manipulation stuff with fopen, fwrite, fread and etc, but I wanted to know how this is done with API. Also I've read somewhere that C function fopen end up on CreateFile (under windows os) and that "would be wise" to use it directly to gain better performance. I don't know if this is true, I doubt it.

Thanks again

yes, its true that with M$ compilers fopen and fstream eventually use win32 api functions. But there are a lot of reasons not to use win32 api for reading/writing text files and buffered i/o. Using either fstream or fgets() its really easy to read just one line of text (up to CR/LF), but win32 api its not so easy because you, the programmer, have to duplicate the functionality of fgets().

Bottom line: use win32 api directly only if speed is important to your program. Otherwise use either fstream or FILE and associated functions. Personally, I hate fstream because I think its ugly and very clumbsy. The only advantage is getline() used with std::string object. But for formatted i/o you can't beat the ease of fprintf() and fscanf().

the easiest way is that you save the file with the extension of (.bin) instead of (.txt)

the easiest way is that you save the file with the extension of (.bin) instead of (.txt)

The file extension has nothing to do about file contents. Changing the file extension from .txt to .bin will do nothing (other than renaming the file)

extension (.bin) means that the file is in binary mode and Windows will open it in cmd (command prompt), and it can solve the problem.

And if you don't like it.. try doing this

int      Buffer[5] = {2, -2, 3, 40};
    HANDLE   HandleFileW;
    DWORD    Written;
    HandleFileW = CreateFileW(TEXT("test.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    if (HandleFileW != INVALID_HANDLE_VALUE)
    {
        WriteFile(HandleFileW, Buffer, 5 * sizeof(int) , &Written, 0);
        CloseHandle(HandleFileW);
        cout << "File create successfully . . ." << endl << endl;
    }
    else
    {
        DWORD    ErrorCode;
        wchar_t    ErrorMessage[256];
        HANDLE    hIn = GetStdHandle(0);
        ErrorCode = GetLastError();
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,ErrorCode, 0, ErrorMessage, 256, NULL);
        wprintf(L"%s\n", ErrorMessage);
    }

>>extension (.bin) means that the file is in binary mode

No it doesn't, as the code you posted illustrates. The file extension has nothing to do with whether the file is in binary or text mode. Your own program proved it.

if you wanna see your file as you have written on it... you can use ReadFile API... it will give you the actual written data (and not the ASCII Characters)...

The reason why file is not looking correct when you open it in notepad is very simple.... It is because notepad is made for ASCII Charachter Set, it means that the notepad reads 2 bytes at a time and produce a ASCII character against it.... so if you have written some integers or your own datatype... it's size is changed (as int size is 4bytes) so the number you have written in the file has now been splited into two ASCII charaters....

But when you read the same file using ReadFile API, it actually reads Binary of the data that you have written and produce a charachter (or number ...) against it...

I hope you understand that....

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.