How do I check if a file is empty in C??

W

wetherbean

Hi group..I am writing a playlist management protocol where I have a
file that holds all the playlists and a file that holds all the
songs....before a playlist is created I need to check to see if the
playlist file is empty so that I can assign an integer value to a
playlist id field if it is the first playlist being written to the
file....can anyone help?? Thanks in advance

wetherbean
 
W

wetherbean

Nevermind, someone just gave me an idea that I think will work
fine...he said to fseek tot he end of the file and then do an ftell and
if it is 0 then the file is empty
 
C

Chris Torek

Hi group..I am writing a playlist management protocol where I have a
file that holds all the playlists and a file that holds all the
songs....before a playlist is created I need to check to see if the
playlist file is empty so that I can assign an integer value to a
playlist id field if it is the first playlist being written to the
file....can anyone help?? Thanks in advance

Definition: a file is "empty" if you cannot read anything from it.
(Is there a potential flaw in this definition? [I say yes, but
this is an exercise; you are supposed to identify potential flaws,
not just answer "yes" or "no". :) ])

Conclusion: open the file and try to read from it. If you get
some data, it is not empty. If you get EOF immediately, it is
empty.
 
D

Daniel Cer

wetherbean said:
Nevermind, someone just gave me an idea that I think will work
fine...he said to fseek tot he end of the file and then do an ftell and
if it is 0 then the file is empty

Alternatively, if you want to avoid actually having to open each file,
until you're confident that it's non-empty, then you could use stat().
As an example, check out the code below.

One caveat, if you use stat(), you'll find out the size of the file at
the time of the stat() call. So, in principle, it's possible for the
file to get truncated or deleted before you actually open it up and do
anything with it.

-Dan

get_file_size.c
----------------------------------------------------------
#include <stdio.h>
#include <sys/stat.h>

int main(int argc, char *argv[]) {
int i;

if (argc == 1) {
fprintf(stderr, "Usage:\n\t%s (file1) (file2) .....\n", argv[0]);
return -1;
}

for (i = 1; i < argc; i++) {
struct stat stat_record;
printf("%s - ", argv);
if (stat(argv, &stat_record))
printf("Can't stat (does file exist?)\n");
else if (!stat_record.st_size) printf("Empty file\n");
else {
/* Now you can open up the file an do what ever it is your going
to do - since it is non-empty
(or more technically correct probably still non-empty) */
printf(" Non-empty file (%d bytes)\n", stat_record.st_size);
}
}
return 0;
}
----------------------------------------------------------
 
S

SM Ryan

# Nevermind, someone just gave me an idea that I think will work
# fine...he said to fseek tot he end of the file and then do an ftell and
# if it is 0 then the file is empty

The return value of ftell is not guarenteed to be meaningful except to fseek.
It might be a file length, or something else altogether.

In ANSI C, open the file and see if you can read anything before getting an EOF.
Your system might provide other calls that don't require openning the file.
 
R

Robert Gamble

Alternatively, if you want to avoid actually having to open each file,
until you're confident that it's non-empty, then you could use stat().

There is no function called stat in Standard C which is what is discussed
here.

Rob Gamble
 
K

Keith Thompson

SM Ryan said:
The return value of ftell is not guarenteed to be meaningful except
to fseek. It might be a file length, or something else altogether.

[Quote character '#' changed to '>' as usual.]

Actually, the result of ftell() is meaningful if the file is opened
in binary mode.

C99 7.19.9.4p2:

The ftell function obtains the current value of the file position
indicator for the stream pointed to by stream. For a binary
stream, the value is the number of characters from the beginning
of the file. For a text stream, its file position indicator
contains unspecified information,
[snip]
 
J

Jack Klein

SM Ryan said:
The return value of ftell is not guarenteed to be meaningful except
to fseek. It might be a file length, or something else altogether.

[Quote character '#' changed to '>' as usual.]

Actually, the result of ftell() is meaningful if the file is opened
in binary mode.

C99 7.19.9.4p2:

The ftell function obtains the current value of the file position
indicator for the stream pointed to by stream. For a binary
stream, the value is the number of characters from the beginning
of the file. For a text stream, its file position indicator
contains unspecified information,
[snip]

The ftell() function is indeed meaningful for binary files, but using
fseek() first to get to the end, so ftell() can return the file size,
it not.

