Discussion:
reading string from a text file from vc++ without MFC support
(too old to reply)
r***@yahoo.com
2007-06-16 05:28:32 UTC
Permalink
Hi
I am having a typical problem from last one day.I am being able to
writ into a text file from my vc++ application,but I am not being able
to read the file.actually I need to write something in the file and I
need need to again read the file.here is y code which is working fine
for writing to file:
FILE *fp=NULL;
fp=_wfopen(lstr,_T("w+"));//lstr is having the path to the file
fwrite( strTitleCurrentDate, sizeof(TCHAR), strTitle.GetLength()/
** sizeof( TCHAR )*/, fp );
fclose( fp );
this code is working fine but
CString strTitle1;
newBuffer=strTitle1.GetBuffer(strTitle1.GetLength()*
sizeof( TCHAR ));
LPTSTR lstr=strPath2.GetBuffer(strTitle.GetLength()* sizeof( TCHAR ));
FILE *fp=NULL;
fp=_wfopen(lstr,_T("a+"));
while(!feof(fp))
fread( newBuffer, sizeof(char), 100/** sizeof( TCHAR )*/, fp );
fclose( fp );

This piece of code really meking me frustrated because the data in
file I am being able to read which actually should be "15th june 2007"
is coming as "15th june 2007SID",from where this SID is coming?One
more thing is that after this code of file reading if I take any
CString variable and try to display it in a message box,it is showing
the value "15th june 2007SID" whereas it should show blank.I am
getting crash also in my application may be due to this problem.Plz
help me to solve this problem with code,because it will help me a
lot.Plz help me as early as possible because the deadline is coming
and I am being frustrated.I also have to read data in a text file line
by line which is also not being possible for me.Plz help me with code.
MrAsm
2007-06-16 07:01:36 UTC
Permalink
Post by r***@yahoo.com
need need to again read the file.here is y code which is working fine
FILE *fp=NULL;
fp=_wfopen(lstr,_T("w+"));//lstr is having the path to the file
fwrite( strTitleCurrentDate, sizeof(TCHAR), strTitle.GetLength()/
** sizeof( TCHAR )*/, fp );
fclose( fp );
this code is working fine but
The previous code is not good.

You are using _T and Unicode (_wfopen) in a wrong way.
_wfopen is the Unicode version of fopen, its prototype is:

FILE *_wfopen(
const wchar_t *filename,
const wchar_t *mode
);

So 'mode' is a Unicode string (wchar_t *) in _wfopen, so you should
use L"w+", not _T("w+"), with _wfopen.

Or, if you want to use Unicode-aware style consistently, you can
write:

// Assume 'lstr' is a TCHAR-string (e.g. a CString)
FILE * fp = _tfopen( lstr, _T("w+") );

Your original code would compile only in Unicode builds, but is
inconsistent with TCHAR convention.
Post by r***@yahoo.com
fwrite( strTitleCurrentDate, sizeof(TCHAR), strTitle.GetLength()/
** sizeof( TCHAR )*/, fp );
You are writing 'strTitleCurrentData' characters, but you are giving
fwrite the length of 'strTitle'... are these variables the *same*
string? If so, why are you using two different variables for the same
string? The code is confusing...

Moreover, if 'strTitleCurrentDate' is of type CString, I would prefer
to explicitly cast to LPCTSTR to access string character pointer.

Finally, are you aware that you are writing only the string characters
but *no* the final _T('\0') of the string? In fact, GetLength returns
the number of TCHARs in the string, excluding the terminating
_T('\0').
Post by r***@yahoo.com
CString strTitle1;
newBuffer=strTitle1.GetBuffer(strTitle1.GetLength()*
sizeof( TCHAR ));
'strTitle1' is initialized to an empty string by the default
constructor. So 'strTitle1.GetLength()' is 0, so you are passing 0 to
GetBuffer.
Is that what you really want??
Post by r***@yahoo.com
LPTSTR lstr=strPath2.GetBuffer(strTitle.GetLength()* sizeof( TCHAR ));
FILE *fp=NULL;
fp=_wfopen(lstr,_T("a+"));
You have the same Unicode/_T (_wfopen/_T("a+")) mismatch as above.
Post by r***@yahoo.com
while(!feof(fp))
fread( newBuffer, sizeof(char), 100/** sizeof( TCHAR )*/, fp );
fclose( fp );
You called GetBuffer above, but you didn't release the buffer with
ReleaseBuffer.
Moreover, where is the 'newBuffer' memory?
Where is defined that 'newBuffer' is 100 bytes?
Why are you using 'char' and not 'TCHAR'?

IMHO, the code has several inconsistent things...
You should really clean it up.

You might consider using more modern C++ I/O stream classes to manage
files; they are easier than C FILE*, are more robust (e.g. the
destructor will close the file, while with C FILE * you may forget to
call fclose, etc.)

If you want to write to a file, you may use code as follow:

// Your file object
std::ofstream file( "TheFileName.txt" );

// You may check result with file.is_open()
// if ( file.is_open() ...

// Write to file:
file << "This is the first line.\n";
file << "Hello...\n";
... and so on

// You may call file.close() or let the
// class destructor close the file when
// 'file' variable goes out of scope.


If you want to read from a file, line by line:

std::string line;
std::ifstream file("Data.txt");
// if (! file.is_open()) --> error

// Line reading loop
while ( ! file.feof() )
{
std::getline( file, line );
std::cout << "Line read: " << line << std::endl;
}

// file.close() or delegate to destructor


