阅读背景:

c语言写文件不覆盖,C在二进制文件中间进行写入,而不会覆盖任何现有内容_超蜡笔的博客

来源:互联网 

慕田峪7331174

这extend_file_and_insert()或多或少是完成工作的功能。#include #include enum { BUFFERSIZE = 64 * 1024 };#define MIN(x, y) (((x) < (y)) ? (x) : (y))/*off_t   is signedssize_t is signedsize_t  is unsignedoff_t   for lseek() offset and returnsize_t  for read()/write() lengthssize_t for read()/write() returnoff_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);}它产生输出:124563451245XxxxxxX63451245XxxxxxX6ZzzzzzzzzzzzzzzzzzzzzzzzZ3451245XxxxxxX6ZzzzzzzzzzYyyyyyyyyyyyyyyYzzzzzzzzzzzzzzZ345应该在一些更大的文件上进行测试(比BUFFERSIZE大一些,但是使用比64 KiB小得多的BUFFERSIZE进行测试是明智的;我使用32字节,这似乎还可以)。我只是关注结果,但是这些模式旨在让您容易看出它们是正确的。该代码不检查任何lseek()调用。这是一个较小的风险。这extend_file_and_insert()




你的当前访问异常,请进行认证后继续阅读剩余内容。

分享到: