我正在尝试使用lseek()创建一个具有给定大小的文件,并在文件末尾添加一个字节,但是它会创建一个0字节的稀疏文件。
以下是代码......有什么建议吗?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif // BUF_SIZE
int main(int argc, char *argv[])
{
int inputFd;
int fileSize = 500000000;
int openFlags;
int result;
mode_t filePerms;
ssize_t numRead;
char buf[BUF_SIZE];
openFlags = O_WRONLY | O_CREAT | O_EXCL;
filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /*rw-rw-ew*/
inputFd = open(argv[1], openFlags, filePerms);
if (inputFd == -1)
printf("problem opening file %s ", argv[1]);
return 1;
printf ("input FD: %d", inputFd);
result = lseek(inputFd, fileSize-1, SEEK_SET);
if (result == -1){
close(inputFd);
printf("Error calling lseek() to stretch the file");
return 1;
}
result = write(inputFd, "", 1);
if (result < 0){
close(inputFd);
printf("Error writing a byte at the end of file\n");
return 1;
}
if (close(inputFd) == -1)
printf("problem closing file %s \n",argv[1]);
return 0;
}
答案 0 :(得分:5)
你缺少一些大括号:
if (inputFd == -1)
printf("problem opening file %s ", argv[1]);
return 1;
您需要将其更改为:
if (inputFd == -1) {
printf("problem opening file %s ", argv[1]);
return 1;
}
没有大括号,if
语句控制的唯一语句是printf
,无论return 1;
的值是什么,inputFd
语句总是运行
优点是总是在受控块周围使用大括号,即使只有一个语句(例如程序末尾的close
)。
答案 1 :(得分:0)
你有任何在文件的每个块上写一个字节的例子吗?
此代码来自略有不同的上下文,但可以根据您的情况进行调整。上下文是确保Informix数据库的磁盘空间全部被分配,因此围绕它的包装器代码创建了文件(并且它不存在等)。但是,实际写入的入口点是这两个函数中的第二个 - 填充缓冲区函数将8字节字informix
复制到64 KiB块中。
/* Fill the given buffer with the string 'informix' repeatedly */
static void fill_buffer(char *buffer, size_t buflen)
{
size_t filled = sizeof("informix") - 1;
assert(buflen > filled);
memmove(buffer, "informix", sizeof("informix")-1);
while (filled < buflen)
{
size_t ncopy = (filled > buflen - filled) ? buflen - filled : filled;
memmove(&buffer[filled], buffer, ncopy);
filled *= 2;
}
}
/* Ensure the file is of the required size by writing to it */
static void write_file(int fd, size_t req_size)
{
char buffer[64*1024];
size_t nbytes = (req_size > sizeof(buffer)) ? sizeof(buffer) : req_size;
size_t filesize = 0;
fill_buffer(buffer, nbytes);
while (filesize < req_size)
{
size_t to_write = nbytes;
ssize_t written;
if (to_write > req_size - filesize)
to_write = req_size - filesize;
if ((written = write(fd, buffer, to_write)) != (ssize_t)to_write)
err_syserr("short write (%d vs %u requested)\n",
(int)written, (unsigned)to_write);
filesize += to_write;
}
}
正如您所看到的,它写入64 KiB块。坦率地说,在页面上写入所有字节和每页写入一个字节之间没有区别。实际上,如果有的话,编写整个页面会更快,因为可以简单地编写新值,而如果每页只写一个字节,则必须创建/读取,修改旧页面,然后再写回。
在您的上下文中,我会将当前文件扩展为4 KiB的倍数(如果您愿意,则为8 KiB),然后编写主数据块,并在必要时写入最终的部分块。你可能只是做memset(buffer, '\0', sizeof(buffer));
而示例代码是故意编写除零字节块之外的东西。 AFAIK,即使您编写的块都是零字节,驱动程序实际上会将该块写入磁盘 - 简单的写入操作可确保文件非稀疏。
err_syserr()
函数有点像fprintf(stderr, …)
,但它会添加来自errno
和strerror()
的系统错误消息,并退出程序。代码确实假设32位(或更大)int
值。我从未尝试过使用TB级文件 - 该代码最后一次更新于2009年。