There is also the MFC CStdioFile class, but I would prefer a
substitute from CodeProject (or Tom's much better version):

http://www.codeproject.com/file/stdiofileex.asp

MrAsm
MrAsm
2007-06-16 07:41:38 UTC
Permalink
Post by MrAsm
// Your file object
std::ofstream file( "TheFileName.txt" );
...
Post by MrAsm
file << "This is the first line.\n";
file << "Hello...\n";
Note that these strings are not Unicode UTF-16 (i.e. L"..." strings).

If I need to write Unicode strings to an external file (for example,
using C++ I/O streams), I like to convert Unicode UTF-16 (which is the
Windows Unicode format) CStringW strings to Unicode UTF-8. The UTF-8
strings can be stored in CStringA or std::string. Then I write the
std::string UTF-8 encoded string to file.

When I read string data back from file, I read UTF-8 strings in
std::string's, then convert UTF-8 to UTF-16 CStringW strings, and use
CStringW for Windows.
(In fact, I think that the most efficient way to manage strings in
Windows is using Unicode UTF-16, because it is the "native" Unicode
format for Windows.)


UTF-16 string (CStringW)
|
+---> UTF-8 string (std::string)
|
+---> Write to file


Read UTF-8 string (std::string) from file
|
+---> Convert to UTF-16 (CStringW)


Different methods are available, too (like writing directly Unicode
UTF-16 strings to file and reading them back, using the CStdioFileEx
classes I mentioned in previous post).

MrAsm
r***@yahoo.com
2007-06-17 06:11:11 UTC
Permalink
Post by MrAsm
need need to again read thefile.here is y code which is working fine
FILE*fp=NULL;
fp=_wfopen(lstr,_T("w+"));//lstr is having the path to thefile
fwrite( strTitleCurrentDate, sizeof(TCHAR), strTitle.GetLength()/
** sizeof( TCHAR )*/, fp );
fclose( fp );
this code is working fine but
The previous code is not good.
You are using _T and Unicode (_wfopen) in a wrong way.
FILE*_wfopen(
const wchar_t *filename,
const wchar_t *mode
);
So 'mode' is a Unicodestring(wchar_t *) in _wfopen, so you should
use L"w+", not _T("w+"), with _wfopen.
Or, if you want to use Unicode-aware style consistently, you can
// Assume 'lstr' is a TCHAR-string(e.g. a CString)
FILE* fp = _tfopen( lstr, _T("w+") );
Your original code would compile only in Unicode builds, but is
inconsistent with TCHAR convention.
fwrite( strTitleCurrentDate, sizeof(TCHAR), strTitle.GetLength()/
** sizeof( TCHAR )*/, fp );
You are writing 'strTitleCurrentData' characters, but you are giving
fwrite the length of 'strTitle'... are these variables the *same*string? If so, why are you using two different variables for the samestring? The code is confusing...
Moreover, if 'strTitleCurrentDate' is of type CString, I would prefer
to explicitly cast to LPCTSTR to accessstringcharacter pointer.
Finally, are you aware that you are writing only thestringcharacters
but *no* the final _T('\0') of thestring? In fact, GetLength returns
the number of TCHARs in thestring, excluding the terminating
_T('\0').
CString strTitle1;
newBuffer=strTitle1.GetBuffer(strTitle1.GetLength()*
sizeof( TCHAR ));
'strTitle1' is initialized to an emptystringby the default
constructor. So 'strTitle1.GetLength()' is 0, so you are passing 0 to
GetBuffer.
Is that what you really want??
LPTSTR lstr=strPath2.GetBuffer(strTitle.GetLength()* sizeof( TCHAR ));
FILE*fp=NULL;
fp=_wfopen(lstr,_T("a+"));
You have the same Unicode/_T (_wfopen/_T("a+")) mismatch as above.
while(!feof(fp))
fread( newBuffer, sizeof(char), 100/** sizeof( TCHAR )*/, fp );
fclose( fp );
You called GetBuffer above, but you didn't release the buffer with
ReleaseBuffer.
Moreover, where is the 'newBuffer' memory?
Where is defined that 'newBuffer' is 100 bytes?
Why are you using 'char' and not 'TCHAR'?
IMHO, the code has several inconsistent things...
You should really clean it up.
You might consider using more modern C++ I/O stream classes to manage
files; they are easier than CFILE*, are more robust (e.g. the
destructor will close thefile, while with CFILE* you may forget to
call fclose, etc.)
// Yourfileobject
std::ofstreamfile( "TheFileName.txt" );
// You may check result withfile.is_open()
// if (file.is_open() ...
file<< "This is the first line.\n";
file<< "Hello...\n";
... and so on
// You may callfile.close() or let the
// class destructor close thefilewhen
// 'file' variable goes out of scope.
std::stringline;
std::ifstreamfile("Data.txt");
// if (!file.is_open()) --> error
// Linereadingloop
while ( !file.feof() )
{
std::getline(file, line );
std::cout << "Line read: " << line << std::endl;
}
//file.close() or delegate to destructor
There is also the MFC CStdioFile class, but I would prefer a
http://www.codeproject.com/file/stdiofileex.asp
MrAsm
Thanks a lot MrAsm for your precious suggestions,I have made the
changes in the code to what you suggested(such as _wfopen to
_tfopen,charto TCHAR etc.).But the code what you have sent {


If you want to write to a file, you may use code as follow:


// Your file object
std::ofstream file( "TheFileName.txt" );


// You may check result with file.is_open()
// if ( file.is_open() ...


// Write to file:
file << "This is the first line.\n";
file << "Hello...\n";
... and so on


// You may call file.close() or let the
// class destructor close the file when
// 'file' variable goes out of scope.


If you want to read from a file, line by line:


std::string line;
std::ifstream file("Data.txt");
// if (! file.is_open()) --> error


// Line reading loop
while ( ! file.feof() )
{
std::getline( file, line );
std::cout << "Line read: " << line << std::endl;
}


// file.close() or delegate to destructor


}

I am not being able to use this code,I dont know why.My project is an
ATL COM project with WTL support without MFC.So I am not able to use
CFile class also.will U plz get me a code for reading file line by
line using FILE structure.my text file will be having random number of
data such as
atlanta/123
atlanta/greetings
atlanta/double
............
............
....//random nuber of lines.
Now I need to read each line of the file and save it into a string
variable and use this variable in the application.the problem here is
that I dont know How many lines will the file have.I am really
puzzled here with so many problems.Plz help me with code which will be
not using C++ I/O stream classes,will be using FILE structure,because
I am having problem with that.plz get me out of this situation as
early as possible b'coz my boss is screwing me now.Again thanks a lot
from my heart for your invaluable suggestions.
MrAsm
2007-06-17 09:43:32 UTC
Permalink
Post by r***@yahoo.com
will U plz get me a code for reading file line by
line using FILE structure.
OK, I understand that you want to use C 'FILE *'.
Post by r***@yahoo.com
my text file will be having random number of
data such as
atlanta/123
atlanta/greetings
atlanta/double
............
............
....//random nuber of lines.
Now I need to read each line of the file and save it into a string
variable and use this variable in the application.the problem here is
The problem is easy. You just need to open the file using _tfopen
(_tfopen is the Unicode-aware version of standard C fopen), read text
lines using _fgetts (the Unicode-aware version of standard C fgets),
until you reach end of file (use feof to test it) and close the file
with fclose.

You read each file line into a temporary local buffer (TCHAR array of
maximum specified size) using _fgetts, and then you can store the line
you have just read in the old-style C buffer into a more modern robust
useful CString instance.


<CODE>
CString fileName = _T("c:\\prova.txt");

// Open the file for reading in text mode
FILE * file = _tfopen( fileName, _T("rt"));
// If file == NULL ... error

// Maximum number of characters in a line
static const int maxLineChars = 200;

// This will store each line of text
TCHAR line[ maxLineChars ];

// Read line by line from file
while ( ! feof(file) )
{
// Clear destination buffer
::ZeroMemory( line, sizeof(line) );

// Read the line
_fgetts( line, maxLineChars, file );

// Now 'line' contains the line read from file.
// Do your processing.
// e.g.: You may store the read line into a CString
CString strLine( line );

// Process strLine...
// DoLineProcessing( strLine );
...
}

// Close the file
fclose(file);
file = NULL; // Avoid dangling references

</CODE>
Post by r***@yahoo.com
that I dont know How many lines will the file have.
No problem: 'feof' function and 'while' statement help you here :)


