C++: fopen() returns handle to empty file - c++

I'm getting a strange file handle from fopen; the pointer itself isn't NULL, but the file it represents has no size, and feof(file) is already set... what could be causing this?
(I triple checked the file itself, it exists, has data, and the file's permissions are okay... and filename is set to "source/test_file.object.txt")
bool tagFile(const char * filename){
FILE * file = fopen(filename, "r");
if(file == NULL){ // file is not NULL
printf(" Couldn't open the file %s", filename);
return false;
}
int size = fseek(file, 0, SEEK_END); // size is 0
rewind(file);
while(feof(file)){
.... // never executes because feof(file) fails
}
}
0x002cc410 // value of 'file' in the debugger
_ptr=0x00000000 <Bad Ptr>
_cnt=0
_base=0x00000000 <Bad Ptr>
_flag = 1
_file = 3

The most common cause of this is simply opening a file which is empty. There are no bytes to read so EOF is immediate, but the file exists so fopen can't return NULL.

Related

Passing a char array reading from file to fopen() generating error as Invalid arguments

I tried to read file path and name into a char array from a configuration.txt file. Then passing the char array to fopen(). However, it is generating errors like invalid argument. Instead, if I directly passed the path same to what is in configuration.txt, it will succeed. The code is like:
FILE *FIDConfig = fopen(argv[1],"r"); // open configuration file; could be a .txt file
char inputfname[200], backgroundfname[200], outputfname[200];
fscanf(FIDConfig, "%s", inputfname); //int fscanf ( FILE * stream, const char * format, ... );
fscanf(FIDConfig, "%s", backgroundfname);
fscanf(FIDConfig, "%s", outputfname);
/* FILE WITH THE RAW DATA */
errno = 0;
FILE *FIDIN, *FIDOUT, *FIDBack; // inputfname = "./data.bin", backgroundfname = "./dbk.bin";
FIDIN = fopen(inputfname, "rb"); // if changed to FIDIN("./data.bin","rb") it works!
FIDBack = fopen(backgroundfname, "rb");

How to open a file with append mode only if it exist

The function fopen("file-name",a); will return a pointer to the end of the file. If the file exist it is opened, otherwise a new file is created.
Is it possible to use the append mode and open the file only if it already exist? (and return a NULL pointer otherwise).
Thanks in advance
To avoid race conditions, opening and checking for existence should be done in one system call. In POSIX this can be done with open as it will not create the file if the flag O_CREAT is not provided.
int fd;
FILE *fp = NULL;
fd = open ("file-name", O_APPEND);
if (fd >= 0) {
/* successfully opened the file, now get a FILE datastructure */
fp = fdopen (fd, "a")
}
open may fail for other reasons too. If you do not want to ignore all of them, you will have to check errno.
int fd;
FILE *fp = NULL;
do {
fd = open ("file-name", O_APPEND);
/* retry if open was interrupted by a signal */
} while (fd < 0 && errno == EINTR);
if (fd >= 0) {
/* successfully opened the file, now get a FILE datastructure */
fp = fdopen (fd, "a")
} else if (errno != ENOENT) { /* ignore if the file does not exist */
perror ("open file-name"); /* report any other error */
exit (EXIT_FAILURE)
}
First check if the file already exists. A simple code to do that might be like this:
int exists(const char *fname)
{
FILE *file;
if ((file = fopen(fname, "r")))
{
fclose(file);
return 1;
}
return 0;
}
It will return 0 if file doesn't exist...
and use it like this:
if(exists("somefile")){file=fopen("somefile","a");}

_read function is returning obsolete values for file handle

The block of code here runs fine till the _read function is called, after that it changes the value of file handle variable 'fh' for no reason.
std::string& xLogFile;
std::string& xBuffer;
struct _stat& xStatBuffer)
char *buffer;
buffer = (char *)malloc(sizeof(char) * xStatBuffer.st_size);
#define _O_RDONLY 0x0000 /* open for reading only */
int fh = 0, read_bytes =0;
fh = _open(xLogFile.c_str(), _O_RDONLY); // ToDo function deprecated should be changed to fstream
if (fh ==1)
{
if (mWriteLog) IntPkgUtil::TraceLog("Error!! Couldn't open the log file");
return true;
}
read_bytes = _read(fh,&buffer,xStatBuffer.st_size);
_close(fh);
if (read_bytes <= 0)
{
if (mWriteLog) IntPkgUtil::TraceLog("Error!! Couldn't read the log file");
return true;
}
buffer[read_bytes] = '\0';
xBuffer = buffer;
This is a block of code i am using to read from a file into a buffer, but it is failing at the _read function, where the value of file handle 'fh' changes after the call to the function.
Fix the code as below, buffer and not &buffer. You are overwriting the stack.
read_bytes = _read(fh,buffer,xStatBuffer.st_size);

