यहाँ एक समारोह extend_file_and_insert()
कि काम और अधिक या कम करता है, है।
#include <sys/stat.h>
#include <unistd.h>
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-07-19 जोड़ा गया;। यह एक बग केवल पता चलता है कि जब बफर आकार डेटा की मात्रा से छोटा होता है ओर इशारा करते हुए के लिए malat करने के लिए फ़ाइल धन्यवाद कॉपी करने के लिए था । त्रुटि बाहर संहिता अब BUFFERSIZE = 4
के साथ परीक्षण)
यह कुछ छोटे पैमाने पर परीक्षण कोड है:।
#include <fcntl.h>
#include <string.h>
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
यह कुछ बड़ी फ़ाइलों (परीक्षण के मुकाबले बड़े से अधिक) पर परीक्षण किया जाना चाहिए, लेकिन 64 कीबी से बहुत कम बुफे के साथ परीक्षण करना समझदारी होगी; मैंने 32 बाइट्स का इस्तेमाल किया और यह ठीक लग रहा था)। मैंने केवल परिणामों को नजरअंदाज कर दिया है लेकिन पैटर्न को यह देखने में आसान बनाने के लिए डिज़ाइन किया गया है कि वे सही हैं। कोड lseek()
कॉलों में से कोई भी जांच नहीं करता है; यह एक मामूली जोखिम है।
@ जॉन का जवाब ऐसा लगता है कि यह एकमात्र तरीका हो सकता है लेकिन इसमें बड़ी फ़ाइलों के लिए बहुत सारी प्रतिलिपि शामिल होगी। तो यदि संभव हो तो, डेटा क्रमबद्धता के लिए एक और दृष्टिकोण की तलाश करना सबसे अच्छा काम हो सकता है। – gcbenison
@gcbenison, हाँ, मेरी बाइनरी फ़ाइल 1 जीबी हो सकती है और विस्तार प्रक्रिया बहुत समय तक ट्रिगर हो जाएगी, इसलिए यह शायद एक समस्या होगी –
यदि आप फ़ाइल के बीच में डेटा डालने से बच सकते हैं तो यह सबसे अच्छा होगा, क्योंकि यह करने के लिए इतना महंगा है, गोगबाइट आकार फ़ाइलों में दोगुना है। –