Click to See Complete Forum and Search --> : ReadFile, WriteFile, etc


cpp_programmer
March 16th, 2004, 08:49 AM
hi,

I've been trying to figure out how to use the ReadFile and WriteFile functions. Is there an example I can see of how to use it?

And also, is it possible somehow to use the C++ string class with it, so that I can figure out the length of the text using that? That would be a lot easier.

thanks.


Brandon

Andreas Masur
March 16th, 2004, 09:30 AM
Well...simply do a forum search....there are enough examples for both of your questions... :cool:

cpp_programmer
March 16th, 2004, 11:23 AM
hi,

Thanks. I searched a bit, but didn't come up with too much. Most of it is about other things besides files, like ports, pipes, etc. I"ll keep trying though, but any help would be appreciated.

Ok, a third question though. With the SetFilePointer function, it doesn't seem to return any error when it reaches the end of the file. Say my file is 4 bytes long, and I try setting the pointer to the fifth or sixth byte, I thought that the functionw as suppose to return 0xFFFFFFFF? But it doesn't seem to do so.

Further, what is the purpose of the third argument? That is, the highbyte variable.

Thanks again.


Brandon

Andreas Masur
March 16th, 2004, 05:52 PM
Reading and Writing Asynchronously (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/reading_and_writing_asynchronously.asp)...

Other than that, you might simply want to look at the MSDN documentation for these functions as well...

Andreas Masur
March 16th, 2004, 05:57 PM
Originally posted by cpp_programmer
With the SetFilePointer function, it doesn't seem to return any error when it reaches the end of the file. Say my file is 4 bytes long, and I try setting the pointer to the fifth or sixth byte, I thought that the functionw as suppose to return 0xFFFFFFFF? But it doesn't seem to do so.

From MSDN:

Return Values

If the SetFilePointer function succeeds and lpDistanceToMoveHigh is NULL, the return value is the low-order DWORD of the new file pointer. If lpDistanceToMoveHigh is not NULL, the function returns the low order DWORD of the new file pointer, and puts the high-order DWORD of the new file pointer into the LONG pointed to by that parameter.

If the function fails and lpDistanceToMoveHigh is NULL, the return value is INVALID_SET_FILE_POINTER. To get extended error information, call GetLastError.

If the function fails, and lpDistanceToMoveHigh is non-NULL, the return value is INVALID_SET_FILE_POINTER. However, because INVALID_SET_FILE_POINTER is a valid value for the low- order DWORD of the new file pointer, you must check GetLastError to determine whether an error occurred. If an error occurred, GetLastError returns a value other than NO_ERROR. For a code example that illustrates this point, see the Remarks section later in this topic.

If the new file pointer would have been a negative value, the function fails, the file pointer is not moved, and the code returned by GetLastError is ERROR_NEGATIVE_SEEK.


Originally posted by cpp_programmer
Further, what is the purpose of the third argument? That is, the highbyte variable.

Again from MSDN:

Although the parameter lpDistanceToMoveHigh is used to manipulate huge files, the value of this parameter should be set when moving files of any size. If it is set to NULL, then lDistanceToMove has a maximum value of 2^31–2, or 2 gigabytes less two. This is because all file pointer values are signed values. Therefore if there is even a small chance that the file will grow to that size, you should treat the file as a huge file and work with 64-bit file pointers. With file compression on NTFS, and sparse files, it is possible to have files that are large even if the underlying volume is not very large.

If lpDistanceToMoveHigh is not NULL, then lpDistanceToMoveHigh and lDistanceToMove form a single 64-bit signed value. The lDistanceToMove parameter is treated as the low-order 32 bits of the value, and lpDistanceToMoveHigh as the upper 32 bits. Thus, lpDistanceToMoveHigh is a sign extension of lDistanceToMove.

To move the file pointer from zero to 2 gigabytes, lpDistanceToMoveHigh must be set to either NULL or a sign extension of lDistanceToMove. To move the pointer more than 2 gigabytes, use lpDistanceToMoveHigh and lDistanceToMove as a single 64-bit quantity. For example, to move in the range from 2 gigabytes to 4 gigabytes set the contents of lpDistanceToMoveHigh to zero, or to –1 for a negative sign extension of lDistanceToMove.

To work with 64-bit file pointers, you can declare a LONG, treat it as the upper half of the 64-bit file pointer, and pass its address in lpDistanceToMoveHigh. This means you have to treat two different variables as a logical unit, which is error-prone. The problems can be ameliorated by using the LARGE_INTEGER structure to create a 64-bit value and passing the two 32-bit values by means of the appropriate elements of the union.

