C lseek()试图与字节文件一起使用,但指针是文件类型
这是一个让每个人都意识到的项目。这是我在C语言中的第一个项目,我有一个关于lseek和移动文件指针的问题 现在我能够读取位图文件的位图和DIB头。我现在需要遍历像素并以某种方式操纵它们。我已经用伪代码写了我计划如何处理操纵。但我很难理解如何正确使用lseek,因为我一直得到不兼容的整数转换指针。。。警告与我的代码。我将给出我的主要方法的一个简短示例,因为这是针对一个项目的:C lseek()试图与字节文件一起使用,但指针是文件类型,c,pointers,bitmap,file-handling,lseek,C,Pointers,Bitmap,File Handling,Lseek,这是一个让每个人都意识到的项目。这是我在C语言中的第一个项目,我有一个关于lseek和移动文件指针的问题 现在我能够读取位图文件的位图和DIB头。我现在需要遍历像素并以某种方式操纵它们。我已经用伪代码写了我计划如何处理操纵。但我很难理解如何正确使用lseek,因为我一直得到不兼容的整数转换指针。。。警告与我的代码。我将给出我的主要方法的一个简短示例,因为这是针对一个项目的: int main(int argc, const char * argv[]) { FILE *fp;
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有关的一切之外,我没有得到什么?这里fp是文件的类型*,但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*作为参数并返回lseek函数所需的文件描述符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);
这里是doc=>这里fp是文件的类型*,但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*作为参数并返回lseek函数所需的文件描述符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);
下面是doc=>如果您想继续使用FILE*fp,这可能是一个好主意,您可以使用int filenoFILE*stream将fp转换为相应的int文件描述符。换句话说,
lseek(fileno(fp), -1, SEEK_CUR);
增加
所有工作与fseek良好
然后
$ gcc foo.c -o foo
$ ./foo foo.c
Initial contents: #include <stdio.
Position at end of file: 881
Final contents: $include <stdio.
如果您想继续使用FILE*fp,这可能是一个好主意,您可以使用int filenoFILE*stream将fp转换为其对应的int文件描述符。换句话说,
lseek(fileno(fp), -1, SEEK_CUR);
增加
所有工作与fseek良好
然后
$ gcc foo.c -o foo
$ ./foo foo.c
Initial contents: #include <stdio.
Position at end of file: 881
Final contents: $include <stdio.
所以我需要在我的文件中维护2个指针?现在,我正在使用fread将值填充到带有标题信息的结构中。为这个可能很愚蠢的问题道歉,但是你是说当我对我的当前文件*fp使用fopen时,我还应该用另一个int指针open来跟踪它吗?我还得查一下这些论点,因为它们对我来说是新的。谢谢!就在你发完帖子之后,我当然发现了。我没有正确表达我的问题,使我感到困惑。我要试一试!我已经添加了您提到的代码,但没有看到预期的响应。请看我上面的编辑,不要害怕告诉我我是如何以一种非常严厉和批判性的方式做错事的。所以我需要在我的文件中保留两个指针?现在,我正在使用fread将值填充到带有标题信息的结构中。为这个可能很愚蠢的问题道歉,但是你是说当我对我的当前文件*fp使用fopen时,我还应该用另一个int指针open来跟踪它吗?我还得查一下这些论点,因为它们对我来说是新的。谢谢!就在你发完帖子之后,我当然发现了。我没有正确表达我的问题,使我感到困惑。我要试一试!我已经添加了您提到的代码,但没有看到预期的响应。请看我上面的编辑,不要害怕告诉我我是如何以一种非常严厉和批判性的方式做错事的。我结合了你和@YaatSuka的建议,仍然没有得到我认为会得到的结果。请看我的编辑,谢谢你的建议@Pwrcdr87您正在获得预期的结果。文件句柄是小整数,在大多数C impl中从3开始,因为0,1,2用于stdin、stdout和stderr。如果您打开一个不同的文件,它可能会得到4,等等。fp是指向内存中文件数据结构的指针。这不会改变的。你在期待什么?也许您打算ftell查看当前流的位置。这就是通过调用任何seek变体进行调整的内容。但是C标准不能保证ftell结果是字节偏移量;只有它上面的fseek才会使文件处于相同的状态。顺便问一下,你对fseek有什么反对意见?我个人并不反对fseek,但我相信我的问题是我没有完全理解它的用途以及如何正确地检索它的当前值。我记得我的教授提到过lseek,但不记得他说过它是否有用。我把你和@YaatSuka的建议结合在一起,仍然没有得到我想得到的结果。请看我的编辑a
谢谢你的建议@Pwrcdr87您正在获得预期的结果。文件句柄是小整数,在大多数C impl中从3开始,因为0,1,2用于stdin、stdout和stderr。如果您打开一个不同的文件,它可能会得到4,等等。fp是指向内存中文件数据结构的指针。这不会改变的。你在期待什么?也许您打算ftell查看当前流的位置。这就是通过调用任何seek变体进行调整的内容。但是C标准不能保证ftell结果是字节偏移量;只有它上面的fseek才会使文件处于相同的状态。顺便问一下,你对fseek有什么反对意见?我个人并不反对fseek,但我相信我的问题是我没有完全理解它的用途以及如何正确地检索它的当前值。我记得我的教授提到过lseek,但不记得他说过它是否可用。第6行:filenofp而不是filefp为什么要用lseek而不是fseek?@dashwuff是的,因为我需要能够在读写字节时在字节之间来回移动指针。提示:我很难理解如何正确地使用它们使用lseek->那么为什么代码不检查fseek、rewind、fread、lseek等的返回值。。。确保代码正常运行?代码很好地做到了这一点。通过测试返回值可以获得更多的洞察力和代码可信度。不要将lseek与stdio例程混合使用。文件*具有内部缓冲,并且不知道您对LSEEK进行了交互。使用fseek。第6行:filenofp而不是filefp为什么要使用lseek而不是fseek?@duskwuff是的,因为我需要能够在读取和写入字节时在字节之间来回移动指针。提示:我很难理解如何正确使用lseek->那么为什么代码不检查fseek、rewind、fread、lseek的返回值, ... 确保代码正常运行?代码很好地做到了这一点。通过测试返回值可以获得更多的洞察力和代码可信度。不要将lseek与stdio例程混合使用。文件*具有内部缓冲,并且不知道您对LSEEK进行了交互。使用fseek。