此问题在此处已有答案:
Increasing a file's size using mmap(1个答案)
5天前关闭。
问题和预期结果
我正在尝试读入一个文件,看看是否可以将该数据写入另一个非空文件。最后,我希望能够将数据插入到该文件中,但这是另一个问题。现在,我能够写入该文件,但文件的大小不会更改。例如,给定以下文件test.dat
Name,marker1,marker2,marker3,marker4
barc1,AA,AB,BB,--
barc2,AB,AA,BB,--
如果我尝试写入以下数据test.dat.toAdd
barc3,BB,AB,--,AA
barc4,AB,--,BB,AA
barc5,--,AB,AA,BB
barc6,BB,AA,AB,--
barc7,AA,AB,BB,AA
barc8,BB,AB,AA,BB
从15字节开始,我希望得到
Name,marker1,mabarc3,BB,AB,--,AA
barc4,AB,--,BB,AA
barc5,--,AB,AA,BB
barc6,BB,AA,AB,--
barc7,AA,AB,BB,AA
barc8,BB,AB,AA,BB
但实际上我最后test.dat
Name,marker1,mabarc3,BB,AB,--,AA
barc4,AB,--,BB,AA
barc5,--,AB,AA,BB
barc
因此,它只写入test.dat
最初的大小
代码
下面是我使用的代码my_write.cpp
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <sstream>
#include <unistd.h>
// Opens up [filename] after [offset] bytes and returns a pointer in memory to the beginning of [filename] + [offset]
char* open_mmap_file_read(const char* filename, long long offset, long long& filesize) {
// Open the file in read-only mode
const char* my_file = filename;
int fd = open(my_file, O_RDONLY);
if (fd < 0) { std::cerr << "Cannot open the file " << my_file << std::endl; }
// Get the filesize (and possibly error) of the file opening. Filesize is in bytes
struct stat statbuf;
int err = fstat(fd, &statbuf);
off_t sz = statbuf.st_size;
if (err < 0) { std::cerr << "Cannot open the file " << my_file << " because of fstat val " << err << std::endl; return NULL; }
std::cout << "File size for " << my_file << " is " << sz << " bytes" << std::endl;
// Map the file into memory with a pointer to the beginning of the file
void *fileArea = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
if (! fileArea) { std::cerr << "Cannot map " << my_file << std::endl; return NULL; }
std::cout << "File " << my_file << " mapped to address " << fileArea << std::endl;
// Move the pointer according to the [offset] parameter in memory
char *localArea = reinterpret_cast<char*>(fileArea);
if (! localArea) { std::cerr << "Cannot allocate " << sz << " bytes" << std::endl; return NULL; }
localArea += offset;
// Store the filesize for use when function returns
filesize = sz;
return localArea;
}
// Opens [filename] and writes [data_to_write] in [filename] starting at [offset] bytes. The amount of data to be written is [size_data_to_write]
char* open_mmap_file_write(const char* filename, long long offset, char* data_to_write, long long size_data_to_write, long long& filesize) {
// Open the file in read/write mode
const char* my_file = filename;
int fd = open(my_file, O_RDWR);
if (fd < 0) { std::cerr << "Cannot open the file " << my_file << std::endl; }
// Get the filesize (and possibly error) of the file opening. Filesize is in bytes
struct stat statbuf;
int err = fstat(fd, &statbuf);
off_t sz = statbuf.st_size;
if (err < 0) { std::cerr << "Cannot open the file " << my_file << " because of fstat val " << err << std::endl; return NULL; }
std::cout << "File size for " << my_file << " is " << sz << " bytes" << std::endl;
filesize = sz;
// Map the file into memory with a pointer to the beginning of the file
void *fileArea = mmap(NULL, offset + size_data_to_write, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
//void *fileArea = mmap(NULL, 200, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (! fileArea) { std::cerr << "Cannot map " << my_file << std::endl; return NULL; }
std::cout << "File " << my_file << " mapped to address " << fileArea << std::endl;
// Move the pointer according to the [offset] parameter in memory
char *localArea = reinterpret_cast<char*>(fileArea);
if (! localArea) { std::cerr << "Cannot allocate " << sz << " bytes" << std::endl; return NULL; }
localArea += offset;
// Copy [data_to_write] into the memory mapping of [filename] starting from [offset] bytes
//ssize_t n = write(fd, data_to_write, size_data_to_write);
void* copiedArea = memcpy(localArea, data_to_write, size_data_to_write);
// Return a pointer to the beginning of the file
return reinterpret_cast<char*>(fileArea);
}
int main(int argc, char *argv[]) {
if (argc < 4) {
std::cerr << "Please provide two command-line arguments: file_to_open (string) and file_offset (integer), file_to_add (string)" << std::endl;
return 1;
}
// Get the filename and offset parameters and make sure offset is valid
const char* file_to_open = argv[1];
const char* arg_file_offset = argv[2];
const char* file_to_add = argv[3];
std::istringstream iss(arg_file_offset);
long long file_offset;
if (!(iss >> file_offset)) { std::cerr << "Cannot convert command-line argument " << arg_file_offset << " into an integer for file offset" << std::endl; return 1; }
long long file_to_add_size; // Pass this by reference to the following function to keep track of filesize
char* file_to_add_pointer = open_mmap_file_read(file_to_add, 0, file_to_add_size);
// Print out the first 20 characters from where the file start pointing
for (int i = 0; i < 20; i++) { std::cout << file_to_add_pointer[i]; } std::cout << std::endl;
std::cout << std::endl;
long long file_size;
char* file_pointer = open_mmap_file_write(file_to_open, file_offset, file_to_add_pointer, file_to_add_size, file_size);
// Print out all the characters that were written to the memory-mapping
for (int i = 0; i < file_offset + file_to_add_size; i++) { std::cout << file_pointer[i]; } std::cout << std::endl;
std::cout << std::endl;
return 0;
}
它使用./my_write test.dat 15 test.dat.toAdd
运行
所以我的问题是,我如何“扩展”文件以容纳正在写入的全部数据。它正在写入内存(正如我们可以从main函数中的print看到的),甚至正在写入文件,但它会根据文件大小被截断。我确信这是一个简单的修复,但我似乎找不到如何告诉系统扩展文件的内存
1条答案
按热度按时间nr9pn0ug1#
目标文件不足以存储所有
test.dat.toAdd
+ 15字节。您可以使用
ftruncate
在open_mmap_file_write
中扩展它: