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

时间:2017-10-03 02:02:02

标签: c pointers bitmap file-handling lseek

这是一个适合每个人意识的项目。它是我在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有关的所有内容之外,我得到的是什么?

2 个答案:

答案 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