我正在尝试在创建所需大小的文件时真正理解lseek()
的使用。所以我编写了这段代码,唯一的目标是创建一个输入中给出的大小的文件。
运行例如:
$ ./lseek_test myFile 5
我希望它能创建一个名为myFile
的5个字节的文件,其最后一个字节被数字5占用。我得到的是一个我甚至无法访问的文件。 出了什么问题?我是否错误地解释了lseek()
的用法?
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#define abort_on_error(cond, msg) do {\
if(cond) {\
int _e = errno;\
fprintf(stderr, "%s (%d)\n", msg, _e);\
exit(EXIT_FAILURE);\
}\
} while(0)
/* Write an integer with error control on the file */
void write_int(int fd, int v) {
ssize_t c = write(fd, &v, sizeof(v));
if (c == sizeof(v))
return;
abort_on_error(c == -1 && errno != EINTR, "Error writing the output file");
abort_on_error(1, "Write operation interrupted, aborting");
}
int main(int argc, char *argv[]) {
// Usage control
abort_on_error(argc != 3, "Usage: ./lseek_test <FileName> <FileSize>");
// Parsing of the input
int size = strtol(argv[2], NULL, 0);
// Open file
int fd = open(argv[1], O_RDWR|O_CREAT, 0644);
abort_on_error(fd == -1, "Error opening or creating file");
// Use lseek() and write() to create the file of the needed size
abort_on_error(lseek(fd, size, SEEK_SET) == -1, "Error in lseek");
write_int(fd, size); // To truly extend the file
//Close file
abort_on_error(close(fd) == -1, "Error closing file");
return EXIT_SUCCESS;
}
答案 0 :(得分:6)
根据其实施情况,您的计划完全符合我的预期:
int
(sizeof(int)
)的4个字节写入文件,从偏移量5开始结果是一个9字节的文件,带有字节值(不可打印数字):
0 0 0 0 0 5 0 0 0
(我的系统是little-endian。)特别注意,该文件在任何意义上都不是 text 文件。如果您期望一个文本文件,就像在这种情况下一样,您可能确实会看到关于它的意外行为,您可能会将其描述为无法访问它。
然后考虑一些事项:
char
中并写下char
;不要写它的int
表示。或者,将文件描述符包装在流中并使用流I / O函数,例如fputc()
。lseek()函数应允许将文件偏移量设置为超出文件中现有数据的末尾。如果此时稍后写入数据,则后续读取间隙中的数据应返回值为0的字节,直到数据实际写入间隙为止。
答案 1 :(得分:-2)
在某些(非常旧的?)系统上lseek
将不允许您搜索文件的末尾,如果您尝试它,则会收到EINVAL
错误。< / p>
相反,您希望先使用ftruncate
更改文件大小,然后使用lseek
来查找要读取(或写入)文件的位置。以你的例子:
ftruncate(fd, 5); // set file size to 5
lseek(fd, SEEK_END, 0); // reposition to new end
write(fd, &v, sizeof(v); // write data (extending the file)