MrAsm
r***@yahoo.com
2007-06-18 10:50:00 UTC
Permalink
will U plz get me a code forreadingfileline by
line usingFILEstructure.
OK, I understand that you want to use C 'FILE*'.
my textfilewill be having random number of
data such as
atlanta/123
atlanta/greetings
atlanta/double
............
............
....//random nuber of lines.
Now I need to read each line of thefileand save it into astring
variable and use this variable in the application.the problem here is
The problem is easy. You just need to open thefileusing _tfopen
(_tfopen is the Unicode-aware version of standard C fopen), read text
lines using _fgetts (the Unicode-aware version of standard C fgets),
until you reach end offile(use feof to test it) and close thefile
with fclose.
You read eachfileline into a temporary local buffer (TCHAR array of
maximum specified size) using _fgetts, and then you can store the line
you have just read in the old-style C buffer into a more modern robust
useful CString instance.
<CODE>
CString fileName = _T("c:\\prova.txt");
// Open thefileforreadingin text mode
FILE*file= _tfopen( fileName, _T("rt"));
// Iffile== NULL ... error
// Maximum number of characters in a line
static const int maxLineChars = 200;
// This will store each line of text
TCHAR line[ maxLineChars ];
// Read line by line fromfile
while ( ! feof(file) )
{
// Clear destination buffer
::ZeroMemory( line, sizeof(line) );
// Read the line
_fgetts( line, maxLineChars,file);
// Now 'line' contains the line read fromfile.
// Do your processing.
// e.g.: You may store the read line into a CString
CString strLine( line );
// Process strLine...
// DoLineProcessing( strLine );
...
}
// Close thefile
fclose(file);
file= NULL; // Avoid dangling references
</CODE>
that I dont know How many lines will thefilehave.
No problem: 'feof' function and 'while' statement help you here :)
MrAsm
Hi MrAsm
I dont know really just how to thank you,your code was
excellent,It worked properly.I really appreciate your help ,Thanks a
lot.Now only one problem I am having.Actually the text entered into
the text file were having '\n' in each line.actually I am implementing
a dynamic menu here which will be created by taking these text from
this file.Now when I am putting MessageBox(strLine),It is showing the
proper text,But when the menu is being created dynamically(menu items
are the values in strLine),a square symbol is coming after each menu
item ,means after every strLine value.I think this may be due to the
'\n' in each line.How to remove it?I want the actual text.Plz send me
the code.Once again thanks a lot for ur help,thank u,thanks a lot.
Tom Serface
2007-06-18 13:58:42 UTC
Permalink
When you read the text back in strip the CR/NL off the end of the line using
something like:

http://msdn2.microsoft.com/en-us/library/dkxtwt6t(VS.80).aspx

cs = cs.Trim();

Tom
Post by r***@yahoo.com
will U plz get me a code forreadingfileline by
line usingFILEstructure.
OK, I understand that you want to use C 'FILE*'.
my textfilewill be having random number of
data such as
atlanta/123
atlanta/greetings
atlanta/double
............
............
....//random nuber of lines.
Now I need to read each line of thefileand save it into astring
variable and use this variable in the application.the problem here is
The problem is easy. You just need to open thefileusing _tfopen
(_tfopen is the Unicode-aware version of standard C fopen), read text
lines using _fgetts (the Unicode-aware version of standard C fgets),
until you reach end offile(use feof to test it) and close thefile
with fclose.
You read eachfileline into a temporary local buffer (TCHAR array of
maximum specified size) using _fgetts, and then you can store the line
you have just read in the old-style C buffer into a more modern robust
useful CString instance.
<CODE>
CString fileName = _T("c:\\prova.txt");
// Open thefileforreadingin text mode
FILE*file= _tfopen( fileName, _T("rt"));
// Iffile== NULL ... error
// Maximum number of characters in a line
static const int maxLineChars = 200;
// This will store each line of text
TCHAR line[ maxLineChars ];
// Read line by line fromfile
while ( ! feof(file) )
{
// Clear destination buffer
::ZeroMemory( line, sizeof(line) );
// Read the line
_fgetts( line, maxLineChars,file);
// Now 'line' contains the line read fromfile.
// Do your processing.
// e.g.: You may store the read line into a CString
CString strLine( line );
// Process strLine...
// DoLineProcessing( strLine );
...
}
// Close thefile
fclose(file);
file= NULL; // Avoid dangling references
</CODE>
that I dont know How many lines will thefilehave.
No problem: 'feof' function and 'while' statement help you here :)
MrAsm
Hi MrAsm
I dont know really just how to thank you,your code was
excellent,It worked properly.I really appreciate your help ,Thanks a
lot.Now only one problem I am having.Actually the text entered into
the text file were having '\n' in each line.actually I am implementing
a dynamic menu here which will be created by taking these text from
this file.Now when I am putting MessageBox(strLine),It is showing the
proper text,But when the menu is being created dynamically(menu items
are the values in strLine),a square symbol is coming after each menu
item ,means after every strLine value.I think this may be due to the
'\n' in each line.How to remove it?I want the actual text.Plz send me
the code.Once again thanks a lot for ur help,thank u,thanks a lot.
MrAsm
2007-06-18 14:30:37 UTC
Permalink
Post by r***@yahoo.com
Post by MrAsm
// Read the line
_fgetts( line, maxLineChars,file);
I think this may be due to the
'\n' in each line.How to remove it?
In addition to Tom's post, you might consider this function:

<CODE>
inline TCHAR * RemoveEndingNewLine( TCHAR * line )
{
const size_t len = _tcslen(line);
if ( len != 0 )
{
line[ len - 1 ] = _T('\0');
}

return line;
}
</CODE>

and call it after the _fgetts:

RemoveEndingNewLine( line );

The function just seeks the end of string (the length of the string is
returned by _tcslen) and replaces the ending \n with \0 (EOS = End Of
String - someone calls it NUL, with one 'L').

MrAsm
Tom Serface
2007-06-18 15:16:16 UTC
Permalink
Hi G,

This would work OK and has the advantage of not needing a CString, but it
assumes the NL is the last char and that there is no other white space at
the end or the beginning of the string. Since OP was intending to use the
strings in menus I thought the Trim() function was a nice way to just get
rid of any white space at the beginning or end of the line.

If I were going to use your method, I'd probably check the character as well
to make sure that there really was a NL at the end of the string (just to be
safe).

Tom
Post by MrAsm
Post by r***@yahoo.com
Post by MrAsm
// Read the line
_fgetts( line, maxLineChars,file);
I think this may be due to the
'\n' in each line.How to remove it?
<CODE>
inline TCHAR * RemoveEndingNewLine( TCHAR * line )
{
const size_t len = _tcslen(line);
if ( len != 0 )
{
line[ len - 1 ] = _T('\0');
}
return line;
}
</CODE>
RemoveEndingNewLine( line );
The function just seeks the end of string (the length of the string is
returned by _tcslen) and replaces the ending \n with \0 (EOS = End Of
String - someone calls it NUL, with one 'L').
MrAsm
MrAsm
2007-06-18 21:40:26 UTC
Permalink
On Mon, 18 Jun 2007 08:16:16 -0700, "Tom Serface"
Post by Tom Serface
Hi G,
This would work OK and has the advantage of not needing a CString, but it
assumes the NL is the last char and that there is no other white space at
the end or the beginning of the string. Since OP was intending to use the
strings in menus I thought the Trim() function was a nice way to just get
rid of any white space at the beginning or end of the line.
Hi Tom,

you are absolutely right!

I used that function just to remove the \n for strings read with
_fgetts. My function is very ad-hoc and no general; it was designed
for a very specific case.
I agree with you.
Post by Tom Serface
If I were going to use your method, I'd probably check the character as well
to make sure that there really was a NL at the end of the string (just to be
safe).
You're right: an ASSERT( lastChar == _T('\n') ); should be very good!

Thanks for your insights
MrAsm
Tom Serface
2007-06-19 00:01:49 UTC
Permalink
I'm just thrilled to hear/read someone say "I'm right". I don't even
remember what we were talking about :o)

