{"id":5699,"date":"2023-01-08T00:01:05","date_gmt":"2023-01-08T08:01:05","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=5699"},"modified":"2023-01-07T11:11:29","modified_gmt":"2023-01-07T19:11:29","slug":"how-big-is-that-file-solution","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=5699","title":{"rendered":"How Big is That File? &#8211; Solution"},"content":{"rendered":"<p>The challenge for <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5690\">this month&#8217;s Exercise<\/a> is to return a file&#8217;s size without using the <em>stat()<\/em> function. My goal is to get you to think about various file tools and how they can be useful beyond their intended purpose.<br \/>\n<!--more--><br \/>\nThe hint for this solution is random file access. This approach manipulates a &#8220;file pointer,&#8221; which has nothing to do with C language pointers. No, a file pointer is an index into the file, an offset. I prefer to use the term <em>file position indicator<\/em>, which is how I describe it in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3357\">an older post<\/a>. The functions required are <em>fseek()<\/em> and <em>ftell()<\/em>.<\/p>\n<p>The <em>fseek()<\/em> function moves the file position indicator. Here is the <em>man<\/em> page format:<\/p>\n<p><code>int fseek(FILE *stream, long offset, int whence);<\/code><\/p>\n<p>Given the open file handle <code>*stream<\/code>, you can reset the file position indicator&#8217;s location to the end of the file. Use the <code>whence<\/code> value <code>SEEK_END<\/code> and set the <code>offset<\/code> to zero. Upon success, the file position indicator references the file&#8217;s final byte. You then use the <em>ftell()<\/em> function to report this offset:<\/p>\n<p><code>long ftell(FILE *stream);<\/code><\/p>\n<p>The <code>stream<\/code> argument is the open file handle. The value returned is a <em>long<\/em> integer representing the file position indicator&#8217;s location &mdash; its offset from the start of the file. Presto! You have the file&#8217;s size, as shown in my solution:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2023_01-Exercise.c\" rel=\"noopener\" target=\"_blank\">2023_01-Exercise.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n\r\nint main(int argc, char *argv[])\r\n{\r\n    char *filename;\r\n    FILE *fh;\r\n    long size;\r\n    \r\n    <span class=\"comments\">\/* check for filename argument *\/<\/span>\r\n    if( argc&lt;2 )\r\n    {\r\n        puts(\"Specify a filename\");\r\n        return(1);\r\n    }\r\n\r\n    <span class=\"comments\">\/* operate from the first argument *\/<\/span>\r\n    filename = argv[1];\r\n\r\n    fh = fopen(filename,\"r\");\r\n    if( fh==NULL )\r\n    {\r\n        fprintf(stderr,\"Unable to open %s\\n\",filename);\r\n        return(1);\r\n    }\r\n\r\n    fseek( fh, 0, SEEK_END );\r\n    size = ftell(fh);\r\n    fclose(fh);\r\n\r\n    printf(\"%s is %ld bytes long\\n\",filename,size);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The code starts the same as the Exercise post that used the <em>stat()<\/em> function: An argument is tested for and, when found, the named file is opened for read access.<\/p>\n<p>At Line 26, the <em>fseek()<\/em> function moves the file position indicator to the last byte in the file. Then <em>ftell()<\/em> reports that value, saved in <em>long<\/em> variable <code>size<\/code>. The file is closed, then the size is output.<\/p>\n<p>Of course, all this file position indicator manipulation isn&#8217;t necessary if you just use the <em>stat()<\/em> function. Still, I find that random file access is something many C programmers don&#8217;t use often. To think of reading data at a certain offset in a file isn&#8217;t something you normally do. Yet it&#8217;s something you can do and something you can use to obtain information about a file, such as its size.<\/p>\n<p>I hope your solution met with success. If you figured out a way to do it without manipulating the file position indicator, please let me know. Thanks!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The challenge for this month&#8217;s Exercise is to return a file&#8217;s size without using the stat() function. My goal is to get you to think about various file tools and how they can be useful beyond their intended purpose.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-5699","post","type-post","status-publish","format-standard","hentry","category-solution"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5699","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5699"}],"version-history":[{"count":4,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5699\/revisions"}],"predecessor-version":[{"id":5717,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5699\/revisions\/5717"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5699"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5699"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5699"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}