c语言写文件不覆盖,C在二进制文件中间进行写入,而不会覆盖任何现有内容

这extend_file_and_insert()或多或少是完成工作的功能。

#include

#include

enum { BUFFERSIZE = 64 * 1024 };

#define MIN(x, y) (((x) < (y)) ? (x) : (y))

/*

off_t   is signed

ssize_t is signed

size_t  is unsigned

off_t   for lseek() offset and return

size_t  for read()/write() length

ssize_t for read()/write() return

off_t   for st_size

*/

static int extend_file_and_insert(int fd, off_t offset, char const *insert, size_t inslen)

{

char buffer[BUFFERSIZE];

struct stat sb;

int rc = -1;

if (fstat(fd, &sb) == 0)

{

if (sb.st_size > offset)

{

/* Move data after offset up by inslen bytes */

size_t bytes_to_move = sb.st_size - offset;

off_t read_end_offset = sb.st_size;

while (bytes_to_move != 0)

{

ssize_t bytes_this_time = MIN(BUFFERSIZE, bytes_to_move);

ssize_t rd_off = read_end_offset - bytes_this_time;

ssize_t wr_off = rd_off + inslen;

lseek(fd, rd_off, SEEK_SET);

if (read(fd, buffer, bytes_this_time) != bytes_this_time)

return -1;

lseek(fd, wr_off, SEEK_SET);

if (write(fd, buffer, bytes_this_time) != bytes_this_time)

return -1;

bytes_to_move -= bytes_this_time;

read_end_offset -= bytes_this_time; /* Added 2013-07-19 */

}

}

lseek(fd, offset, SEEK_SET);

write(fd, insert, inslen);

rc = 0;

}

return rc;

}

(请注意,在2013年7月19日增加了另一行;它是一个错误,仅在缓冲区大小小于要复制到文件上的数据量时才显示。感谢malat指出了该错误。现在对代码进行测试BUFFERSIZE = 4)

这是一些小型测试代码:

#include

#include

static const char base_data[] = "12345";

typedef struct Data

{

off_t       posn;

const char *data;

} Data;

static const Data insert[] =

{

{  2, "456"                       },

{  4, "XxxxxxX"                   },

{ 12, "ZzzzzzzzzzzzzzzzzzzzzzzzX" },

{ 22, "YyyyyyyyyyyyyyyY"          },

};

enum { NUM_INSERT = sizeof(insert) / sizeof(insert[0]) };

int main(void)

{

int fd = open("test.dat", O_RDWR | O_TRUNC | O_CREAT, 0644);

if (fd > 0)

{

ssize_t base_len = sizeof(base_data) - 1;

if (write(fd, base_data, base_len) == base_len)

{

for (int i = 0; i < NUM_INSERT; i++)

{

off_t length = strlen(insert[i].data);

if (extend_file_and_insert(fd, insert[i].posn, insert[i].data, length) != 0)

break;

lseek(fd, 0, SEEK_SET);

char buffer[BUFFERSIZE];

ssize_t nbytes;

while ((nbytes = read(fd, buffer, sizeof(buffer))) > 0)

write(1, buffer, nbytes);

write(1, "\n", 1);

}

}

close(fd);

}

return(0);

}

它产生输出:

12456345

1245XxxxxxX6345

1245XxxxxxX6ZzzzzzzzzzzzzzzzzzzzzzzzZ345

1245XxxxxxX6ZzzzzzzzzzYyyyyyyyyyyyyyyYzzzzzzzzzzzzzzZ345

应该在一些更大的文件上进行测试(比BUFFERSIZE大一些,但是使用比64 KiB小得多的BUFFERSIZE进行测试是明智的;我使用32字节,这似乎还可以)。我只是关注结果,但是这些模式旨在让您容易看出它们是正确的。该代码不检查任何lseek()调用。这是一个较小的风险。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值