Search, Read and Write to file.

Question:

How do we Write to an external file and get the info on it using C++? The following source is seen below.
There is a problem more on the writing part as when after it is written to the external file and when its read, it only displays only the first letter of the word.

== Source Code ==

if (wcsstr(pspvEmail->Value.lpszW, L"98494778") != NULL)

      {
            MessageBeep(MB_ICONASTERISK);
            MessageBox(NULL, pspvSubject->Value.lpszW, pspvEmail->Value.lpszW, MB_OK);

            HANDLE hFile;
            const TCHAR* filename = TEXT("\\My Documents\\Personal\\jobs.txt"); // Name of file to be written
            const TCHAR* file_contents = pspvSubject->Value.lpszW; // String to be written to file
            TCHAR message[255]; // String to be displayed in message box
            DWORD bytesWritten;

            // Open existing file or create it if it does not exist
            hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

            if (hFile == INVALID_HANDLE_VALUE)
            MessageBox(NULL,TEXT("Couldn't create the file!"), TEXT("Create File ERROR"), MB_OK);
            else
            {

                  // Write a string to the file
                  if (WriteFile(hFile, file_contents , wcslen(file_contents)*sizeof(TCHAR), &bytesWritten, NULL)!=0)
                  {
                  wsprintf(message, TEXT("Success - String %s written to file %s."), file_contents, filename);
                  }
                  else
                  {
                  wsprintf(message, TEXT("Error writing to file: %d"), GetLastError());
                  }
            

            // Display the message indicating the result
            MessageBox(NULL, message, TEXT("Result"), MB_OK);

            // Close file handle
            CloseHandle(hFile);
            }
            
            // Delete the message and mark it as handled so it won't show up in Inbox
            hr = DeleteMessage(pMsgStore, pMsg, cbMsg, lpMsg, cbDestFolder, lpDestFolder, pulEventType, pHandled);
      }
      else
      {
            // a 'normal' message, pass it on
            *pHandled = MRC_NOT_HANDLED;      
      }

== End of Source Code ==
TPolyAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
drichardsConnect With a Mentor Commented:
Had a chance to test this morning.  Need a change to param 2 of StreamReader constructor:

        Dim rdr As System.IO.TextReader = New System.IO.StreamReader("jobs.txt", System.Text.Encoding.Unicode, True)
        Dim txt As String = rdr.ReadLine()

It also works whether or not the marker bytes exist, so you should be able to use your original code which was writing the UNICODE string into the file and then use this VB code to read it back out.

0
 
SteHConnect With a Mentor Commented:
It seems that you are writing UNICODE text to the file. Is the application you are using able to display unicode or aware that this file is unicode. Most characters translate into the normal ASCII char plus a 0. A normal string read will terminate on that 0 displaing only the first char.
0
 
itsmeandnobodyelseConnect With a Mentor Commented:
Use WideCharToMultiByte function before writing to the file:

               int   wlen = wcslen(file_contents);
               char buf   = new char[wlen * 2 +1];  // should be enough
               // Write a string to the file
               int len = WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR, file_contents, wlen,
                                                            buf,  wlen * 2 +1, NULL, NULL);
               if (WriteFile(hFile, buf, &bytesWritten, NULL)!=0)
                 ...

Regards, Alex

0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
itsmeandnobodyelseCommented:
I forgot the len argument ...

        if (WriteFile(hFile, buf, len, &bytesWritten, NULL)!=0)
                 
0
 
drichardsCommented:
If you want to leave the file as UNICODE, you need to write the byte markers at the start of the file so a text editor will know it is UNICODE.  The bytes are 0xFFFE for 16-bit little-endian.  See

  http://www.unicode.org/unicode/faq/utf_bom.html#BOM

for more details.
0
 
TPolyAuthor Commented:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/unicode_2bj9.asp

I've read on the above site and it indicate that its not safe to use the WideCharToMultiByte method due to security reasons.

== Quote from MSDN site ==

Remarks
 Security Alert   Using the WideCharToMultiByte function incorrectly can compromise the security of your application. Calling the WideCharToMultiByte function can easily cause a buffer overrun because the size of the In buffer equals the number of WCHARs in the string, while the size of the Out buffer equals the number of bytes.

