fstream delete N bytes from the end of a binary file - c++

Is it possible to delete N bytes from the end of a binary file in C++ using fstream (or something similar)? I don´t want to read the whole file, cut it and write it again, but since it´s from the end of a file it seems like it shouldn't be such a problem.

I'm not aware of a generic C++ (platform independent) way to do this without writing a new file. However, on POSIX systems (Linux, etc.) you can use the ftruncate() function. On Windows, you can use SetEndOfFile().
This also means you'll need to open the file using the native functions instead of fstream since you need the native descriptor/handle for those functions.
EDIT: If you are able to use the Boost library, it has a resize_file() function in its Filesystem library which would do what you want.

Update:
Now in C++17 you can use resize_file from filesystem
Live on Coliru

In case you want to use Qt, QFile also provides two resize() methods that allow to truncate a file.

Related

Can std::ifstream get a file's unique identification [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Getting a FILE* from a std::fstream
I am working on Linux and file descriptors are the main model in this OS.
I was wondering whether is there any library or any way to retrieve the native Linux file descriptor starting from a C++ std::fstream.
I thought about boost::iostream since there is a class called file_descriptor but I understood that its purpose is different from the one I want to achieve.
Do you know some way to do that?
You can go the other way: implement your own stream buffer that wraps a file descriptor and then use it with iostream instead of fstream. Using Boost.Iostreams can make the task easier.
Non-portable gcc solution is:
#include <ext/stdio_filebuf.h>
{
int fd = ...;
__gnu_cxx::stdio_filebuf<char> fd_file_buf{fd, std::ios_base::out | std::ios_base::binary};
std::ostream fd_stream{&fd_file_buf};
// Write into fd_stream.
// ...
// Flushes the stream and closes fd at scope exit.
}
There is no (standard) way to extract the file number from an std::fstream since the standard library does not mandate how file streams will be implemented.
Rather, you need to use the C file API if you want to do this (using FILE*).
There is no official way to get the private file handle of a file stream (or actualy a std::basic_filebuf), just because it should be portable and discourage use of platform-specific functions.
However, you can do ugly hack like inheriting std::basic_filebuf and from that try to pry out the file handle. It's not something I recommend though as it will probably break on different versions of the C++ library.
There is no support of exposing file descriptor neither in standard C++ nor in libstdc++.

Redirect FILE handle to char-buffer

I'm using a third-party library that allows conversion between two file formats A and B. I would like to use this library to load a file of format A and convert it to format B, but I only need the converted representation in memory. So I would like to do the conversion without actually saving a file of the target format to disk and rather obtain an unsigned char* buffer or something similar. Unfortunately the libraries only conversion function is of the form
void saveAsB(A& a, std::FILE *const file);
What can I do? Is there any way to redirect the write operations performed on the handle to some buffer?
If your platform supports it, use open_memstream(3). This will be available on Linux and BSD systems, and it's probably better than fmemopen() for your use case because open_memstream() allocates the output buffer dynamically rather than you having to know the maximum size in advance.
If your platform doesn't have those functions, you can always use a "RAM disk" approach, which again on Linux would be writing a "file" to /dev/shm/ which will never actually reach any disk, but rather be stored in memory.
Edit: OK, so you say you're using Windows. Here's an outline of what you can try:
Open a non-persisted memory-mapped files.
Use _open_osfhandle to convert the HANDLE to an int file descriptor.
Use _fdopen to convert the int file descriptor to FILE*.
Cross your fingers. I haven't tested any of this.
I found this reference useful in putting the pieces together: http://www.codeproject.com/Articles/1044/A-Handy-Guide-To-Handling-Handles
Edit 2: It looks like CreateFileMapping() and _open_osfhandle() may be incompatible with each other--you would be at least the third person to try it:
https://groups.google.com/forum/#!topic/comp.os.ms-windows.programmer.win32/NTGL3h7L1LY
http://www.progtown.com/topic178214-createfilemapping-and-file.html
So, you can try what the last link suggested, which is to use setvbuf() to "trick" the data into flowing to a buffer you control, but even that has potential problems, e.g. it won't work if the library seeks within the FILE*.
So, perhaps you can just write to a file on some temporary/scratch filesystem and be done with it? Or use a platform other than Windows? Or use some "RAM disk" software.
If you can rely on POSIX being available, then use fmemopen().

Retrieving file descriptor from a std::fstream [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Getting a FILE* from a std::fstream
I am working on Linux and file descriptors are the main model in this OS.
I was wondering whether is there any library or any way to retrieve the native Linux file descriptor starting from a C++ std::fstream.
I thought about boost::iostream since there is a class called file_descriptor but I understood that its purpose is different from the one I want to achieve.
Do you know some way to do that?
You can go the other way: implement your own stream buffer that wraps a file descriptor and then use it with iostream instead of fstream. Using Boost.Iostreams can make the task easier.
Non-portable gcc solution is:
#include <ext/stdio_filebuf.h>
{
int fd = ...;
__gnu_cxx::stdio_filebuf<char> fd_file_buf{fd, std::ios_base::out | std::ios_base::binary};
std::ostream fd_stream{&fd_file_buf};
// Write into fd_stream.
// ...
// Flushes the stream and closes fd at scope exit.
}
There is no (standard) way to extract the file number from an std::fstream since the standard library does not mandate how file streams will be implemented.
Rather, you need to use the C file API if you want to do this (using FILE*).
There is no official way to get the private file handle of a file stream (or actualy a std::basic_filebuf), just because it should be portable and discourage use of platform-specific functions.
However, you can do ugly hack like inheriting std::basic_filebuf and from that try to pry out the file handle. It's not something I recommend though as it will probably break on different versions of the C++ library.
There is no support of exposing file descriptor neither in standard C++ nor in libstdc++.

Clearing Contents of a File in C++ knowing only the FILE *

Is it possible to clear the contents (ie. set EOF to the beginning/reset the file) in C++ knowing just the FILE*? I'm writing to a temp file with wb+ access and wish to sometimes clear it and truncate it without adding the calls to fclose and fopen. I dont think it's possible... but if not, why not?
Thanks in advance!
It will depend on your platform. The POSIX standard provides ftruncate(), which requires a file descriptor, not a FILE pointer, but it also provides fileno() to get the file descriptor from the FILE pointer.
The analogous facilities will be available in Windows environments - but under different names.
I don't believe this can be done using just the FILE*. You can always write null data through the end of the file but that won't truncate it.
Alternately if you have access to the filename (I can't tell from the question) you could use freopen which hides the close/open/truncate into a single function call.
#include <cstdio>
freopen(null, "w", filePtr);
see http://www.cplusplus.com/reference/clibrary/cstdio/freopen/ for more. espacialy the description for the parameter filename.

How can I create a temporary file for writing in C++ on a Linux platform?

In C++, on Linux, how can I write a function to return a temporary filename that I can then open for writing?
The filename should be as unique as possible, so that another process using the same function won't get the same name.
Use one of the standard library "mktemp" functions: mktemp/mkstemp/mkstemps/mkdtemp.
Edit: plain mktemp can be insecure - mkstemp is preferred.
tmpnam(), or anything that gives you a name is going to be vulnerable to race conditions. Use something designed for this purpose that returns a handle, such as tmpfile():
#include <stdio.h>
FILE *tmpfile(void);
The GNU libc manual discusses the various options available and their caveats:
http://www.gnu.org/s/libc/manual/html_node/Temporary-Files.html
Long story short, only mkstemp() or tmpfile() should be used, as others have mentioned.
man tmpfile
The tmpfile() function opens a unique temporary file in binary
read/write (w+b) mode. The file will be automatically deleted when it
is closed or the program terminates.ote
mktemp should work or else get one of the plenty of available libraries to generate a UUID.
The tmpnam() function in the C standard library is designed to solve just this problem. There's also tmpfile(), which returns an open file handle (and automatically deletes it when you close it).
You should simply check if the file you're trying to write to already exists.
This is a locking problem.
Files also have owners so if you're doing it right the wrong process will not be able to write to it.