C++ Overwriting Contents of a Handle - c++

I am trying to get a number from a HANDLE file, store it in an int, and possibly replace it in the same file. My code right now looks like this
HANDLE numFile = INVALID_HANDLE_VALUE; //Just in case file not found
numFile = CreateFile("numFile.txt",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
ReadFile(numFile, input, sizeof(char), &bytesRead, NULL);
int myNumber = input[0];
I know that there exists a WriteFile method in the API, but it looks like it will append the file as opposed to overwriting the contents. I have briefly considered deleting and recreating the file each time, but this seems unnecessarily complex for this problem. Any ideas out there?

Use the function SetFilePointer prior WriteFile for moving back to the begin
SetFilePointer(numFile, 0, NULL, FILE_BEGIN);

Related

IWICImagingFactory::CreateDecoderFromFilename() keeps the file locked even after the decoder is destroyed

I'm using IWICImagingFactory::CreateDecoderFromFilename() for reading only. Is there a way I can pass something like the FILE_SHARE_READ flag? The file stays open from the function call above until the program terminates.
During another operation within the same program, I attempted to use CFile::Open(), but I got error 32 ("The process cannot access the file because it is being used by another process").
What I ended up doing was using
pImagePoolEntry->hFileHandle = CreateFile(
path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
before the call to CreateDecoderFromFilename().
Since I was already using an Image Pool keeping track of opened, shared images I just added the initial file handle and added code to use CloseHandle() when the image was not longer in use.
I'm not sure what the IWICBitmapDecoder does with the file, but it seems to be keeping it opened past the Release() call on it. It might have a bug where the handle isn't closed, who knows. I couldn't find any information on that behaviour. Actually, apart from this question, nobody seems to have noticed (or nobody cares).
In any case, the solution, as hinted by Tony, is to open the file manually and use CreateDecoderFromFileHandle() instead of CreateDecoderFromFilename(). Note that "the file handle must remain alive during the lifetime of the decoder."
So this:
void f(IWICImagingFactory* factory, const wchar_t* path)
{
IWICBitmapDecoder* decoder = nullptr;
factory->CreateDecoderFromFilename(
path, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &decoder);
// ...
decoder->Release();
}
becomes this:
void f(IWICImagingFactory* factory, const wchar_t* path)
{
auto h = CreateFileW(
path, GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
IWICBitmapDecoder* decoder = nullptr;
factory->CreateDecoderFromFileHandle(
reinterpret_cast<ULONG_PTR>(h), nullptr,
WICDecodeMetadataCacheOnLoad, &decoder);
// ...
decoder->Release();
CloseHandle(h);
}

Why does WriteFile not run more than once?

Here's my code in which I've got on an infinite loop (to my knowledge)
while(true) {
DWORD TitleID = XamGetCurrentTitleId();
std::ostringstream titleMessageSS;
titleMessageSS << "Here's the current title we're on : " << TitleID << "\n\n";
std::string titleMessage = titleMessageSS.str(); // get the string from the stream
DWORD dwBytesToWrite = (DWORD)titleMessage.size();
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
HANDLE logFile = CreateFile( "Hdd:\\LOGFile.txt", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
bErrorFlag = WriteFile(logFile, titleMessage.c_str(), dwBytesToWrite, &dwBytesWritten, NULL);
CloseHandle(logFile);
Sleep(30000);
}
return NULL;
Does anyone see a reason as to why this only writes just once? I've waited over 5 minutes to see if it does anything in the end to no avail.
The Flag CREATE_NEW in CreateFile prevents the update of the file because CreateFile fail with ERROR_FILE_EXISTS. Use OPEN_ALWAYS instead.
Also it will always truncate. Replace GENERIC_WRITE with FILE_APPEND_DATA if you want to add a new line at the end of your logfile.
The whole CreateFile line should be:
HANDLE logFile = CreateFile( "Hdd:\\LOGFile.txt", FILE_APPEND_DATA , 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
Read CreateFile documentation carefully, it worth it, because it has a central role in the windows IO universe:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
look also add:
https://stackoverflow.com/a/9891875/1922748
As Martin James mentioned, from MSDN:
CREATE_NEW
Creates a new file, only if it does not already exist.
If the specified file exists, the function fails and the last-error
code is set to ERROR_FILE_EXISTS (80).
If the specified file does not exist and is a valid path to a writable
location, a new file is created.
So it seems that the handle is invalid after the first call, and hence WriteFile() fails.

Write to a txt file using windows API

I am trying to write some lines to a a txt file through an ATL application. Below is the fragment of code I use:
HANDLE hFile = CreateFile(ofn.lpstrFile,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
DWORD dwBytesWritten = 0;
std::list<CString> helpList;
std::list<CString>::iterator it;
helpList.push_back(L"First Line\r\n");
helpList.push_back(L"Second Line");
for(it=helpList.begin(); it!=helpList.end(); ++it)
WriteFile( hFile, (*it).GetString(), (*it).GetLength(), &dwBytesWritten, NULL );
CloseHandle(hFile);
Notwithstanding everything is working right, nothing is finally written to the file. What should I change in the code?
Couple of issues:
Close the handle to the file using CloseHandle()
The length argument for WriteFile() is in bytes but you're specifying characters. Since you're using wide chars you need to multiple the length value by the size of the char.

Can't get ReadFile to read from the file i just wrote to

Im writing to a file using WriteFile. That works fine. Its just a simple string:
"Test string, testing windows functions".
Im trying to read from the file now and compare with the string i write just to ensure its working properly. I have:
DWORD dwBytesRead;
char buff[128];
ReadFile(hFile, buff, 128, &dwBytesRead, NULL)
But its returning false for me. hFile is the handle I use when writing to the file. Can have any ideas about what might be going on?
EDIT (updated from comment):
I'm getting E_ACCESSDENIED from GetLastError(). Here is how i got hFile:
hFile = CreateFile (TEXT(movedFileName.c_str()),
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
hFile has been opened for GENERIC_WRITE only. It needs to be opened with GENERIC_READ if you want to read from it as well as write to it:
hFile = CreateFile (TEXT(movedFileName.c_str()),
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);

CreateFile / WriteFile is not destroying contents of old file

The old contents are not being wiped out.
Instead the data is being written over, so I still see old contents.
What did I not do?
hFile = CreateFile(fname, // open testfile.txt
GENERIC_WRITE, // open for reading
0, // do not share
NULL, // default security
OPEN_ALWAYS, //
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attribute template
dwBytesToWrite = buff.GetLength();
WriteFile(hFile, buff.GetBuffer(100), dwBytesToWrite, &dwBytesWritten, NULL);
You have specified the wrong value for dwCreationDisposition. You need to specify CREATE_ALWAYS.
Creates a new file, always.
If the specified file exists and is writable, the function overwrites the file, the function succeeds, and last-error code is set to ERROR_ALREADY_EXISTS (183).
If the specified file does not exist and is a valid path, a new file is created, the function succeeds, and the last-error code is set to zero.
In dwCreationDisposition you need to specify CREATE_ALWAYS.
You need dwCreationDisposition = TRUNCATE_EXISTING. This however:
Opens a file and truncates it so that its size is zero bytes, only if
it exists. If the specified file does not exist, the function fails
and the last-error code is set to ERROR_FILE_NOT_FOUND (2). The
calling process must open the file with the GENERIC_WRITE bit set as
part of the dwDesiredAccess parameter.
So I would try and open it first with TRUNCATE_EXISTING. If it fails with ERROR_FILE_NOT_FOUND, then open it with CREATE_NEW.
hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, TRUNCATE_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if ((hFile == NULL) && (GetLastError() == ERROR_FILE_NOT_FOUND))
{
hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL);
}
EDIT: This is not the best way to do this. CREATE_ALWAYS is the dwCreationDisposition you want to use. See David Heffernan's answer.