lseek() 尝试使用字节文件,但指针是 FILE 类型

lseek() Trying to use with a byte file but pointer is of FILE type

这是一个让每个人都意识到的项目。这是我在 C 中的第一个项目,有一个关于 lseek() 和移动文件指针的问题。

现在我可以读取位图文件的位图和 DIB header。我现在需要遍历像素并以特定方式操作它们。我已经用伪代码写出了我打算如何处理操纵。但是我很难理解如何正确使用 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。我注意到它 returns 是一个 int 值,所以我知道这是因为我的文件指针是 FILE 类型。但是使用这种方法的正确方法是什么?我看到一个例子,它以读写模式打开同一个文件,其中写模式使用 lseek。但不知为何我不知道这是否正确。

已编辑 根据两位成员的回应,我将上面的代码更改为:

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 相关的一切之外,我还没有得到什么?

这里 fpFILE * 的类型,但是 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 * 作为参数,return lseek() 函数所需的 file_descriptor (int)。
你可以这样使用它:

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);

这是文档 => https://linux.die.net/man/3/fileno

如果您想继续使用 FILE *fp,这可能是个好主意,您可以使用 [=16= 将 fp 转换为相应的 int 文件描述符].也就是说,

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] = '[=11=]';
  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] = '[=11=]';
  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.