0

I can read a file with Unicode path like this:

#include "iostream"
#include "windows.h"
using namespace std;

///--- variables ---///
//-- DWORD --//
DWORD dwBytesToRead = 0;

//-- HANDLE --//
HANDLE hFileHandle;

//-- wchar_t array --//
wchar_t a_wcContentsOfFile[999999] = {0};

//-- WINBOOL --//
WINBOOL wbResult;

int main()
{
    hFileHandle = CreateFileW(L"D:\\Çağatay.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if(hFileHandle != NULL)
    {
        wbResult = ReadFile(hFileHandle, a_wcContentsOfFile, 999999 - 1, &dwBytesToRead, NULL);
        if(wbResult != 0)
        {
            if(dwBytesToRead > 0)
            {
                a_wcContentsOfFile[dwBytesToRead + 1] = '\0';
                wprintf(L"%s\n", a_wcContentsOfFile + 1);
            }
        }
        CloseHandle(hFileHandle);
    }

    getchar();
    return 0;
}

I have used this website as guideline:

https://www.installsetupconfig.com/win32programming/windowsfileapis4_22.html

But I want to write contents of the file to wstring, not stdout.

How can I do this?

12
  • 2
    If you don't need something special from the WinAPI, why not use std::wifstream? Re: " I want to write contents of the file to wstring" - That's a one-liner using std::wifstream . Commented Sep 2, 2024 at 20:36
  • @TedLyngmo ifstream does not support non-ASCII paths. For example Ç and ğ are not ASCII. Commented Sep 2, 2024 at 20:38
  • Style note: comments that simply repeat the code aren't helpful. //-- HANDLE --// followed by HANDLE hHandle; is just distracting. Not to mention the name hHandle, which says nothing. Windows programs tend to use prefixes like h to describe the type of the variable (h stands for HANDLE), but many folks these days things that's just noise. With or without that prefix, though, give the variable a name that says what it does. hHandle should be something like fileHandle. Commented Sep 2, 2024 at 20:41
  • @PeteBecker I have already know that. Commented Sep 2, 2024 at 20:45
  • @ÇağatayKAYA What makes you think it doesn't support non-ASCII paths? std::wifstream is(std::filesystem::path(L"D:/Çağatay.txt")); and then std::wstring content(std::istreambuf_iterator<wchar_t>(is), std::istreambuf_iterator<wchar_t>{}); - Done Commented Sep 2, 2024 at 20:46

1 Answer 1

3

ReadFile() has no concept of strings or Unicode, it only knows about raw bytes.

You already know how to read the raw bytes into a wchar_t[] array (assuming the file content is encoded in UCS-2 or UTF-16, that is). Simply assign that array to a std::wstring object afterwards, eg:

std::wstring wContent;

wbResult = ReadFile(hFileHandle, a_wcContentsOfFile, sizeof(a_wcContentsOfFile), &dwBytesRead, NULL);

if(wbResult != 0)
{
    wContent.assign(a_wcContentsOfFile, dwBytesRead / sizeof(wchar_t));
}

If you know the file size ahead of time (ie, from GetFileSize() or equivalent) then you don't even need the wchar_t[] array at all, you can presize the wstring and read directly into its data buffer, eg:

DWORD dwFileSize = GetFileSize(ReadFile(hFileHandle, NULL); 

std::wstring wContent;
wContent.resize(dwFileSize / sizeof(wchar_t));

wbResult = ReadFile(hFileHandle, wContent.data(), wContent.size() * sizeof(wchar_t), &dwBytesRead, NULL);

if(wbResult == 0)
    dwBytesRead = 0;

wContent.resize(dwBytesRead / sizeof(wchar_t));

Also see: How do I read an entire file into a std::string in C++?, the solutions can be adapted for std::wstring.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.