Tom
Post by MrAsm
On Mon, 18 Jun 2007 08:16:16 -0700, "Tom Serface"
Hi Tom,
you are absolutely right!
MrAsm
2007-06-19 10:27:47 UTC
Permalink
On Mon, 18 Jun 2007 17:01:49 -0700, "Tom Serface"
Post by Tom Serface
I'm just thrilled to hear/read someone say "I'm right". I don't even
remember what we were talking about :o)
Hi Tom,

This is what (correct) quoting is for ;)

MrAsm
Tom Serface
2007-06-19 13:00:09 UTC
Permalink
Acutally, you're right. I try to trim so that the part of the message I
think is relavent is right below what I write in reply (I top post since I
hate scrolling for three or four screens to get to a response). I fact, I'm
almost at the point where if I open a message and can't see something that
doesn't look like:
on the screen somwhere I just go to the next message :o)

Tom
Post by MrAsm
On Mon, 18 Jun 2007 17:01:49 -0700, "Tom Serface"
Post by Tom Serface
I'm just thrilled to hear/read someone say "I'm right". I don't even
remember what we were talking about :o)
Hi Tom,
This is what (correct) quoting is for ;)
MrAsm
MrAsm
2007-06-19 13:45:03 UTC
Permalink
On Tue, 19 Jun 2007 06:00:09 -0700, "Tom Serface"
Post by Tom Serface
(I top post since I
hate scrolling for three or four screens to get to a response).
Hi Tom,

but the original message(s) could be edited and several lines cut away
in the response post, so we don't need to do the 3-4 screens scrolling
:)

MrAsm
Tom Serface
2007-06-19 15:55:47 UTC
Permalink
That would be the ultimate solution. Alas...

Tom
Post by MrAsm
Hi Tom,
but the original message(s) could be edited and several lines cut away
in the response post, so we don't need to do the 3-4 screens scrolling
:)
MrAsm
r***@yahoo.com
2007-06-19 09:52:11 UTC
Permalink
will U plz get me a code forreadingfileline by
line usingFILEstructure.
OK, I understand that you want to use C 'FILE*'.
my textfilewill be having random number of
data such as
atlanta/123
atlanta/greetings
atlanta/double
............
............
....//random nuber of lines.
Now I need to read each line of thefileand save it into astring
variable and use this variable in the application.the problem here is
The problem is easy. You just need to open thefileusing _tfopen
(_tfopen is the Unicode-aware version of standard C fopen), read text
lines using _fgetts (the Unicode-aware version of standard C fgets),
until you reach end offile(use feof to test it) and close thefile
with fclose.
You read eachfileline into a temporary local buffer (TCHAR array of
maximum specified size) using _fgetts, and then you can store the line
you have just read in the old-style C buffer into a more modern robust
useful CString instance.
<CODE>
CString fileName = _T("c:\\prova.txt");
// Open thefileforreadingin text mode
FILE*file= _tfopen( fileName, _T("rt"));
// Iffile== NULL ... error
// Maximum number of characters in a line
static const int maxLineChars = 200;
// This will store each line of text
TCHAR line[ maxLineChars ];
// Read line by line fromfile
while ( ! feof(file) )
{
// Clear destination buffer
::ZeroMemory( line, sizeof(line) );
// Read the line
_fgetts( line, maxLineChars,file);
// Now 'line' contains the line read fromfile.
// Do your processing.
// e.g.: You may store the read line into a CString
CString strLine( line );
// Process strLine...
// DoLineProcessing( strLine );
...
}
// Close thefile
fclose(file);
file= NULL; // Avoid dangling references
</CODE>
that I dont know How many lines will thefilehave.
No problem: 'feof' function and 'while' statement help you here :)
MrAsm
Hi MrAsm
Your code is good but there is one problem,If I do
MessageBox(strLine) after CString strLine( line),then I am getting one
blank Message box after reading all the lines.Means if the file is
having one line,then first messagebox is displaying the line value and
one more messagebox is coming which is blank.I dont want this blank
messagebox.Plz help me to solve this problem with code.again thanks a
lot for all ur help.
MrAsm
2007-06-19 10:26:53 UTC
Permalink
Post by r***@yahoo.com
Your code is good but there is one problem,If I do
MessageBox(strLine) after CString strLine( line),then I am getting one
blank Message box after reading all the lines.
I think this is due to the fact that you have a blank line (only a \n
line) at the end of your text file.

If you want to avoid the last blank message, you have two options:

- don't insert a blank line in the text file you are reading

- check if you have read a blank line, and reject it in case

A possible way of adjusting the code is to put the check after
_fgetts, e.g.:

_fgetts( line, maxLineChars,file);

// If we read an empty line (i.e. a line with just the newline)
// we skip it
if ( line[0] == _T('\n') )
{
continue; // next iteration
}

Moreover, a more robust thing could be to trim line spaces e.g. using
CString::TrimLeft/Right.

If you are sure that your source file is well edited and has no
spurious spaces, but just a possible empty line at its end, then the
_T('\n') check should be fine.

MrAsm
Tom Serface
2007-06-19 12:58:40 UTC
Permalink
Hi Asm,

After trimming the new line off the line OP could always just check the
CString variable as well:

if(!strLine.IsEmpty()) {
// Do something with it
}

Tom
Post by MrAsm
Post by r***@yahoo.com
Your code is good but there is one problem,If I do
MessageBox(strLine) after CString strLine( line),then I am getting one
blank Message box after reading all the lines.
I think this is due to the fact that you have a blank line (only a \n
line) at the end of your text file.
- don't insert a blank line in the text file you are reading
- check if you have read a blank line, and reject it in case
A possible way of adjusting the code is to put the check after
_fgetts( line, maxLineChars,file);
// If we read an empty line (i.e. a line with just the newline)
// we skip it
if ( line[0] == _T('\n') )
{
continue; // next iteration
}
Moreover, a more robust thing could be to trim line spaces e.g. using
CString::TrimLeft/Right.
If you are sure that your source file is well edited and has no
spurious spaces, but just a possible empty line at its end, then the
_T('\n') check should be fine.
MrAsm
David Wilkinson
2007-06-19 12:34:39 UTC
Permalink
Post by r***@yahoo.com
Hi MrAsm
Your code is good but there is one problem,If I do
MessageBox(strLine) after CString strLine( line),then I am getting one
blank Message box after reading all the lines.Means if the file is
having one line,then first messagebox is displaying the line value and
one more messagebox is coming which is blank.I dont want this blank
messagebox.Plz help me to solve this problem with code.again thanks a
lot for all ur help.
rindam:

I don't use these old C file handling functions, but isn't this
happening because your while condition is not correct? Shouldn't it be

TCHAR line[ maxLineChars ];

// Read line by line from file
while ( _fgetts( line, maxLineChars, file ) != NULL)
{
CString strLine( line );

// Process strLine...
// DoLineProcessing( strLine );
//...
}
if(! feof(file))
{
// error handling
}

[I don't think it is necessary to zero the line, because if the return
from _fgetts is not NULL, the target string is always NUL-terminated.]
--
David Wilkinson
Visual C++ MVP
MrAsm
2007-06-19 13:34:44 UTC
Permalink
On Tue, 19 Jun 2007 07:34:39 -0500, David Wilkinson
Post by David Wilkinson
I don't use these old C file handling functions,
But it was a requirement by the OP, not my choice...
Post by David Wilkinson
but isn't this
happening because your while condition is not correct?
No, I tested my code before posting, and I also found that if a text
file is like so:

---Start
Hello
World

---End

then a last empty line is read, and an empty MessageBox is displayed.