cpp_programmer
March 16th, 2004, 07:01 PM
hi again,


Yeah I have looked at the msdn documentation. That page you linked to is nice, but that example is way too complicated for me right now! I do know the basics of how this works, I just had those questions about using them. I can't remember if I said this in my last post or not, but interestingly, I have a less difficult time writing or reading an integer or some other datatype, rather than a character array.

Anyway, if you can help with this, could you do the following:


string str = "Hello.";

HANDLE hFile = CreateFile(
"file.txt",
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);

DWORD bytes_written;
WriteFile(hFile, str.c_str(), str.length(), &bytes_written, NULL);

CloseHandle(hFile);


and if you can, then how would you get that file's text back into that string?

Oh, and, the thing I was confused about before. When writing or reading a character array, do you have to also specify in the length, room for the NULL terminator, also? For instance, if the string is 5 characters, do you have to put 6 as the length argument of WriteFile or ReadFile?

Sam Hobbs
March 17th, 2004, 02:06 PM
Originally posted by cpp_programmer
When writing or reading a character array, do you have to also specify in the length, room for the NULL terminator, also?Probably not, but it depends on what you want to do. You will need to have a way to know the size of the string when you read it. A NULL is usually a bad way to do that in a file, but it can be used.

I don't know if it is clear from what you have said if you want to read the string after writing it without closing the file or if you want to open the file separatly to read it. The main reason it is not clear is that you use "GENERIC_READ|GENERIC_WRITE" in the CreateFile to write the file.

Instead of asking for a sample of how to read the file, try to do it yourself and ask for help with the specific parameters you need help with.

Andreas Masur
March 17th, 2004, 02:13 PM
Originally posted by cpp_programmer

string str = "Hello.";

HANDLE hFile = CreateFile(
"file.txt",
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);

DWORD bytes_written;
WriteFile(hFile, str.c_str(), str.length(), &bytes_written, NULL);

CloseHandle(hFile);


That should actually work...getting it back to a STL string would not that easy since there is no direct write access to the string...

cpp_programmer
March 17th, 2004, 03:28 PM
Originally posted by Sam Hobbs
I don't know if it is clear from what you have said if you want to read the string after writing it without closing the file or if you want to open the file separatly to read it. The main reason it is not clear is that you use "GENERIC_READ|GENERIC_WRITE" in the CreateFile to write the file.

It doesn't really matter; I just did that since in my tests with the functions I was using the same handle without closing it. But either way, that shouldn't really make a difference, as long as I set the pointer back to the beginning.

Instead of asking for a sample of how to read the file, try to do it yourself and ask for help with the specific parameters you need help with.

You see, I have; I've tried. I don't just post without first trying and researching all I can. I said before that I seem to have more success when I'm writing or reading another variable type besides a string for some reason. But the result when I try writing or reading a string (character array) is that if I don't specify an extra byte for that terminator, I get unexpected data when reading it back. It will read some of it correctly, then it will give unexpected characters. That was why I asked if you were suppose to provide an extra byte for that terminator.

thanks for the help.


Edit:


Here is a sample program I made, just so you'd think I at least tried doing this. :)



#include <iostream>
#include <windows.h>
#include <string>

using namespace std;

int main()
{
HANDLE hFile = CreateFile(
"myfile.txt",
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);


string str;
cout << "Enter a string" << endl;
getline(cin, str);


DWORD bytes;
cout << "Writing..." << endl;
WriteFile(hFile, str.c_str(), str.length(), &bytes, NULL);

cout << bytes << " bytes written" << endl;



SetFilePointer(hFile, 0, NULL, FILE_BEGIN);

cout << "Reading..." << endl;

char* buffer = new char (str.length() + 1);
ReadFile(hFile, buffer, str.length(), &bytes, NULL);

cout << bytes << " bytes read" << endl;
cout << "Data" << endl;
str = buffer;
cout << str << endl;

CloseHandle(hFile);
}



Sample output:


Enter a string
Hello.


Writing...
6 bytes written


Reading...
6 bytes read

Data
Hello.A



Another sample output:



Enter a string
This is some sample input.


Writing...
23 bytes written

Reading...
23 bytes read


Data:
This is a sample input.

"fileio.exe has encountered a problem and needs to close. We are sorry for the inconvenience. If you were in the middle of something, the information you were working on might be lost. For more information about this error, click here." Close button