7.19.9.2 P3:

A binary stream need not meaningfully support fseek calls with a
whence value of SEEK_END.
 
D

Daniel Cer

Robert said:
There is no function called stat in Standard C which is what is discussed
here.

Rob Gamble

Even though stat() is not part of the current C standard, it is
available to C developers, in some form or another, on most of the
systems they might target. For example, the code should work as is on
systems like Linux, Mac OS X, Solaris, and perhaps even OpenVMS.

Even on Microsoft Windows, I think the only change would be to use
_stat() rather than stat(), with this function still being included from
the same header file, sys/stat.h. Moreover, the structure populated by
_stat() still contains a field 'st_size' that indicates the size of the
file in question and returns 0 on success or a non-zero value on failure.

Anyhow, using stat(), or a stat like function, should be a more
efficient than having to open each file and then attempting to read from
it to see if it contains any data. And, it seems a bit more elegant.
But, yeah, I probably should have said something about it being part of
the POSIX standard and/or system dependent rather than being Standard C.

-Dan
 
C

Chris Torek

Even though stat() is not part of the current C standard, it is
available to C developers, in some form or another, on most of the
systems they might target.

Perhaps. It is certainly available in all POSIX-conformant systems.
Still, "available in most systems" is obviously not quite as good
as "available in all systems on which files are available".
Anyhow, using stat(), or a stat like function, should be a more
efficient than having to open each file and then attempting to read from
it to see if it contains any data.

Have you tested this? In particular, have you compared the
performance of the sequence:

stat the file to find out if it is empty.
then, open the file and if it was empty earlier, write an ID, but if it
was not empty, read the ID;
then, write any data;
finally, close the file.

vs:

open the file;
try to read the ID; if none available, write an ID;
then, write any data;
finally, close the file.

? Try it (with a large number of files) and see if you get the
results that *I* expect, namely, that the latter should be slightly
faster. (How much faster depends on the system. The reason is
that, on modern systems, "look up file by name" happens to be the
slowest file-related operation the system ever does. The "stat
then open" sequence looks up the file name twice. The "open then
manipulate" sequence looks up the file name just once. You can
achieve the same performance as the "test read" method by using
fstat() once the file is open, of course, if you are on a POSIX
system.)

Of course, the "best" way to open the file is often to use the
non-C-Standard function that says "open this file for reading and
writing, creating it if necessary, but not discarding existing
data". Standard C has only three ways to open for both reading
and writing:

method1 = fopen(filename1, "r+"); /* or r+b */
method2 = fopen(filename2, "w+"); /* or w+b */
method3 = fopen(filename2, "a+"); /* or a+b */

The file opened via method 1 must already exist -- if not, the
fopen() must fail and method1 will be NULL. Method 2 will create
the file, but an existing file opened via method 2 has any existing
data removed first, which is clearly not what is wanted in this
case. Method 3 will also create the file if it does not yet exist,
but has the drawback that *every* write to the file will append,
whether or not you positioned the file elsewhere with fseek().
If this is what you wanted, great, but if not -- well, there
really ought to be a variation on "r+" meaning "create file if
needed". Perhaps "r+c", or perhaps "R+" or "c+", for instance.

(If you have a POSIX system, you can use:

fd = open(filename, O_RDWR | O_CREAT, mode); /* but not O_TRUNC */

to get the actual file created if needed, followed by an fdopen()
call with either "r+" or "w+" to get the C-style "FILE *" stream.
Why an appropriate mode name was not put into C99 is something of
a mystery to me, though.)
 
S

Stan Milam

Chris said:
wetherbean said:
Hi group..I am writing a playlist management protocol where I have a
file that holds all the playlists and a file that holds all the
songs....before a playlist is created I need to check to see if the
playlist file is empty so that I can assign an integer value to a
playlist id field if it is the first playlist being written to the
file....can anyone help?? Thanks in advance


Definition: a file is "empty" if you cannot read anything from it.
(Is there a potential flaw in this definition? [I say yes, but
this is an exercise; you are supposed to identify potential flaws,
not just answer "yes" or "no". :) ])

Conclusion: open the file and try to read from it. If you get
some data, it is not empty. If you get EOF immediately, it is
empty.

Leave it to Chris to cut through to the chase and give the KISS answer.

Anyway, this is how I used to do it many moons ago, but now that we have
long longs and files > 2 gigs are common place I will have to rewrite my
code.

/**********************************************************************/
/* File Id. filelen.c. */
/* Author: Stan Milam. */
/* Date Written: 5 May 92. */
/* Description: */
/* Implement a function to determine the size of a file in bytes. */
/* Useful for determining if a file is empty too. */
/* */
/* (c) Copyright 2005 by Stan Milam. */
/* All rights reserved. */
/* */
/**********************************************************************/

#include <stdio.h>
#include <sys/types.h>
#ifdef _UNIX
# include <unistd.h>
#else
# if defined (__TURBOC__) || defined (__POWERC)
# include <io.h>
# endif
#endif

/* $Revision$ */
extern char tb_copyright[];

/**********************************************************************/
/* Name: */
/* filelength(). */
/* */
/* Synopsis: */
/* #include "toolbox.h" */
/* long filelength( in fd ); */
/* */
/* Description: */
/* This function will return the length of a file in bytes. */
/* */
/* Arguments: */
/* int fd - A file descriptor. */
/* */
/* Returns Value: */
/* A value of type long representing the size of the file. -1L is */
/* returned when an error occurs. */
/* */
/**********************************************************************/

long
filelength (int fd)
{
long rv, here;

if (( here = lseek(fd, 0L, SEEK_CUR)) == -1L )
rv = -1L;
else {
rv = lseek(fd, 0L, SEEK_END);
lseek(fd, here, SEEK_SET);
}
return rv;
}
 
D

Daniel Cer

Anyhow, using stat(), or a stat like function, should be a more
Have you tested this? In particular, have you compared the
performance of the sequence:

stat the file to find out if it is empty.
then, open the file and if it was empty earlier, write an ID, but if it
was not empty, read the ID;
then, write any data;
finally, close the file.

vs:

open the file;
try to read the ID; if none available, write an ID;
then, write any data;
finally, close the file.

Hrm....I reread the original post by wetherbean. It looks like, for what
s/he is trying to do, you're right using the fopen approach is the
better way to go.

The post I replied to just mentions "How do I check if a file is empty
in C?" and a solution involving opening the file, fseeking to the end of
the file and then looking at the value of ftell to see if it's empty or
not.

Going off of just that, I thought, gee it seems like checking if a file
is empty or not by using fopen(), fseek(), ftell(), and then presumably
fclose() is much more complicated than just a single call to stat().
Also, the fopen(), fseek()..... sequence might involve the C library
reading part of the file into a buffer in preparation for calls that
normally come after commands like fopen, e.g. fgets, fgetc.

In contrast, the stat() approach only requires one command, and will
probably only involve the system retrieving the meta data associated
with the file(s). This meta data would also presumably be read in by the
underlying OS whenever fopen is called as well. Also, stat(), or
something very similar to it, for example, _stat() on Windows, is
ubiquitous enough that there's a >95% chance** that it's available on
whatever system the original poster is using.

So, if someone is just interested in whether a file is empty or not, for
example, if they just want to build a list of either empty or non-empty
files, using stat()/_stat() seems like a fairly reasonable approach. Or,
at least, something a programmer should be aware of when deciding what
approach to take.

Anyhow, like I said above, given what wetherbean is trying to do (i.e.
the file is going to be written to after the empty/non-empty check),
then, yeah, using the approach you suggested, something like fopen() +
fgetc() with a test for an immediate EOF, seems like the way to go.

-Dan

** Okay, this value was carefully obtained by the rule that "70% of
statistics are made up on the spot". But, it's still not entirely baseless.
 
C

Chris Torek

The post I replied to just mentions "How do I check if a file is empty
in C?" and a solution involving opening the file, fseeking to the end of
the file and then looking at the value of ftell to see if it's empty or
not.

(Which is not a 100% reliable method, due to the restrictions on
seek positions -- ANSI/ISO C says nothing at all about text files,
and says that binary files may contain arbitrary padding. Of course
it works on most real systems, especially for simple empty/nonempty
tests.)
In contrast, the stat() approach only requires one [call], and will
probably only involve the system retrieving the meta data associated
with the file(s).