The 'while' loop works well.
There is just the need to check for empty lines.

MrAsm
David Wilkinson
2007-06-19 14:51:19 UTC
Permalink
Post by MrAsm
No, I tested my code before posting, and I also found that if a text
---Start
Hello
World
---End
then a last empty line is read, and an empty MessageBox is displayed.
The 'while' loop works well.
There is just the need to check for empty lines.
MrAsm
Asm:

I still think your condition is wrong. What happens on the iteration
when the file hits EOF and _fgetts returns NULL? Because you zero the
line, you will get an empty string, which you will have to handle. If
you do as I suggest, you do not need to zero the line and the loop will
end one iteration sooner.
--
David Wilkinson
Visual C++ MVP
MrAsm
2007-06-19 14:10:11 UTC
Permalink
On Tue, 19 Jun 2007 09:51:19 -0500, David Wilkinson
Post by David Wilkinson
I still think your condition is wrong. What happens on the iteration
when the file hits EOF and _fgetts returns NULL?
I have the foef() check in the while condition... so it is the first
thing to be checked, and so if EOF is hit, then the while body is not
executed.

Am I missing anything?
Please enlight me...

Regard the clearing of whole buffer before reading, I would suggest
you to read Secure Coding book:

http://www.securecoding.org/

I recall that I read somewhere there that there was an attack or
password leak (or something similar) due to the fact that a buffer was
not cleared completely, so it happened to have something like this:

|<--- this "trash" was useful for ---->|
| the attack |
|<------------------------------------>|
. .
. .
|A string | '\0' |Senstive data from other processing \0|
\----------------------- ------------------------------/
\/
The whole buffer

I prefer to clear everything in the buffers; it is very robust secure
code, even if it will consume some more CPU cycles.

(Of course, in a very optimized routine, I would avoid such
operations; but, unless differently specified, I prefer security and
robustness over performance).

MrAsm
MrAsm
2007-06-19 14:11:50 UTC
Permalink
Post by MrAsm
|A string | '\0' |Senstive data from other processing \0|
\----------------------- ------------------------------/
\/
The whole buffer
I prefer this:

|A string | '\0' 0000000000000000000................0000
\----------------------- ------------------------------/
\/
The whole buffer

MrAsm
Tom Serface
2007-06-19 15:58:00 UTC
Permalink
I think almost every reading function returns the actual number of
characters read as well so you can use that to trim your buffer. Although
zero filling it is cheap insurance.

Tom
Post by MrAsm
On Tue, 19 Jun 2007 09:51:19 -0500, David Wilkinson
Post by David Wilkinson
I still think your condition is wrong. What happens on the iteration
when the file hits EOF and _fgetts returns NULL?
I have the foef() check in the while condition... so it is the first
thing to be checked, and so if EOF is hit, then the while body is not
executed.
Am I missing anything?
Please enlight me...
Regard the clearing of whole buffer before reading, I would suggest
http://www.securecoding.org/
I recall that I read somewhere there that there was an attack or
password leak (or something similar) due to the fact that a buffer was
|<--- this "trash" was useful for ---->|
| the attack |
|<------------------------------------>|
. .
. .
|A string | '\0' |Senstive data from other processing \0|
\----------------------- ------------------------------/
\/
The whole buffer
I prefer to clear everything in the buffers; it is very robust secure
code, even if it will consume some more CPU cycles.
(Of course, in a very optimized routine, I would avoid such
operations; but, unless differently specified, I prefer security and
robustness over performance).
MrAsm
David Wilkinson
2007-06-19 17:48:16 UTC
Permalink
Post by MrAsm
On Tue, 19 Jun 2007 09:51:19 -0500, David Wilkinson
Post by David Wilkinson
I still think your condition is wrong. What happens on the iteration
when the file hits EOF and _fgetts returns NULL?
I have the foef() check in the while condition... so it is the first
thing to be checked, and so if EOF is hit, then the while body is not
executed.
Am I missing anything?
Please enlight me...
Asm:

feof() tests whether EOF was reached on the previous read, not whether
it would be reached on the next read. See for example

http://c-faq.com/stdio/feof.html
--
David Wilkinson
Visual C++ MVP
MrAsm
2007-06-19 17:37:27 UTC
Permalink
On Tue, 19 Jun 2007 12:48:16 -0500, David Wilkinson
Post by David Wilkinson
feof() tests whether EOF was reached on the previous read, not whether
it would be reached on the next read. See for example
http://c-faq.com/stdio/feof.html
Thank you very much, David.
(I clearly was misunderstanding feof.)

A new thing learnt :)

MrAsm
David Wilkinson
2007-06-19 18:50:08 UTC
Permalink
Post by MrAsm
On Tue, 19 Jun 2007 12:48:16 -0500, David Wilkinson
Post by David Wilkinson
feof() tests whether EOF was reached on the previous read, not whether
it would be reached on the next read. See for example
http://c-faq.com/stdio/feof.html
Thank you very much, David.
(I clearly was misunderstanding feof.)
A new thing learnt :)
Asm:

You're welcome. I used to make this mistake, so I remember it. It's the
same thing with std::istream.
--
David Wilkinson
Visual C++ MVP
r***@yahoo.com
2007-06-20 09:15:18 UTC
Permalink
Post by MrAsm
On Tue, 19 Jun 2007 07:34:39 -0500, David Wilkinson
I don't use these old Cfilehandling functions,
But it was a requirement by the OP, not my choice...
but isn't this
happening because your while condition is not correct?
---Start
Hello
World
---End
then a last empty line is read, and an empty MessageBox is displayed.
The 'while' loop works well.
There is just the need to check for empty lines.
MrAsm
Hi
I am having two text files.
----------------text file1----------------
apple
mango
banana
--------
------random number of line
-------------End of text file1------------

----------------text file----------------
www.wonders.com
www.magic.com
www.moris.com
--------
------random number of line
-------------End of text file1------------

Now what I want is that I want to read the first lines from both file
at a time and do some calculations on them,then I want to read the
second lines from both file and do some calculations on them and so on
for all the lines in both files.This two files will have same number
of lines.

I tried to do like this---->
FILE *fp=NULL;
fp=_tfopen(lpstrPathToUserRss,_T("a+")); //opens Text
file 1
static const int maxLineChars = 200;
TCHAR line[ maxLineChars ];
while ( ! feof(fp) )
{
// Clear destination buffer
::ZeroMemory( line, sizeof(line) );

// Read the line
_fgetts( line, maxLineChars, fp );

CString strLine( line );

FILE *fp1=NULL;

fp1=_tfopen(lpstrPathToUserRssXmlPath,_T("a+")); //opens text file2
static const int maxLineCharsForXmlPath
= 200;
TCHAR
lineForXmlPath[ maxLineCharsForXmlPath ];
while ( ! feof(fp1) )
{
// Clear destination buffer
::ZeroMemory( lineForXmlPath,
sizeof(lineForXmlPath) );


// Read the line
_fgetts( lineForXmlPath,
maxLineCharsForXmlPath, fp1 );


// Now 'line' contains the line read from file.
// Do your processing.
// e.g.: You may store the read line into a
CString
CString strLineForXmlPath( lineForXmlPath );
} //end of second while loop
} //end of first while loop

