How does one shrink a file in C? For example, if I open a 2mb file, do some work 开发者_运维百科and decide only 1mb of the file should still exist, how is this accomplished? I know how to use write( fd,....) to write to a file, but what if I want to carve out certain parts in the middle of a file or truncate it?
You're likely looking for truncate()
ftruncate()
or on windows, SetEndOfFile()
. There's no way to "cut" out a piece of the file, you will need to rewrite it from front and then truncate it.
Almost every real system provides some way to truncate a file, but the C standard doesn't provide it in the standard library.
That means pretty much all you can do is define a function to do the job, and implement that function for each target you care about (e.g., on Windows it'll call SetEndOfFile
, on Unix-like systems it'll call ftruncate
, etc.).
Edit: just to clarify: that only works for the "or truncate it" part of the question. Most file systems don't provide anything to "carve out certain parts in the middle of a file". If you want to remove things from the middle of a file, you generally have to rewrite the whole file, or handle things on your own. The latter typically works out to some sort of database-like structure where don't actually delete data from the middle of the file; instead, you create something like an index that tells about the location of data you care about, and simply marks parts as no longer in use when you delete them. Those parts are then eligible for re-use when/if you add data later. In a few cases, you'll have a "compress" function that takes such a database and rewrites it to eliminate the dead space (but there, again, you're back to rewriting the file).
If the file is small enough to fit in RAM, you can read the file, and rewrite only the necessary things back(that is, read the file, close the file, open the file again in write mode, write what's necessary, close). If not, you can create a second file, write in it, then delete the first file and rename the second.
My point is, there is no direct way to just delete some part of the file in the middle.
You have two options:
- Create a temporary file, write the contents you want out to that, and rename it to the original file
- Read the entire file into memory, edit in memory and use freopen to reopen the file, truncating it
If you want to preserve the previous contents of the file up to some length (a length bigger than zero), then POSIX provides the truncate() and ftruncate() functions for the job.
#include <unistd.h>
int ftruncate(int fildes, off_t length);
int truncate(const char *path, off_t length);
The name indicates the primary purpose - shortening a file. But if the specified length is longer than the previous length, the file grows (zero padding) to the new size. Note that ftruncate() works on a file descriptor, not a FILE *;
you could use:
if (ftruncate(fileno(fp), new_length) != 0)
...error handling...
It is likely, though, that for your purposes, truncate on open is all you need.
If you have a POSIX system, take a look at ftruncate()
.
The others already answered how to truncate a file. Removing parts in the middle of a file is not possible, though. For this, you'd need to rewrite the whole file.
精彩评论