So in one instance, it added a nonexistent A. And in the second example, it encountereda problem and had to close.....


Brandon

Andreas Masur
March 17th, 2004, 04:38 PM
Originally posted by cpp_programmer
So in one instance, it added a nonexistent A. And in the second example, it encountereda problem and had to close.....


char* buffer = new char[str.length() + 1];
ReadFile(hFile, buffer, str.length(), &bytes, NULL);

cout << bytes << " bytes read" << endl;
cout << "Data" << endl;
str = buffer;
cout << str << endl;

delete [] buffer;

CloseHandle(hFile);

Paul McKenzie
March 17th, 2004, 04:48 PM
You can also use Andreas's code, but without the new/delete:

#include <vector>
//...
std::vector<char> buffer(str.length() + 1);
ReadFile(hFile, &buffer[0], str.length(), &bytes, NULL);

cout << bytes << " bytes read" << endl;
cout << "Data" << endl;
str = &buffer[0];
cout << str << endl;

CloseHandle(hFile);

Regards,

Paul McKenzie

Andreas Masur
March 17th, 2004, 04:57 PM
Originally posted by Paul McKenzie
You can also use Andreas's code, but without the new/delete:

Which is even much better, since it eliminates potential memory leaks (such as the one in the original code)...

cpp_programmer
March 17th, 2004, 05:13 PM
Originally posted by Paul McKenzie
You can also use Andreas's code, but without the new/delete:

Yeah, thanks. I never thought of that one.


I tend to forget to free memory sometimes. :) still doesn't work though, but I don't think I get that "fileio.exe has encountered a problem and needs to close" error anymore. I will try out the vector method now.


Any explanation to why my code, (minus my little mistake), gave the output it did?

Sam Hobbs
March 17th, 2004, 06:10 PM
Originally posted by Sam Hobbs
ask for help with the specific parameters you need help with.That is the important part that I did not see. It might be more educational to get answers about specific parameters instead of an example showing one possible solution without a corresponding explanation.
Originally posted by cpp_programmer
Any explanation to why my code, (minus my little mistake), gave the output it did? Yes, explanations can be helpful. I will try to take more time to help with that too.

zariostr
March 18th, 2004, 12:15 AM
hi

you use ReadFile when you know length of string
but if you haven't it ?
i need read file, all strings from it and put it in list box
so i haven't string length there

thanks

Andreas Masur
March 18th, 2004, 04:18 AM
Originally posted by cpp_programmer
Any explanation to why my code, (minus my little mistake), gave the output it did?
Initialize your allocated array by

memset(buffer, 0, str.length() + 1);

cpp_programmer
March 18th, 2004, 03:39 PM
Originally posted by zariostr
hi

you use ReadFile when you know length of string
but if you haven't it ?
i need read file, all strings from it and put it in list box
so i haven't string length there

thanks

Do you mean you are trying to get multiple strings from multiple files? You can get the file size by GetFileSize() if that is what you need. Otherwise, you can set a length, and read by increments; i.e., read so many characters at a time.

zariostr
March 19th, 2004, 12:10 AM
i use this code but it's not read right

char data[255];

void OpeningFile()
{
of_name.lStructSize=sizeof(OPENFILENAME);
of_name.hwndOwner=hwnd;
of_name.hInstance=hInstance;
of_name.lpstrFile=szFile;
of_name.nMaxFile=sizeof(szFile);
of_name.lpstrFilter="*.TXT\0";
of_name.nFilterIndex=1;
of_name.lpstrFileTitle=NULL;
of_name.nMaxFileTitle=0;
of_name.lpstrInitialDir=NULL;
of_name.Flags=OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;

BOOL bResult;
DWORD howmuch;
LPSTR filename;

HWND preList;
preList=GetDlgItem(hDlg,IDC_LIST3);
if (GetOpenFileName(&of_name)==TRUE)
{
filename=of_name.lpstrFile;
SendMessage(preList,LB_RESETCONTENT,0,0);
filename=of_name.lpstrFile;
hf=CreateFile(filename,GENERIC_READ,0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hf)
{

while(howmuch!=0)
{
bResult=ReadFile(hf,&data,255,&howmuch,NULL);
SendMessage(preList,LB_ADDSTRING,0,(LPARAM)data);
}
}
UpdateWindow(hwnd);
}
CloseHandle(hf);
}

// second my question
when i read file i get "||" i think it's "\r\n" symbols how remove them ?