Yes; although as it happens, opening a file is usually just about
the same amount of work. (The "extra" work in opening the file,
if any, lies in allocating data structures to track the open file.
But, just to take an example of a system I work on now: in vxWorks,
stat() is implemented internally as open() followed by fstat()
followed by close() -- so there is no savings at all! Indeed,
virtually all operations in vxWorks require opening the file first,
which may be a problem for POSIX semantics. A POSIX system allows
renaming or removing a file that you have no permission to open,
for instance.)
This meta data would also presumably be read in by the
underlying OS whenever fopen is called as well. Also, stat(), or
something very similar to it, for example, _stat() on Windows, is
ubiquitous enough that there's a >95% chance** that it's available on
whatever system the original poster is using.

It is pretty darn common -- but note that issues like "sometimes
it is named _stat" are already an annoyance.
So, if someone is just interested in whether a file is empty or not, for
example, if they just want to build a list of either empty or non-empty
files, using stat()/_stat() seems like a fairly reasonable approach.

To build a list of files, you usually have to do something else
that cannot be done in ANSI/ISO C: read directories. There is no
harm going beyond the Standard in this case. If you have to do
something that is impossible in Standard C, you might as well use
non-Standard C. :)

The trickier tradeoffs come in when you *can* do it -- whatever
"it" is -- in Standard C, but you can do it "better" with some
non-standard calls. Now you face the same problem as the fellow
who wants to buy a car, and can get a clapped-out Yugo for a hundred
bucks, or a nice shiny slightly-used Lexus or BMW for a mere $25
grand: "good, fast, cheap -- pick any two." :)
 
W

wetherbean

Hello...thanks for all your input guys....this was the biggest response
I have had yet. I have found for my purpose the fseek.ftell method
seems to be the best...although I did encounter a small
problem....after I check if the file is empty I have to call rewind()
so fread in a loop from the beginning of the file to get the playlist
id of the last file entry before I can write the new playlist entry to
the file.....this part of the code is successful but within my
while(!feof) the code is doing an extra run as if the EOF has gotten
pushed up a line....can anyone explain this?? Here is the portion of
my code where I was trying to test if the fwrites were actually
producing the correct info....if anyone needs more explanation let me
know...Thanks in advance

weatherbean


fseek(list_file,0,SEEK_END);

if(ftell(list_file)==0){
//printf("ftell=0\n");
playlist.list_id=1;

fwrite(&playlist,sizeof(playlist),1,list_file);
}

else if(ftell(list_file)!=0){
rewind(list_file);
while(!feof(list_file)){

fread(&playlist,sizeof(playlist),1,list_file);



printf("%s\n",playlist.list_name);
printf("%d\n",playlist.list_id);

prev_id=playlist.list_id;

}//end while

playlist.list_id=prev_id+1;

strcpy(playlist.list_name,listname);

fwrite(&playlist,sizeof(playlist),1,list_file);
 
K

Keith Thompson

wetherbean said:
Hello...thanks for all your input guys....this was the biggest response
I have had yet. I have found for my purpose the fseek.ftell method
seems to be the best...although I did encounter a small
problem....after I check if the file is empty I have to call rewind()
so fread in a loop from the beginning of the file to get the playlist
id of the last file entry before I can write the new playlist entry to
the file.....this part of the code is successful but within my
while(!feof) the code is doing an extra run as if the EOF has gotten
pushed up a line....can anyone explain this?? Here is the portion of
my code where I was trying to test if the fwrites were actually
producing the correct info....if anyone needs more explanation let me
know...Thanks in advance

The feof() fucntion tells you that the last read operation hit the end
of the file, not that the next one is going to. (It also doesn't tell
you when an error occurs, so your loop could be an infinite one.)

fread() returns the number of bytes it actually read; use that to
determine when you've reached the end of the file. (You can then use
the feof() function to distinguish between reaching the end of the
file and encountering an error.)
 
W

wetherbean

Thanks...that worked great....I also encountered a problem putting with
putting my switch into a loop.....I want all of the user errors to
return to the second menu I have but when I try to put the second
switch in my program in a loop it segfaults...I think it might be
easier to show you what I mean if I just post the entire code here...I
know some consider it bad practice to put switch statements in loops
but at this point I am just trying to make it work....lol..any
suggestions?? Thanks in advance

