gpt4 book ai didi

C - 在不使用内存(就地)的情况下读取然后写入文件?

转载 作者:行者123 更新时间:2023-11-30 14:57:59 27 4
gpt4 key购买 nike

我需要将一个大字符串向左“移动”X 个空格。它太大了,无法放入内存,所以我需要就地做。我需要使用最少量的系统调用来完成此操作。

我知道我可以使用缓冲区并重用内存来最大限度地减少内存消耗,然后使用 fseek -> Read -> Write 直到完成,但我有兴趣看看是否这样做这样的事情是可能发生的。

最佳答案

您可以通过一次移动一个字节来完成此操作,如下所示。但是,如果允许更大的缓冲区(一次移动 4096 字节),您将获得更好的性能。显然,我们使用了一些堆栈内存,但它不会根据前缀的大小或文件的大小进行分配,因此我们可以将其称为“就地”。

void inPlaceTruncate(
char const * const filename,
int shift)
{
FILE * f;
if ((f = fopen(filename, "r+")) == NULL) {
// handle error
}

// go to the end
if (fseek(f, 0, SEEK_END) != 0) {
// handle error
}

// get current file size
long int const oldFileLen = ftell(f);
if (oldFileLen < 0) {
// handle error
} else if (oldFileLen < shift) {
// make the file empty
shift = oldFileLen;
}

// go back to the beginning
if (fseek(f, 0, SEEK_SET) != 0) {
// handle error
}

// move file
char buffer;
for (long int pos = 0; pos < oldFileLen-shift; ++pos) {
// slow to be repeatedly fseeking...
if (fseek(f, pos+shift, SEEK_SET) != 0) {
// handle error
}

if (fread(&buffer, sizeof(buffer), 1, f) != 1) {
// handle error
}

if (fseek(f, pos, SEEK_SET) != 0) {
// handle error
}

if (fwrite(&buffer, sizeof(buffer), 1, f) != 1) {
// handle error
}
}

// shrink file -- in a rather unpleasent way
#ifdef WIN32
if (_chsize(fileno(f), oldFileLen-shift) != 0) {
// handle error
}
#else
// we're assuming if its not windows, it's at least posix compliant.
if (ftruncate(fileno(f), oldFileLen-shift) != 0) {
// handle error
}
#endif

fclose(f);
}

相关post用于缩小文件。

编辑以实际回答OP的问题。

已编辑以记录错误处理的位置。

此外,正如评论中所指出的,这只能处理小于 2GB 的文件和移位。为了处理更大的文件并解决 fseek()/ftell()/ftruncate() 32 位限制(在 Windows 上,您可以可以使用 _chsize_s ),您需要使用相对偏移量确定循环中的文件大小,并多次调用 ftruncate()

关于C - 在不使用内存(就地)的情况下读取然后写入文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43553736/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com