Check unsupported file name for fopen

I'm trying to open a file to treat it later. My problem is that if my file name is not ANSI (Arabic, Hindi...) fopen_s and fopen refuse to open it and give me an Invalid argument error. I can't use CreateFile() to do that so I thought to check either my file name is supported by fopen or not(try to open it) and create a temporary file instead:
QString fileN=QString::fromWCharArray(fname);
QFileInfo file(DIRPath+"/"+fileN);
bool Supported=true;
if(file.exists()) {
QString temp;
char* Fname=(char*)malloc(260*sizeof(char));
strcpy(Fname,(QString(DIRPath+"/"+fileN).toStdString()).c_str());
FILE* Filedesc;
errno_t err=fopen_s(&Filedesc,Fname,"rb");
if(Filedesc!=NULL) {
qDebug()<<"\nfile opened ";
fclose(Filedesc);
} else if(err==22) {
qDebug()<<"\nfail to open file error 22: Invalid argument";
temp=QString(DIRPath+"/Temp"+QString::number(nb));
Supported=false;
} else qDebug()<<"\nfail to open file error"<<GetLastError()<<"errno"<<errno<<"strerrno"<<strerror(errno);
Fname=NULL;
free(Fname);
...
My question is: can anyone clarify for me the UNICODE/ANSI confusion? Am I safe so far or are there more precautions to consider? Is there a safer way to check if the given name is not ANSI?
Thank you in advance, any help will be appreciated.
EDIT 1
I tried this but in vain : CreateFile() return an INVALID_HANDLE_VALUE and GetLastError() return 0
//WCHAR fname[]=L"D:/أحدالأنشطة.txt";
char* name="D:/أحدالأنشطة.txt";
wchar_t* nameW=(wchar_t*)malloc(sizeof(wchar_t)*17);
qDebug()<<"s :"<<mbstowcs(nameW,name,17);
//QString path=QString::fromWCharArray(fname,17);
//QString path=QString::fromLatin1(name,17);
HANDLE fileHandle = CreateFile( nameW, // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL);
if (fileHandle == INVALID_HANDLE_VALUE)
{
qDebug()<<"CreateFile failed!\n"<<GetLastError();
nameW=NULL;
free(nameW);
return 2;
}else
qDebug()<<"CreateFile succeeded!\n";
int fd = _open_osfhandle((intptr_t) fileHandle, _O_RDONLY);
FILE* fstr = _fdopen(fd, "r");
QFile indirect;
if (!indirect.open(fstr, QIODevice::ReadOnly))
qDebug()<<"QFile open against file descriptor failed!\n";
else
{
qDebug()<<"QFile open against file descriptor succeeded!\n";
indirect.close();
}
// This will fail
QFile direct(path);
if (!direct.open(QIODevice::ReadOnly))
qDebug()<<"QFile open of filename directly failed!\n";
else
{
qDebug()<<"QFile open of filename directly succeeded!\n";
direct.close();
}
nameW=NULL;
free(nameW);
EDIT 2
QString fname(QFile::decodeName("D:/أحدالأنشطة.txt"));
QFile qFile(fname);
bool b=qFile.open(QIODevice::ReadOnly);
if(b)
{
FILE* filedesc = fdopen(qFile.handle(), "rb");
if(filedesc!=NULL)
{
char* nb=(char*)malloc(2*sizeof(char));
qDebug()<<"opened ";
size_t size=fread(nb,sizeof(char),2,filedesc);
fclose(filedesc);
qDebug()<<"filedesc closed size "<<size<<"nb "<<QString::fromAscii(nb,2);
nb=NULL;
free(nb);
}else qDebug()<<"filedesc failed error"<<strerror(errno);
}else
qDebug()<<"qFile failed error"<<strerror(errno);
You should probably use QFile to open the file, and then pass QFile::handle() to your C function. In the C code you would then use fdopen() to associate a FILE* stream to the file descriptor. Note that the mode you use in fdopen() should be compatible with the mode you used in QFile::open(). For example:
void c_func(int fd)
{
FILE* file = fdopen(fd, "rb");
// ...
}

C++ fwrite doesn't write to text file, have no idea why?

I have this code that basically reads from file and creates new file and write the content from the source to the destination file. It reads the buffer and creates the file, but fwrite
doesn't write the content to the newly created file, I have no idea why.
here is the code. (I have to use only this with _sopen, its part of legacy code)
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <string>
#include <share.h>
#include <sys\stat.h>
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
FILE* pfFile;
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
pfFile = fdopen(iFileId, "r");
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
// buffer = (char*) malloc (sizeof(char)*lSize);
buffer = (char*) malloc (sizeof(char)*lSize);
if (buffer == NULL)
{
return false;
}
// copy the file into the buffer:
result = fread (buffer,lSize,1,pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile );
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
return 0;
}
You can make main file and try it see if its working for you .
Thanks
Change your code to the following and then report your results:
int main () {
std::string szSource = "H:\\cpp\\test1.txt";
int iFileId = _sopen(szSource.c_str(),_O_RDONLY, _SH_DENYNO, _S_IREAD);
if (iFileId >= 0)
{
FILE* pfFile;
if ((pfFile = fdopen(iFileId, "r")) != (FILE *)NULL)
{
//read file content to buffer
char * buffer;
size_t result;
long lSize;
// obtain file size:
fseek (pfFile , 0 , SEEK_END);
lSize = ftell (pfFile);
fseek(pfFile, 0, SEEK_SET);
if ((buffer = (char*) malloc (lSize)) == NULL)
return false;
// copy the file into the buffer:
result = fread (buffer,(size_t)lSize,1,pfFile);
fclose(pfFile);
std::string szdes = "H:\\cpp\\test_des.txt";
FILE* pDesfFile;
int iFileId2 = _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
{
if ((pDesfFile = fdopen(iFileId2, "w+")) != (FILE *)NULL)
{
size_t f = fwrite (buffer, (size_t)lSize, 1, pDesfFile);
printf ("elements written <%d>\n", f);
if (f == 0)
printf("Error code: %d\n",ferror(pDesfFile));
fclose (pDesfFile);
}
}
}
}
return 0;
}
[edit]
for other posters, to show the usage/results of fwrite - what is the output of the following?
#include <stdio.h>
int main (int argc, char **argv) {
FILE *fp = fopen ("f.kdt", "w+");
printf ("wrote %d\n", fwrite ("asdf", 4, 1, fp));
fclose (fp);
}
[/edit]
sizeof(buffer) is the size of the pointer, i.e. 4 and not the number of items in the buffer
If buffer is an array then sizeof(buffer) would potentially work as it returns the number of bytes in the array.
The third parameter to fwrite is sizeof(buffer) which is 4 bytes (a pointer). You need to pass in the number of bytes to write instead (lSize).
Update: It also looks like you're missing the flag indicating the file should be Read/Write: _O_RDWR
This is working for me...
std::string szdes = "C:\\temp\\test_des.txt";
FILE* pDesfFile;
int iFileId2;
err = _sopen_s(&iFileId2, szdes.c_str(), _O_CREAT|_O_BINARY|_O_RDWR, _SH_DENYNO, _S_IREAD | _S_IWRITE);
if (iFileId2 >= 0)
pDesfFile = _fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, lSize, pDesfFile );
fclose (pDesfFile);
Since I can't find info about _sopen, I can only look at man open. It reports:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
Your call _sopen(szdes.c_str(),_O_CREAT,_SH_DENYNO,_S_IREAD | _S_IWRITE); doesn't match either one of those, you seem to have flags and 'something' and modes / what is SH_DENY?
What is the result of man _sopen?
Finally, shouldn't you close the file descriptor from _sopen after you fclose the file pointer?
Your final lines should look like this, btw :
if (iFileId2 >= 0)
{
pDesfFile = fdopen(iFileId2, "w+");
size_t f = fwrite (buffer , 1, sizeof(buffer),pDesfFile ); //<-- the f returns me 4
fclose (pDesfFile);
}
Since you currently write the file regardless of whether or not the fdopen after the O_CREAT succeeded. You also do the same thing at the top, you process the read (and the write) regardless of the success of the fdopen of the RDONLY file :(
You are using a mixture of C and C++. That is confusing.
The sizeof operator does not do what you expect it to do.
Looks like #PJL and #jschroedl found the real problem, but also in general:
Documentation for fwrite states:
fwrite returns the number of full items actually written, which may be less than count if an error occurs. Also, if an error occurs, the file-position indicator cannot be determined.
So if the return value is less than the count passed, use ferror to find out what happened.
The ferror routine (implemented both as a function and as a macro) tests for a reading or writing error on the file associated with stream. If an error has occurred, the error indicator for the stream remains set until the stream is closed or rewound, or until clearerr is called against it.