Wetherbean


#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct song_rec{
char artist[30];
char album[35];
int track;
int song_id;};

struct playlist_rec{
char list_name[20];
int list_id;};

struct user_rec{
char name[15];
int pw;};


int main(int argc,char**argv) {

FILE* user_file;
FILE* list_file;
FILE* song_file;
struct user_rec user;
struct playlist_rec playlist;
struct song_rec song;
int choice=0,found=0,password=0,registered=0,offset=0;
int first=0,choice2=0,prev_id=0,count=0,list_id;
char uname[15];
char listname[20];
char song_file_name[25];
char list_file_name[25];



printf("1)REGISTER\n");
printf("2)LOGIN\n");
printf("->");
scanf("%d",&choice);



switch(choice){

case 1:
while(registered!=1){
found=0;
printf("Enter desired login name: ");
scanf("%s",uname);
printf("%s\n",uname);

user_file=fopen("user_file.data","a+");

while(!feof(user_file)&&found!=1){
fread(&user,sizeof(user),1,user_file);

if (strcmp(uname,user.name)==0){
found=1;
printf("Login name already in use\n");
fclose(user_file);
}
}//end while

if (found==0){
registered=1;
printf("Enter desired password: ");
scanf("%d",&password);
strcpy(user.name,uname);
user.pw=password;
fwrite(&user,sizeof(user),1,user_file);
printf("Registration Successful\n");
printf("Username: %s\n Password:
%d\n",user.name,user.pw);
fclose(user_file);}

}
break;

case 2:

user_file=fopen("user_file.data","rb");

printf("Enter username: ");
scanf("%s",uname);
printf("Enter password: ");
scanf("%d",&password);
while(!feof(user_file)&&strcmp(user.name,uname)!=0){
fread(&user,sizeof(user),1,user_file);


if (strcmp(user.name,uname)==0 && password==user.pw){
printf("Logged In....\n\n");
sprintf(list_file_name,"%s.plst",user.name);
sleep(1);}

else{
printf("User name and password do not
match\n");
exit(1);}
}



case 3:

/******ANSI CODE FOR CLEAR SCREEN*******/



printf(" \033[2J");

//------------------------------------ >
//I want the code after this to loop
// until choice2==7 but it segfaults when I add in the while loop

// while(1){

printf("Hello %s, Enter the number of your
choice\n");
printf("1)Create Playlist\n");
printf("2)Add song to a playlist\n");
printf("3)Delete Song From a playlist\n");
printf("4)Randomize playlist\n");
printf("5)Delete Playlist\n");
printf("6)Display Playlist File\n");
printf("7)Exit\n");
printf("->");
scanf("%d",&choice2);

switch(choice2){

/**************CREATE
PLAYLIST****************************/

case 1:
printf("Enter name of new playlist: ");
scanf("%s",listname);


//
sprintf(list_file_name,"%s.plst",user.name);
list_file=fopen(list_file_name,"a+");
/**************stopped working
here**************/
fseek(list_file,0,SEEK_END);

if(ftell(list_file)==0){
//printf("ftell=0\n");
playlist.list_id=1;
strcpy(playlist.list_name,listname);

fwrite(&playlist,sizeof(playlist),1,list_file);
}

else if(ftell(list_file)!=0){
rewind(list_file);

while(fread(&playlist,sizeof(playlist),1,list_file)!=0){

if
(strcmp(playlist.list_name,listname)==0){
printf("Playlist Name
already in use\n");
exit(0);}


printf("%s\n",playlist.list_name);
printf("%d\n",playlist.list_id);

prev_id=playlist.list_id;

}//end while

playlist.list_id=prev_id+1;

strcpy(playlist.list_name,listname);

fwrite(&playlist,sizeof(playlist),1,list_file);
}//else if

//printf("%d\n",playlist.list_id);
fclose(list_file);

break;


/**********************ADD SONG TO
PLAYLIST*************************/
case 2:
printf("Enter name of playlist to add to: ");
scanf("%s",listname);
list_file=fopen(list_file_name,"a+");
printf("Enter Song Artist: ");
scanf("%s",song.artist);
printf("Enter Album Title: ");
scanf("%s",song.album);
printf("Enter Track Number: ");
scanf("%d",&song.track);

while(!feof(list_file)){

fread(&playlist,sizeof(playlist),1,list_file);

if(strcmp(playlist.list_name,listname)==0){
song.song_id=playlist.list_id;
}
}
fclose(list_file);
sprintf(song_file_name,"%s.sng",uname);
song_file=fopen(song_file_name,"a");
fwrite(&song,sizeof(song),1,song_file);

fclose(song_file);

break;


/****************************DISPLAY CURRENT
PLAYLISTS*************************************/


case 6:
list_file=fopen(list_file_name,"a+");

while(fread(&playlist,sizeof(playlist),1,list_file)){

printf("%s\n",playlist.list_name);

}

case 7:
exit(0);


} //end switch 2
// } end while(1)

} //end switch 1

}
 
W

wetherbean

Thanks...that worked great....I also encountered a problem putting with
putting my switch into a loop.....I want all of the user errors to
return to the second menu I have but when I try to put the second
switch in my program in a loop it segfaults...I think it might be
easier to show you what I mean if I just post the entire code here...I
know some consider it bad practice to put switch statements in loops
but at this point I am just trying to make it work....lol..any
suggestions?? Thanks in advance

Wetherbean


#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct song_rec{
char artist[30];
char album[35];
int track;
int song_id;};

struct playlist_rec{
char list_name[20];
int list_id;};

struct user_rec{
char name[15];
int pw;};


int main(int argc,char**argv) {

FILE* user_file;
FILE* list_file;
FILE* song_file;
struct user_rec user;
struct playlist_rec playlist;
struct song_rec song;
int choice=0,found=0,password=0,registered=0,offset=0;
int first=0,choice2=0,prev_id=0,count=0,list_id;
char uname[15];
char listname[20];
char song_file_name[25];
char list_file_name[25];



printf("1)REGISTER\n");
printf("2)LOGIN\n");
printf("->");
scanf("%d",&choice);



switch(choice){

case 1:
while(registered!=1){
found=0;
printf("Enter desired login name: ");
scanf("%s",uname);
printf("%s\n",uname);

user_file=fopen("user_file.data","a+");

while(!feof(user_file)&&found!=1){
fread(&user,sizeof(user),1,user_file);

if (strcmp(uname,user.name)==0){
found=1;
printf("Login name already in use\n");
fclose(user_file);
}
}//end while

if (found==0){
registered=1;
printf("Enter desired password: ");
scanf("%d",&password);
strcpy(user.name,uname);
user.pw=password;
fwrite(&user,sizeof(user),1,user_file);
printf("Registration Successful\n");
printf("Username: %s\n Password:
%d\n",user.name,user.pw);
fclose(user_file);}

}
break;

case 2:

user_file=fopen("user_file.data","rb");

printf("Enter username: ");
scanf("%s",uname);
printf("Enter password: ");
scanf("%d",&password);
while(!feof(user_file)&&strcmp(user.name,uname)!=0){
fread(&user,sizeof(user),1,user_file);


if (strcmp(user.name,uname)==0 && password==user.pw){
printf("Logged In....\n\n");
sprintf(list_file_name,"%s.plst",user.name);
sleep(1);}

else{
printf("User name and password do not
match\n");
exit(1);}
}



case 3:

/******ANSI CODE FOR CLEAR SCREEN*******/



printf(" \033[2J");

//------------------------------------ >
//I want the code after this to loop
// until choice2==7 but it segfaults when I add in the while loop

// while(1){

printf("Hello %s, Enter the number of your
choice\n");
printf("1)Create Playlist\n");
printf("2)Add song to a playlist\n");
printf("3)Delete Song From a playlist\n");
printf("4)Randomize playlist\n");
printf("5)Delete Playlist\n");
printf("6)Display Playlist File\n");
printf("7)Exit\n");
printf("->");
scanf("%d",&choice2);

switch(choice2){

/**************CREATE
PLAYLIST****************************/

case 1:
printf("Enter name of new playlist: ");
scanf("%s",listname);


//
sprintf(list_file_name,"%s.plst",user.name);
list_file=fopen(list_file_name,"a+");
/**************stopped working
here**************/
fseek(list_file,0,SEEK_END);

if(ftell(list_file)==0){
//printf("ftell=0\n");
playlist.list_id=1;
strcpy(playlist.list_name,listname);

fwrite(&playlist,sizeof(playlist),1,list_file);
}

else if(ftell(list_file)!=0){
rewind(list_file);

while(fread(&playlist,sizeof(playlist),1,list_file)!=0){

if
(strcmp(playlist.list_name,listname)==0){
printf("Playlist Name
already in use\n");
exit(0);}


printf("%s\n",playlist.list_name);
printf("%d\n",playlist.list_id);

prev_id=playlist.list_id;

}//end while

playlist.list_id=prev_id+1;

strcpy(playlist.list_name,listname);

fwrite(&playlist,sizeof(playlist),1,list_file);
}//else if

//printf("%d\n",playlist.list_id);
fclose(list_file);

break;


/**********************ADD SONG TO
PLAYLIST*************************/
case 2:
printf("Enter name of playlist to add to: ");
scanf("%s",listname);
list_file=fopen(list_file_name,"a+");
printf("Enter Song Artist: ");
scanf("%s",song.artist);
printf("Enter Album Title: ");
scanf("%s",song.album);
printf("Enter Track Number: ");
scanf("%d",&song.track);

while(!feof(list_file)){

fread(&playlist,sizeof(playlist),1,list_file);

if(strcmp(playlist.list_name,listname)==0){
song.song_id=playlist.list_id;
}
}
fclose(list_file);
sprintf(song_file_name,"%s.sng",uname);
song_file=fopen(song_file_name,"a");
fwrite(&song,sizeof(song),1,song_file);

fclose(song_file);

break;


/****************************DISPLAY CURRENT
PLAYLISTS*************************************/


case 6:
list_file=fopen(list_file_name,"a+");

while(fread(&playlist,sizeof(playlist),1,list_file)){

printf("%s\n",playlist.list_name);

}

case 7:
exit(0);


} //end switch 2
// } end while(1)

} //end switch 1

}
 
R

Richard Bos

Jack Klein said:
Actually, the result of ftell() is meaningful if the file is opened
in binary mode.

C99 7.19.9.4p2:

The ftell function obtains the current value of the file position
indicator for the stream pointed to by stream. For a binary
stream, the value is the number of characters from the beginning
of the file. For a text stream, its file position indicator
contains unspecified information,
[snip]

The ftell() function is indeed meaningful for binary files, but using
fseek() first to get to the end, so ftell() can return the file size,
it not.

True, but the OP wanted to know whether the file is empty, not how large
it is if it's not. So ISTM that opening the file in text mode, fseek()
to the start of the file, save the indicator returned by ftell(),
fseek() to the end, compare the saved value to what ftell() returns now,
will work. If the two indicators are equal, the file is empty; if
they're not, you don't know _what_ the file size is, but you do know
that it's not zero.

Richard
 
L

Lawrence Kirby

Jack Klein said:
Actually, the result of ftell() is meaningful if the file is opened
in binary mode.

C99 7.19.9.4p2:

The ftell function obtains the current value of the file position
indicator for the stream pointed to by stream. For a binary
stream, the value is the number of characters from the beginning
of the file. For a text stream, its file position indicator
contains unspecified information,
[snip]

The ftell() function is indeed meaningful for binary files, but using
fseek() first to get to the end, so ftell() can return the file size,
it not.

True, but the OP wanted to know whether the file is empty, not how large
it is if it's not. So ISTM that opening the file in text mode, fseek()
to the start of the file, save the indicator returned by ftell(),
fseek() to the end, compare the saved value to what ftell() returns now,
will work. If the two indicators are equal, the file is empty; if
they're not, you don't know _what_ the file size is, but you do know
that it's not zero.


AFAICT the Deathstation could return a random but distinct value from each
call to ftell() in a text stream and maintaain an internal lookup table
to find the true offset in fseek(). So the fact that two return values are
different doesn't mean they represent different offsets.

Lawrence
 
J

Joe Wright

Chris Torek wrote:
[ snip ]
Conclusion: open the file and try to read from it. If you get
some data, it is not empty. If you get EOF immediately, it is
empty.

Caveat: On non-Unix systems, open the file in "rb" binary mode. It is
possible for a non-empty file to have 0x1a its first byte. In text mode
reading this byte can give you EOF immediately (not what you wanted to see).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top