So I have opened a file with the "open" command and I get a file descriptor. That means I have to use lseek rather than fseek, which is fine by me. But what if I want to know how long the file is or what if I want to know where I am pointing. If I had a FILE*, I could use ftell. But I don't, so what do I use? ltell appears to not exist. Any ideas or alternatives? I need to bounce all over this file and write things, so I'd like to know where I am. Thanks.

Dani AI

Generated

— because you must keep using file descriptors, there are three practical, commonly used options: use lseek to query/ and set the offset, use fstat/fstat64 to read the file size without moving the file pointer, or use pread/pwrite to read/write at an absolute offset without changing the fd's current position. is right that switching to FILE* gives you ftell/fseek, but that refactor can be expensive. 's mmap idea is attractive when the OS supports it; on many embedded targets it does not. 's pointer to secure-coding concerns is also relevant: avoid assuming all streams are regular files.

Example patterns:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

/* current position */
off_t get_pos(int fd) {
    off_t p = lseek(fd, 0, SEEK_CUR);
    if (p == (off_t)-1) { /* check errno */ }
    return p;
}

/* file size without leaving cursor misplaced */
off_t size_using_seek(int fd) {
    off_t cur = lseek(fd, 0, SEEK_CUR);
    if (cur == (off_t)-1) return -1;
    off_t sz = lseek(fd, 0, SEEK_END);
    if (sz == (off_t)-1) return -1;
    if (lseek(fd, cur, SEEK_SET) == (off_t)-1) return -1;
    return sz;
}

/* preferred: fstat for regular files */
off_t size_using_fstat(int fd) {
    struct stat st;
    if (fstat(fd, &st) == -1) return -1;
    return st.st_size; /* meaningful for regular files */
}

Use pread/pwrite when you need thread-safe offset operations (they do not change the fd offset). Caveats: pipes, sockets, character devices, /proc entries and some network or virtual filesystems don't have meaningful sizes or are not seekable — lseek/fstat can fail or return meaningless values. Watch for large-file support (use 64-bit off_t or platform-specific alternatives), check return values and errno, and avoid race conditions if another thread/process can truncate/extend the file. For NAND/embedded: minimize seeks/writes, or keep an in-memory index of record keys+offsets so binary searches touch flash sparingly.

Recommended Answers

All 5 Replies

Why are you using low-level file i/o?? Just use FILE* and all will be ok. The only reason to use open() is when the compiler for the target operating system doesn't have FILE* and associated functions.

But to answer your question, lseek() returns the file offset.

Just curious, is there a reason why you need to bounce around in the file? Is it such a large file that it can't be loaded to RAM? Why not use file mapping to map it to a series of struct's or arrays of struct's so you dont ever need to bounce around the file?

Why are you using low-level file i/o?? Just use FILE* and all will be ok. The only reason to use open() is when the compiler for the target operating system doesn't have FILE* and associated functions.

But to answer your question, lseek() returns the file offset.

Although this question is answered, since OP is asking about calculating the file size[ how long the file is], i have a to share with you.

, have you experienced anything of that sort as explained in that link. I would like to know your opinion.. I dont have exp in MS technologies... In gcc when i tried, the ftell and fseek all were working as expected..

>> Why are you using low-level file i/o?? Just use FILE* and all will be ok. The only reason to use open() is when the compiler for the target operating system doesn't have FILE* and associated functions.


I inherited a lot of code from the last guy and need to change it. He used file descriptors, so I'm stuck with them or I have to go through all his code and change everything so it takes FILE* parameters. I figured using file descriptors would be easier.


>> But to answer your question, lseek() returns the file offset.

Thanks. Face-->Palm. Didn't really read the lseek description, but instead assumed it returned the same as fseek. We all know what happens when you assume.


>> Just curious, is there a reason why you need to bounce around in the file? Is it such a large file that it can't be loaded to RAM? Why not use file mapping to map it to a series of struct's or arrays of struct's so you dont ever need to bounce around the file?


The files are generally not too big ( afew kilobytes), but potentially could get much bigger. It's embedded program with some fairly limited resources, but enough to handle a buffer containing the whole file, so that is an option.

The files contain records and are searched a lot and inserted and deleted often too, but less frequently. Right now the records are unordered, so it's a pretty brute force method. I'm changing it to an ordered file so I can use a faster binary search and faster insertion. So I want to check how long the file is, get the number of records, bounce to the middle, do the comparison, bounce somewhere else depending on the comparison, etc., till I find the correct spot. Seems easier than reading in the entire file, particularly when the files get bigger.


>> Although this question is answered, since OP is asking about calculating the file size[ how long the file is], i have a link to share with you.

Thanks for sharing the link. It's interesting. I had not heard of that problem before. I don't think it applies to me. I'm using Linux and always reading and writing in binary mode (I guess since I'm using Linux, binary mode is irrelevant).

I was interested in what Salem said here:

http://www.daniweb.com/forums/post778389.html#post778389

Multiple lseeks could be slower that a regular old brute force search. But then there's caching and all that other stuff, plus I'm using nandflash, so that might go out the window.

>>@AncientDragon, have you experienced anything of that sort as explained in that link

I have never experienced a problem in MS-Windows with using fseek() and ftell() to get the file size of a binary file. Even if the file had trailing null bytes I don't see how that would invalidate the return value of ftell() because those trailing null bytes are part of the file.

But I suppose there could be some obscure file systems where ftell() might not work. That doesn't mean it should be prohibited for everyone in the world to use it.

There are some embedded systems on which ftell() and other FILE* related functions won't work. I was writing C++ programs for PocketPC os and the Microsoft compiler (eVC++ 3.0) did not support FILE or any of its associated functions. Nor did it support any of the STL classes, such as fstream, iostream, string, etc.

I wrote a small program to find out how VC++ 2010 Express got the file size for _stat() function. It calls FindFirstFile() to get the file's info. I'm not sure how FindFirstFile() gets its information, but most likely by calling other win32 api functions instead of using ftell() or lseek()

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.