but this code is wrong because it is getting line1 from text file1
and all lines from text file2 at first time,then it is getting line2
from text file1 and all lines from text file2 at second time,then it
is getting line3 from text file1 and all lines from text file2 at
third time and so on.But what I want is not that.I want to get only
line1 from both files at a time,then only line2 from both files at a
time ,then only line3 from both files at a time and so on upto the
end of files.Plz help me to solve this problem.
MrAsm
2007-06-20 10:04:46 UTC
Permalink
Post by r***@yahoo.com
I am having two text files.
Now what I want is that I want to read the first lines from both file
at a time and do some calculations on them,then I want to read the
second lines from both file and do some calculations on them and so on
for all the lines in both files.This two files will have same number
of lines.
You might want to use my TextFileReader class (at the end of this post
- note that the class needs testing), like so:


<CODE>
TextFileReader file1( _T("c:\\data1.txt") );
TextFileReader file2( _T("c:\\data2.txt") );

ASSERT( file1.IsOpen() );
ASSERT( file2.IsOpen() );

// Check the file are open successfully:
//
//if ( ! file1.IsOpen() )
// ... error file 1 open
//if ( ! file2.IsOpen() )
// ... error file 2 open

// Stop when find an empty line
while ( true )
{
// Read lines from files
CString line1 = file1.ReadLine();
CString line2 = file2.ReadLine();

if ( line1.IsEmpty() || line2.IsEmpty() )
break;

// Process the lines...
CString msg;
msg = CString( _T("Line from File #1 : ") ) + line1;
msg += CString( _T("\nLine from File #2 : ") ) + line2;
AfxMessageBox(msg, MB_OK);

}
</CODE>



<FILE name="TextFileReader.h">

#pragma once

class TextFileReader
{
public:

TextFileReader();

// Tries to open the file with given name.
// Check with IsOpen() after constructor for operation result.
explicit TextFileReader( LPCTSTR fileName );

// Closes the file, if open
virtual ~TextFileReader();

// Opens the file.
// Returns 'true' on success, 'false' on error
bool Open( LPCTSTR fileName );

// Reads line from file.
// On error or end of file, returns empty string.
// (Use EoF/FileError methods to check EOF or error condition)
CString ReadLine( bool removeNewLine = true );

// Close the file (if open)
void Close();

// Check if the file is opened
bool IsOpen() const;

// Return file name
LPCTSTR GetFileName() const;

// End of file reached?
bool EoF();

// Error condition?
bool FileError();


//
// IMPLEMENTATION
//

protected:

FILE * m_file; // C file handle
CString m_fileName; // File name


// Helper to remove last '\n
TCHAR * RemoveEndingNewLine( TCHAR * line );


//
// Ban copy
//
private:
TextFileReader( const TextFileReader & );
TextFileReader & operator=( const TextFileReader & );
};


//
// INLINE METHODS
//

inline bool TextFileReader::IsOpen() const
{
return ( ( m_file != NULL ) ? true : false );
}

inline LPCTSTR TextFileReader::GetFileName() const
{
return static_cast<LPCTSTR>( m_fileName );
}

inline TCHAR * TextFileReader::RemoveEndingNewLine( TCHAR * line )
{
const size_t len = _tcslen(line);
if ( len != 0 &&
( line[ len - 1 ] == _T('\n') ) )
{
line[ len - 1 ] = _T('\0');
}

return line;
}

inline bool TextFileReader::EoF()
{
ASSERT( m_file != NULL );
return ( feof(m_file) ? true : false );
}

inline bool TextFileReader::FileError()
{
ASSERT( m_file != NULL );
return ( ferror(m_file) ? true : false );
}

</FILE>


<FILE name="TextFileReader.cpp">

#include "StdAfx.h"
#include "TextFileReader.h"

TextFileReader::TextFileReader()
: m_file(NULL)
{
return;
}

TextFileReader::TextFileReader( LPCTSTR fileName )
: m_file(NULL)
{
ASSERT( fileName != NULL );

// Check result with IsOpen()
Open( fileName );
}

TextFileReader::~TextFileReader()
{
Close();
}

bool TextFileReader::Open( LPCTSTR fileName )
{
// Check name
ASSERT( fileName != NULL );
if ( fileName == NULL )
return false;

// The file must be closed
if ( m_file != NULL )
return false;

// Try open the file
m_file = _tfopen( fileName, _T("rt") );
if ( m_file == NULL )
return false;

// Store file name
m_fileName = fileName;

// All right
return true;
}

CString TextFileReader::ReadLine( bool removeNewLine )
{
// Check that the file is open
ASSERT( m_file != NULL );
if ( m_file == NULL )
return _T("");

// Buffer to read the line
static const int maxLineBufferChars = 260;
TCHAR lineBuffer[ maxLineBufferChars ];

// Clear whole buffer before reading
::ZeroMemory( lineBuffer, sizeof(lineBuffer) );

// Read the line from file
if ( _fgetts( lineBuffer, maxLineBufferChars, m_file ) == NULL )
return _T("");

// Remove new line, if requested
if ( removeNewLine )
RemoveEndingNewLine(lineBuffer);

return CString( lineBuffer );
}

void TextFileReader::Close()
{
// Safely close the file
if ( m_file != NULL )
{
fclose( m_file );
m_file = NULL;

m_fileName.Empty();
}
ASSERT( m_fileName.IsEmpty() );
}

</FILE>


MrAsm
David Wilkinson
2007-06-20 12:26:52 UTC
Permalink
Post by r***@yahoo.com
Hi
I am having two text files.
----------------text file1----------------
apple
mango
banana
--------
------random number of line
-------------End of text file1------------
----------------text file----------------
www.wonders.com
www.magic.com
www.moris.com
--------
------random number of line
-------------End of text file1------------
Now what I want is that I want to read the first lines from both file
at a time and do some calculations on them,then I want to read the
second lines from both file and do some calculations on them and so on
for all the lines in both files.This two files will have same number
of lines.
I tried to do like this---->
FILE *fp=NULL;
fp=_tfopen(lpstrPathToUserRss,_T("a+")); //opens Text
file 1
static const int maxLineChars = 200;
TCHAR line[ maxLineChars ];
while ( ! feof(fp) )
{
// Clear destination buffer
::ZeroMemory( line, sizeof(line) );
// Read the line
_fgetts( line, maxLineChars, fp );
CString strLine( line );
FILE *fp1=NULL;
fp1=_tfopen(lpstrPathToUserRssXmlPath,_T("a+")); //opens text file2
static const int maxLineCharsForXmlPath
= 200;
TCHAR
lineForXmlPath[ maxLineCharsForXmlPath ];
while ( ! feof(fp1) )
{
// Clear destination buffer
::ZeroMemory( lineForXmlPath,
sizeof(lineForXmlPath) );
// Read the line
_fgetts( lineForXmlPath,
maxLineCharsForXmlPath, fp1 );
// Now 'line' contains the line read from file.
// Do your processing.
// e.g.: You may store the read line into a
CString
CString strLineForXmlPath( lineForXmlPath );
} //end of second while loop
} //end of first while loop
but this code is wrong because it is getting line1 from text file1
and all lines from text file2 at first time,then it is getting line2
from text file1 and all lines from text file2 at second time,then it
is getting line3 from text file1 and all lines from text file2 at
third time and so on.But what I want is not that.I want to get only
line1 from both files at a time,then only line2 from both files at a
time ,then only line3 from both files at a time and so on upto the
end of files.Plz help me to solve this problem.
rindam:

You only need one while loop.

