How to Append wstring and write it to a file

1.6k views Asked by At

I have been trying for 1 hour to find a solution for this but nothing is working. I am using the FindFirstFile function to get a list of files/folders. This part works fine, but when I try to use the cFilename of it, its gives a wstring and its almost useless. I tried to convert it to a char to write to a file, it gives me error. I tried to write wstring to file, it messes up and writes the first filesystem object followed by many nulls. This is really frustrating me and I really want help. My code:

{
      //wstring writedata = search_data.cFileName + "\n"; //cant append newline to it
      //printf(search_data.cFileName); //works
      //wstring newline = "\n"; //Cant create newline in wstring
      //fwrite(writedata, 1, sizeof(writedata), directorycontents); //writedata I cant set it
      //fwrite(search_data.cFileName, 1, sizeof(search_data.cFileName), directorycontents); //writes first fileobject and a lot of nulls, fail
  if(FindNextFile(handle, &search_data) == FALSE){
          break;}
   }

Also I would really appreciate it if someone could show me how to convert a wstring to a char[]. I cant find out how to do this either, and it was the first thing I tried.

#include <windows.h>
#include <stdio.h>
#include <string>
using namespace std;
int main(int argc, char* argv[]){WIN32_FIND_DATA search_data;
   memset(&search_data, 0, sizeof(WIN32_FIND_DATA));
   HANDLE handle = FindFirstFile("c:\\*", &search_data);
   FILE *directorycontents = fopen("C:\\testwrite.txt", "w+");
   while(handle != INVALID_HANDLE_VALUE)
   {

      wstring newline = L"\n"; //Cant create newline in wstring
      search_data.cFileName += newline;
      string test = cstr(search_data.cFileName);
      search_data.cFileName += newline;
fwrite(search_data.cFileName, 1, sizeof(search_data.cFileName), directorycontents);
  if(FindNextFile(handle, &search_data) == FALSE){
          break;}
   }}
1

There are 1 answers

1
George On BEST ANSWER

Fix

// enable / disable both of them to enable/disable unicode
//#define UNICODE
//#define _UNICODE

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

int main(int argc, char* argv[]){

   WIN32_FIND_DATA search_data;
   memset(&search_data, 0, sizeof(WIN32_FIND_DATA));
   HANDLE handle = FindFirstFile(TEXT("c:\\*"), &search_data);
   FILE *directorycontents = fopen("C:\\testwrite.txt", "wb");
   while(handle != INVALID_HANDLE_VALUE)
   {
    fwrite(search_data.cFileName, 1, _tcslen(search_data.cFileName) * sizeof(TCHAR), directorycontents);
    _fputts(TEXT("\r\n"), directorycontents);
    if(FindNextFile(handle, &search_data) == FALSE)
      break;
   }
}

Other problems

search_data.cFileName += newline;

This line is problematic because the type of cFileName is TCHAR[] (a TCHAR array) and the type of newline is wstring. These types are not compatible.

You can not append to a fixed size array using the += operator.

cstr(search_data.cFileName)

This has no meaning. The function cstr can only be used on types of string objects.

Learn more about null-terminated strings

http://en.wikipedia.org/wiki/Null-terminated_string

cFileName is a null-terminated string. So for example when TCHAR is char (_UNICODE not defined) then the string "Hello" looks like this in memory:

['H','e','l','l','o', '\0', ...]

Here each element takes one byte, the ... can be any junk. cFileName always has the capacity of 260 elements, but this doesn't mean the lenght of the string inside cFileName is 260 long. Actually the maximal length of the string inside cFileName is 259, because you always must have a terminating '\0' element.

Learn more about TCHAR

http://www.codeproject.com/Articles/76252/What-are-TCHAR-WCHAR-LPSTR-LPWSTR-LPCTSTR-etc

TCHAR    cFileName[MAX_PATH]; //this is how cFileName is defined
sizeof(TCHAR) == 2 // when _UNICODE is defined
sizeof(TCHAR) == 1 // when _UNICODE is defined
  • TCHAR is wchar_t (2 bytes) when _UNICODE is defined
  • TCHAR is char (1 byte) when _UNICODE is not defined.
  • MAX_PATH is defined to 260
  • Therefore calling sizeof(cFileName) will give you 260 (when _UNICODE is not defined), or 520 (when _UNICODE is defined)

To get a length of a string which consists of TCHAR you have to use the _tcslen macro. This macro expands to strlen or wcslen depending on the _UNICODE define.

You have to know that the array cFileName having the size of 260 does not mean that your string have the same length. cFileName stores a C-style string (regardless of _UNICODE) meaning it terminates with a zero element in the array.

If you want to avoid using unicode, make sure that _UNICODE is not defined before including windows.h. You can also achieve this by setting the character set to "Not set" as shown in the article.

TCHAR has been in use to make it easier to compile unicode and non-unicode versions of the same program, just by toggling a define.

Conversion between wchar_t and char strings: http://msdn.microsoft.com/en-us/library/5d7tc9zw.aspx

Learn more about the various string types

http://www.codeproject.com/Articles/2995/The-Complete-Guide-to-C-Strings-Part-I-Win32-Chara http://www.codeproject.com/Articles/3004/The-Complete-Guide-to-C-Strings-Part-II-String-Wra