1

这是一个让每个人都意识到的项目。这是我在 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. 但由于某种原因,我不知道这是否正确。

已编辑 基于两个成员的响应,我将上面的代码更改为:

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

4

2 回答 2

4

如果您想继续使用,这可能是个好FILE *fp主意,您可以使用. 换句话说,fpintint 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.
于 2017-10-03T02:43:53.457 回答
1

fp是 lseek 的类型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()将 aFILE *作为参数并返回函数所需的 file_descriptor ( int) 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);

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

于 2017-10-03T02:16:41.707 回答