FILE* file1;
FILE* file2
// open the files
TCHAR line1[ maxLineChars ];
TCHAR line2[ maxLineChars ];

// Read line by line from file
while ( (_fgetts( line1, maxLineChars, file1 ) != NULL) ) &&
(_fgetts( line2, maxLineChars, file2 ) != NULL) )
{
// Process line1, line2
}

Note that, as a discussed yesterday in this thread, testing for eof() is
not the correct way to write the while condition for reading text lines
from a file.

Note also that you can avoid specifying a (possibly wrong) maximum file
length by using std::getline():

std::ifstream file1;
std::ifstream file2
// open the files
std::string line1;
std::string line2;

// Read line by line from file
while ( (std::getline(file1, line1) &&
(std::getline(file2, line2) )
{
// Process line1, line2
}

You can use the c_str() member to get the buffer from the string.
--
David Wilkinson
Visual C++ MVP
MrAsm
2007-06-20 14:00:11 UTC
Permalink
On Wed, 20 Jun 2007 07:26:52 -0500, David Wilkinson
Post by David Wilkinson
You only need one while loop.
FILE* file1;
FILE* file2
// open the files
TCHAR line1[ maxLineChars ];
TCHAR line2[ maxLineChars ];
// Read line by line from file
while ( (_fgetts( line1, maxLineChars, file1 ) != NULL) ) &&
(_fgetts( line2, maxLineChars, file2 ) != NULL) )
{
// Process line1, line2
}
Note that, as a discussed yesterday in this thread, testing for eof() is
not the correct way to write the while condition for reading text lines
from a file.
Yes, it is important that David has marked this point, because the
original version of the code that I posted was *wrong* about feof()
use.

(The second version I posted with the C++ helper class has been
corrected thanks to David's note.)
Post by David Wilkinson
Note also that you can avoid specifying a (possibly wrong) maximum file
std::ifstream file1;
std::ifstream file2
// open the files
std::string line1;
std::string line2;
I posted in this same thread a reading code using C++ iostreams, but
the OP wrote that there was a requirement that he could not use C++
iostreams nor MFC CFile/CStdioFile.

I agree with you that C++ iostreams tend to be more elegant and robust
than C FILE*.

MrAsm

Tom Serface
2007-06-17 05:35:52 UTC
Permalink
Looks to me like your string is not NULL terminated so it's just reading
past the end of what was read into the buffer in memory. You could
terminate it using the return from fread() (the number of characters
actually read) by writing a '\0' into the character array. You should also
call ReleaseBuffer() since you've modified the buffer contents and you could
just pass the length returned in that call.

It's also suspicious that you allocate CString strTitle1 on the stack then
proceed to call GetLength on it before anything is assigned to it. So the
buffer will not have any size. That could cause you some grief as well :o)
If you are reading a text file you could use CStdioFile and that will be a
lot easier to manage.

Tom
Post by r***@yahoo.com
Hi
I am having a typical problem from last one day.I am being able to
writ into a text file from my vc++ application,but I am not being able
to read the file.actually I need to write something in the file and I
need need to again read the file.here is y code which is working fine
FILE *fp=NULL;
fp=_wfopen(lstr,_T("w+"));//lstr is having the path to the file
fwrite( strTitleCurrentDate, sizeof(TCHAR), strTitle.GetLength()/
** sizeof( TCHAR )*/, fp );
fclose( fp );
this code is working fine but
CString strTitle1;
newBuffer=strTitle1.GetBuffer(strTitle1.GetLength()*
sizeof( TCHAR ));
LPTSTR lstr=strPath2.GetBuffer(strTitle.GetLength()* sizeof( TCHAR ));
FILE *fp=NULL;
fp=_wfopen(lstr,_T("a+"));
while(!feof(fp))
fread( newBuffer, sizeof(char), 100/** sizeof( TCHAR )*/, fp );
fclose( fp );
This piece of code really meking me frustrated because the data in
file I am being able to read which actually should be "15th june 2007"
is coming as "15th june 2007SID",from where this SID is coming?One
more thing is that after this code of file reading if I take any
CString variable and try to display it in a message box,it is showing
the value "15th june 2007SID" whereas it should show blank.I am
getting crash also in my application may be due to this problem.Plz
help me to solve this problem with code,because it will help me a
lot.Plz help me as early as possible because the deadline is coming
and I am being frustrated.I also have to read data in a text file line
by line which is also not being possible for me.Plz help me with code.
MrAsm
2007-06-17 09:22:06 UTC
Permalink
On Sat, 16 Jun 2007 22:35:52 -0700, "Tom Serface"
<***@camaswood.com> wrote:

Hi Tom,
Post by Tom Serface
If you are reading a text file you could use CStdioFile and that will be a
lot easier to manage.
CStdioFile should be deprecated ;)
(exspecially for Unicode)

I would consider using CStdioFileEx from CodeProject:

http://www.codeproject.com/file/stdiofileex.asp

or better:

Tom::CStdioFileEx :)

MrAsm
Tom Serface
2007-06-17 14:24:14 UTC
Permalink
Hi Asm,

CStdioFile works OK if you are reading and writing Unicode from a Unicode
compiled program. I thought that is what OP was doing. You're right that
it is inadequate if you don't know the file type or you want to read Unicode
into ANSI or vice versa.

Tom
Post by MrAsm
On Sat, 16 Jun 2007 22:35:52 -0700, "Tom Serface"
Hi Tom,
Post by Tom Serface
If you are reading a text file you could use CStdioFile and that will be a
lot easier to manage.
CStdioFile should be deprecated ;)
(exspecially for Unicode)
http://www.codeproject.com/file/stdiofileex.asp
Tom::CStdioFileEx :)
MrAsm
MrAsm
2007-06-17 14:44:34 UTC
Permalink
On Sun, 17 Jun 2007 07:24:14 -0700, "Tom Serface"
Post by Tom Serface
CStdioFile works OK if you are reading and writing Unicode from a Unicode
compiled program. I thought that is what OP was doing. You're right that
it is inadequate if you don't know the file type or you want to read Unicode
into ANSI or vice versa.
Hi Tom

you are right.

Moreover, I've read here:

http://msdn2.microsoft.com/en-us/library/yeby3zcb(VS.80).aspx

that VS2005 extended fopen() with new "mode" strings to support
Unicode, UTF-8, UTF-16LE, BOM, etc.

This is *very* good (even if maybe it is non-standard).

Maybe also the new CStdioFile implementation of MFC 8 (VC++2005)
offers better support to Unicode and ANSI/Unicode mix?

MrAsm
MrAsm
2007-06-17 22:22:40 UTC
Permalink
On Sun, 17 Jun 2007 07:24:14 -0700, "Tom Serface"
Post by Tom Serface
Hi Asm,
CStdioFile works OK if you are reading and writing Unicode from a Unicode
compiled program.
Hi Tom,

I've just tried that in VS2003, and I have problem.

So, my original recall that CStdioFile had problems *also* in
reading/writing Unicode in Unicode builds seems correct.

This is a Unicode build (in fact I also forced strings using L
decoration).

I write what seems a Chinese character to me (please note that I'm not
a Far-East language expert, so this symbol may be from other languages
of the Far-East).

I've built the symbol using Unicode UTF16 in WCHAR 'kanji' string.

WCHAR kanji[2];
kanji[0] = 0x5B51;
kanji[1] = 0x0000; // End of string

The symbol is displayed correctly by VS.NET IDE (when I hang mouse
cursor over 'kanji' variable).