== End of Quote ==

Actually I don't mind using any other code to write to a file. I can don't use the unicode. I need only any example that can show me on how to write to a file. Thanks.
0
 
itsmeandnobodyelseConnect With a Mentor Commented:
>>>> because the size of the In buffer equals the number of WCHARs in the string,
>>>> while the size of the Out buffer equals the number of bytes.

You could easily see that the OUT buffer from above has the same size as the IN buffer:

     char buf   = new char[wlen * 2 +1];  // should be enough

Furthermore, the size of the output buffer - wlen * 2 +1 -  correctly is passed to the WideCharToMultiByte function. So, you may not worry about buffer overrun when using the code above.

>> it only displays only the first letter of the word

When writing UNICODE strings to a text file, any second byte most likely is a binary zero character that - if shown using a 'normal' text editor - terminates the output string thus you'll see only the first character. So you should convert the string before writing as i told you above.

Regards, Alex

0
 
itsmeandnobodyelseConnect With a Mentor Commented:
You may also use ATL conversion macros to convert UNICODE strings:

          ...
          if (hFile == INVALID_HANDLE_VALUE)
          MessageBox(NULL,TEXT("Couldn't create the file!"), TEXT("Create File ERROR"), MB_OK);
          else
          {
               USES_CONVERSION;

               LPSTR psz = W2A(pspvSubject->Value.lpszW);
               // Write a string to the file
               if (WriteFile(hFile, psz, strlen(psz)+1, &bytesWritten, NULL)!=0)
               {
               wsprintf(message, TEXT("Success - String %s written to file %s."), file_contents, filename);
               }
               else
               {
               wsprintf(message, TEXT("Error writing to file: %d"), GetLastError());
               }
         }

Regards, Alex
0
 
TPolyAuthor Commented:
This are the errors that was generated from the source code.
We are using Embedded Visual C++

== Error Generated ==

c:\documents and settings\tp\desktop\projfiles\mapirule 13-8\mapirule\mapirule.cpp(616) : error C2440: 'initializing' : cannot convert from 'char *' to 'char'
        This conversion requires a reinterpret_cast, a C-style cast or function-style cast
c:\documents and settings\tp\desktop\projfiles\mapirule 13-8\mapirule\mapirule.cpp(618) : error C2664: 'WideCharToMultiByte' : cannot convert parameter 5 from 'char' to 'char *'
        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
c:\documents and settings\tp\desktop\projfiles\mapirule 13-8\mapirule\mapirule.cpp(622) : error C2664: 'WriteFile' : cannot convert parameter 2 from 'char' to 'const void *'
        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast

== End of Error ==
0
 
SteHCommented:
This looks that at some point you try assign a char pointer to a char and at another you try to do the reverse. Check whether both need to be char* and change the variable type accordingly.
0
 
SteHCommented:
Its in itsmeandnobodyelse's code:
               char buf   = new char[wlen * 2 +1];  // should be enough
should be
               char* buf   = new char[wlen * 2 +1];  // should be enough

and don't forget to delete[] that pointer after using it.

0
 
TPolyAuthor Commented:
Thanks for your fast reply..

There isn't any error now but the problem is that the output to the file is blank.
Nothing is written inside the file.


0
 
itsmeandnobodyelseCommented:
STeH,

thanks for correcting my bugs ;-)


TPoly,

could you debug the function? Is there any value in pspvSubject->Value.lpszW or file_contents? What about buf? Is there any contents before WriteFile?

Regards, Alex
0
 
TPolyAuthor Commented:
== The codes from my question ==

// Write a string to the file
               if (WriteFile(hFile, file_contents , wcslen(file_contents)*sizeof(TCHAR), &bytesWritten, NULL)!=0)
               {
               wsprintf(message, TEXT("Success - String %s written to file %s."), file_contents, filename);
               }
               else
               {
               wsprintf(message, TEXT("Error writing to file: %d"), GetLastError());
               }

== End ==

The messagebox contains the value of file_contents.
And the file_contents has the value that we want (its a string).
example of what is inside file_contents: 123, 18/8/2004 13:45, 123,

