-1

I am using standard file-handler API to read the file , currently I have used a char* buffer to read the data, but I want to use string so I can avoid calloc() use. I tried to pass the string address to the ReadFile() function, but it's not working. Could you please help me???

l_FileHandle = CreateFileA(inputFilePath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
   
l_FileSize = GetFileSize(l_FileHandle, NULL);

char * l_FileBuffer = NULL;

l_FileBuffer = (char *)calloc(l_FileSize, sizeof(char));
     
ReadFile(l_FileHandle,(void *)(l_FileBuffer), l_FileSize, &lpNumberOfBytesRead, lpOverlapped);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • This incurs a fairly costly memory allocation no matter where you want to store the data. [Memory-mapped files](https://learn.microsoft.com/en-us/windows/win32/memory/file-mapping) offer a far less expensive alternative. – IInspectable Feb 14 '22 at 08:45

2 Answers2

1

You can't pass in the address of the string itself, but you can pass in the address of its internal character buffer. Just make sure it has been allocated first.

l_FileHandle = CreateFileA(inputFilePath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
   
l_FileSize = GetFileSize(l_FileHandle, NULL);

string l_FileBuffer(l_FileSize, '\0');
     
ReadFile(l_FileHandle, l_FileBuffer.data(), l_FileSize, &lpNumberOfBytesRead, lpOverlapped);

Note that the non-const version of data() requires C++17 or later. For C++11..14, you can use &l_FileBuffer[0] instead. Prior to C++11, that is not guaranteed to work, but in practice it will work in most implementations.

For a more standard way to read a file into a string, see How do I read an entire file into a std::string in C++?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

The proper use is std::vector.

l_FileSize = GetFileSize(l_FileHandle, NULL);
std::vector<char>  l_FileBuffer(l_FileSize);
ReadFile(l_FileHandle,l_FileBuffer.data(), l_FileSize, &lpNumberOfBytesRead, lpOverlapped);

Since vector by the standard ensures that the items are stored continuously.

Note that even in this way you are still implicitly allocating memory, it's just that the vector will release it automatically on destruction. If the file is known to be very small then you can afford to load it on a stack-allocated buffer instead.

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78
  • Thank you Michael !! I am curious is there any way we can use string..?? – Saurabh Fodekar Feb 14 '22 at 07:19
  • string also has a data() member but it's mostly used in storing *strings*, it's not as flexible in manipulation as vector. – Michael Chourdakis Feb 14 '22 at 07:21
  • 1
    `string::data` is also contiguous. – zdf Feb 14 '22 at 07:40
  • You can copy the data from a `std::vector` quite easily to a `std::string`, for example `std::string result(l_FileBuffer.begin(), l_FileBuffer.end())`. Unfortunately, that copies rather than moves the data. – Peter Feb 14 '22 at 08:16