I can write this symbol with CStdioFileEx and read it back from file
and display it again with no problem. But CStdioFile does *fail* doing
that: in fact, if I inspect the file badly written by CStdioFile and
the file correctly written by CStdioFileEx, and I compare these files,
I see that the bytes in those files corresponding to the kanji symbol
are different.

BTW: The CStdioFileEx I'm using for this test is the one found on
CodeProject:

http://www.codeproject.com/file/stdiofileex.asp

So, while I can write and read Unicode correctly using CStdioFileEx,
CStdioFile seems to fail, also in Unicode builds.

May be it's me doing some error with CStdioFile and Unicode?

However, I tend to use Unicode UTF-16 inside apps, and Unicode UTF-8
outside (e.g. in external files). The conversion between the two
Unicode format is done at the app boundaries.

This is the testing code:

<CODE>

// Kanji symbol definition
WCHAR kanji[2];
kanji[0] = 0x5B51;
kanji[1] = 0x0000; // End of string


//
// CStdioFile Write Test
//
CStdioFile data( L"c:\\test.txt",
CFile::modeCreate | CFile::modeWrite | CFile::typeText );


data.WriteString(L"Hello\n");
data.WriteString(kanji);
data.WriteString(L"\nhello again");


//
// CStdioFileEx Write Test
//

CStdioFileEx data1( L"c:\\test1.txt",
CFile::modeCreate | CFile::modeWrite |
CStdioFileEx::modeWriteUnicode ); // CStdioFileEx Unicode flag

data1.WriteString(L"Hello\n");
data1.WriteString(kanji);
data1.WriteString(L"\nhello again");

data1.Close();


//
// CStdioFileEx Read Test
//
CStdioFileEx data2( L"c:\\test1.txt",
CFile::modeRead | CFile::typeText );

CString s;

//
// I inspect the read lines using the IDE in step-by-step
// debugging, and the read data is correct.
//
data2.ReadString(s);
data2.ReadString(s);
data2.ReadString(s);

</CODE>

MrAsm
Joseph M. Newcomer
2007-06-17 18:06:00 UTC
Permalink
See below...
Post by r***@yahoo.com
Hi
I am having a typical problem from last one day.I am being able to
writ into a text file from my vc++ application,but I am not being able
to read the file.actually I need to write something in the file and I
need need to again read the file.here is y code which is working fine
FILE *fp=NULL;
fp=_wfopen(lstr,_T("w+"));//lstr is having the path to the file
fwrite( strTitleCurrentDate, sizeof(TCHAR), strTitle.GetLength()/
** sizeof( TCHAR )*/, fp );
fclose( fp );
this code is working fine but
CString strTitle1;
newBuffer=strTitle1.GetBuffer(strTitle1.GetLength()*
sizeof( TCHAR ));
*****
strTitle1.GetLength() is of course 0, so this gives you a pointer to a 0-length
buffer!!!!! You should not be surprised if this fails
*****
Post by r***@yahoo.com
LPTSTR lstr=strPath2.GetBuffer(strTitle.GetLength()* sizeof( TCHAR ));
******
I did not see a definition of strTitle here, so I can only presume it is the same variable
from above.
******
Post by r***@yahoo.com
FILE *fp=NULL;
fp=_wfopen(lstr,_T("a+"));
while(!feof(fp))
fread( newBuffer, sizeof(char), 100/** sizeof( TCHAR )*/, fp );
fclose( fp );
This piece of code really meking me frustrated because the data in
file I am being able to read which actually should be "15th june 2007"
is coming as "15th june 2007SID",from where this SID is coming?
*****
And where, exactly, did you put a terminating NUL character after the bytes you read in?
I'm surprised it is something as readable as 'SID'. Your input routine is erroneous
because it does not terminate the string it read in, but then you obviously treat it as a
terminated string, so you are seeing the sort of error such a bug would produce
*****
Post by r***@yahoo.com
One
more thing is that after this code of file reading if I take any
CString variable and try to display it in a message box,it is showing
the value "15th june 2007SID" whereas it should show blank.I am
getting crash also in my application may be due to this problem.
*****
There is no such thing as a "crash" as a meaningful description, unless it is accompanied
by the details of the error and as much information as possible to analyze it.
*****
Post by r***@yahoo.com
Plz
help me to solve this problem with code,because it will help me a
lot.Plz help me as early as possible because the deadline is coming
and I am being frustrated.I also have to read data in a text file line
by line which is also not being possible for me.Plz help me with code.
*****
You wrote out n characters. Note that you used GetLength(), which is tne number of
characters in the string, not including the terminating NUL character. You read in n
characters, which of course means there is no terminating NUL character. If you don't put
one in, it does not appear by magic. If you are reading n 8bit characters, you would
store in string[n] the value '\0'. If you are reading n Unicode characters (2*n bytes),
you would store in string[n/sizeof(WCHAR)] the value L'\0'.
joe
*****
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Christopher Benson
2007-06-18 02:05:23 UTC
Permalink
Hello,

Did anybody mention that when writing data, the file is opened in "w+" mode
(READ and WRITE access, destroy any previous content)? I assume this OK for
you.

But when reading the data, the file is opened in "a+" mode. The 'a' is for
APPEND
at the end of file, athough the '+' means you can read existing data, but I
think only
if you reposition the file pointer (e.g. with fseek(), or rewind()) calls
before calling fread().

I believe that in "a+' mode, the current file position is initially at the
end of the file,
so there is no [more] data to read from that point, when the file is first
opened.

If the fopen() for the read operation is just for reading, then using mode
"r" instead
of "a+" will start at the beginning of the file. Otherwise, you will need to
rewind() or
similar to go backwards in the file to find existing data.

Others had valid contributions, but I think is the the cause of the fread()
failure.
Gosh, having written that, I hope my recollection is correct

Best wishes, from Old Chris.
Post by r***@yahoo.com
Hi
I am having a typical problem from last one day.I am being able to
writ into a text file from my vc++ application,but I am not being able
to read the file.actually I need to write something in the file and I
need need to again read the file.here is y code which is working fine
FILE *fp=NULL;
fp=_wfopen(lstr,_T("w+"));//lstr is having the path to the file
fwrite( strTitleCurrentDate, sizeof(TCHAR), strTitle.GetLength()/
** sizeof( TCHAR )*/, fp );
fclose( fp );
this code is working fine but
CString strTitle1;
newBuffer=strTitle1.GetBuffer(strTitle1.GetLength()*
sizeof( TCHAR ));
LPTSTR lstr=strPath2.GetBuffer(strTitle.GetLength()* sizeof( TCHAR ));
FILE *fp=NULL;
fp=_wfopen(lstr,_T("a+"));
while(!feof(fp))
fread( newBuffer, sizeof(char), 100/** sizeof( TCHAR )*/, fp );
fclose( fp );
This piece of code really meking me frustrated because the data in
file I am being able to read which actually should be "15th june 2007"
is coming as "15th june 2007SID",from where this SID is coming?One
more thing is that after this code of file reading if I take any
CString variable and try to display it in a message box,it is showing
the value "15th june 2007SID" whereas it should show blank.I am
getting crash also in my application may be due to this problem.Plz
help me to solve this problem with code,because it will help me a
lot.Plz help me as early as possible because the deadline is coming
and I am being frustrated.I also have to read data in a text file line
by line which is also not being possible for me.Plz help me with code.
Loading...