I'm not quite sure about the buf. I don't know if there is anything contained inside the bluf.
0
 
itsmeandnobodyelseCommented:

>>>>          if (WriteFile(hFile, file_contents ,

writes the UNICODE string (buffer)  to file. When opening that with any text editor you only see the first character as explained above...

So you _HAVE_ to convert the file_contents buffer (it's a wide string where any character is a 16 bit short integer) to buf (that's a 'normal' string where any character is an 8 bit char) _AND_ use that 'buf' variable when calling WriteFile

    if (WriteFile(hFile, buf, strlen(buf) + 1,  ...

Regards, Alex
0
 
drichardsCommented:
>>    if (WriteFile(hFile, buf, strlen(buf) + 1,  ...

It's a text file so you should not write the string terminator - don't use +1 with strlen(buf).
0
 
itsmeandnobodyelseConnect With a Mentor Commented:
>> It's a text file so you should not write the string terminator - don't use +1 with strlen(buf).

That's true. Maybe you should print a line feed character instead of the terminating zero:

Either that way ...

   if (WriteFile(hFile, buf, strlen(buf),  ... ))
   {
         WriteFile(hFile, "\n", 1, ...);
         ...
   }

or like that:


   int len = strlen(buf);
   buf[len] = '\n';
   buf[++len] = '\0';

 
   if (WriteFile(hFile, buf, len,  ... ))
   {
         ...

Regards, Alex




0
 
TPolyAuthor Commented:
i tried using this method

=== alex's code===

   int len = strlen(buf);
   buf[len] = '\n';
   buf[++len] = '\0';

 
   if (WriteFile(hFile, buf, len,  ... ))
   {
         ...

===end===

now the result:
the contents of the is only a line feed...
0
 
TPolyAuthor Commented:
actually i had posted another question regarding passing a value from this compile dll(which is a dll trying to intercept the incoming SMS from the Inbox of a POCKET PC, so that the SMS is not handled by the Inbox) directly to an VB.NET application, however there is no reply for that question..

thus i try coding this dll and write the value into an external file (eg. jobs.txt) in a POCKET PC (the file format i tried are .pwi , .txt , .csv)..

jobs.txt act as a middleman between the dll and the VB.NET application...

thus at the VB.NET application side, it will reads the jobs.txt and gets the contents, use split() to break the string into parts and insert into a ListView object..

the above three components( dll, jobs.txt and VB.NET application) all resides in the POCKET PC...
0
 
drichardsConnect With a Mentor Commented:
If you're trying to get this data into VB.NET in the end, you should just leave the data as UNICODE since that's what VB.NET will want anyway.  Then in VB.NET, use code something like this (I don't have my development machine to test at the moment to test):

        Dim aStreamReader As TextReader
        aStreamReader = New StreamReader("jobs.txt", System.Text.UnicodeEncoding, True)      
        Dim str As String = aStreamReader.ReadLine()

This should recover the UNICODE string from the file.  The True parameter in the StreamReader constructor tells it to automatically detect the encoding from the byte order marks at the beginning of the file.  If you don't write the marker bytes to the file (as I described previously), you should use False and it will just use the encoding you specify (I think - haven't tried it).
0
 
itsmeandnobodyelseCommented:
That sequence
     
     USES_CONVERSION;
     char* buf   = W2A(pspvSubject->Value.lpszW);

     int len = strlen(buf);
     buf[len] = '\n';
     buf[++len] = '\0';

     if (WriteFile(hFile, buf, len, &bytesWritten, NULL)!=0)
            ...

    ....

    CloseHandle(hFile);


should definitively give some valid output if

     pspvSubject->Value.lpszW

contains a UNICODE string (with printable characters) that isn't empty.

Did you check the values with the Debugger?

Regards, Alex
0
 
TPolyAuthor Commented:
thanks for all your help...
learn alot man...
0
 
TPolyAuthor Commented:
i had posted another project related problem at this question title at VB.NET..

Question Title: Sending SMS to a GSM phone that is connected to a PC COM port

hope u guys can further help...

your help will be greatly appreciated...
0
All Courses

From novice to tech pro — start learning today.