这是一个适合每个人意识的项目。它是我在C中的第一个项目,有一个关于lseek()
和移动文件指针的问题。
现在我能够读取位图文件的位图和DIB标头。我现在需要遍历像素并以某种方式操纵它们。我已经用伪代码写出了我打算如何解决这个问题。但是我很难理解如何正确使用lseek
,因为我的代码不断收到incompatible pointer to integer conversion...
警告。我将简要介绍一下我的主要方法,因为这是一个项目:
int main(int argc, const char * argv[]) {
FILE *fp;
if((fp = fopen(argv[1], "r+b")) == NULL){
printf("Error: Unable to open file.\n");
exit(0);
}
fseek(fp, 0, SEEK_END);
long fsize = ftell(fp);
rewind(fp);
char test; // simply to test overwriting the current byte
fread(&test, sizeof(char), 1, fp);
test = ~test;
lseek(fp, -1, SEEK_CUR); //produces error
//also tried fseek prior to realizing I should be using lseek to move my pointer.
fwrite(&test, 1, sizeof(char), fp);
fclose(fp);
return 0;
}
同样,不要试图提供太多的代码,因为这是一个项目。但是,我希望了解如何正确使用lseek
。我注意到它返回int
值,所以我知道这是因为我的文件指针是FILE
类型。但是使用这种方法的正确方法是什么?我看到一个在读写模式下打开相同文件的示例,其中写模式使用lseek
。但出于某种原因,我不知道这是否正确。
EDITED 根据两位成员的回复,我将上面的代码更改为:
rewind(fp);
lseek(fileno(fp), hdr.offset, SEEK_CUR); //hdr.offset == 54 bytes
printf("FD FILENO: %d\n", fileno(fp)); // prints 3???
printf("CURRENT POS: %p\n", fp); //prints 0x7fffe7eae0b0 (I understand it's an address)
fread(&test, sizeof(char), 1, fp);
lseek(fileno(fp), -1, SEEK_CUR);
fwrite(&test, 1, sizeof(char), fp);
printf("CURRENT POS: %p\n", fp); //prints the same address as above?
除了与C有关的所有内容之外,我得到的是什么?
答案 0 :(得分:3)
如果您想继续使用FILE *fp
,这可能是一个好主意,您可以将fp
转换为与int
对应的int fileno(FILE *stream)
文件描述符。换句话说,
lseek(fileno(fp), -1, SEEK_CUR);
<强>加强>
一切正常fseek
。
#include <stdio.h>
int main(int argc, const char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s FILENAME\n", argv[0]);
return 1;
}
FILE *fp;
if((fp = fopen(argv[1], "r+b")) == NULL){
fprintf(stderr, "Error: Unable to open fle '%s'.\n", argv[1]);
return 1;
}
char buf[17];
size_t n_read = fread(buf, sizeof(char), sizeof buf - 1, fp);
buf[n_read] = '\0';
printf("Initial contents: %s\n", buf);
fseek(fp, 0, SEEK_END);
long fsize = ftell(fp);
printf("Position at end of file: %ld\n", fsize);
// Read first character in file.
rewind(fp);
char test;
fread(&test, sizeof(char), 1, fp);
++test;
fseek(fp, -1, SEEK_CUR);
fwrite(&test, sizeof(char), 1, fp);
rewind(fp);
n_read = fread(buf, sizeof(char), sizeof buf - 1, fp);
buf[n_read] = '\0';
printf("Final contents: %s\n", buf);
fclose(fp);
return 0;
}
然后
$ gcc foo.c -o foo
$ ./foo foo.c
Initial contents: #include <stdio.
Position at end of file: 881
Final contents: $include <stdio.
答案 1 :(得分:1)
此处fp
的类型为FILE *
,但lseek将int
作为第一个参数。
所以使用open而不是fopen:
int main(int argc, const char * argv[]) {
int fp;
// Open return the file descriptor
if((fp = open(argv[1], O_RDWR | O_WRONLY)) == -1){
printf("Error: Unable to open file.\n");
exit(0);
}
// Rest of the function
lseek(fp, -1, SEEK_CUR);
<强> [编辑] 强>
另一个问题是使用fileno()
功能
fileno()
以FILE *
为参数,返回int
函数所需的file_descriptor(lseek()
)。
您可以像这样使用它:
int main(int argc, const char * argv[]) {
FILE *fp;
int fd;
// Open return the file descriptor
if((fp = fopen(argv[1], "r+b")) == NULL){
printf("Error: Unable to open file.\n");
exit(0);
}
if ((fd = fileno(fp)) == -1){
printf("Fileno Error\n");
exit(0);
}
// Rest of the function
lseek(fd, -1, SEEK_CUR);
这是doc =&gt; https://linux.die.net/man/3/fileno