fseek 到 32 位无符号偏移量
fseek to a 32-bit unsigned offset
我正在读取一种文件格式 (TIFF),它从文件开头开始有 32 位无符号偏移量。
不幸的是,fseek 的原型是:
int fseek ( FILE * stream, long int offset, int origin );
所以偏移量是有符号的。我应该如何处理这种情况?我应该使用不同的功能来寻找吗?
您可以尝试使用lseek64()
(man page)
#define _LARGEFILE64_SOURCE /* See feature_test_macros(7) */
#include <sys/types.h>
#include <unistd.h>
off64_t lseek64(int fd, off64_t offset, int whence);
有
int fd = fileno (stream);
来自 The GNU C lib - Setting the File Position of a Descriptor
的注释
This function is similar to the lseek function. The difference is that the offset parameter is of type off64_t instead of off_t which makes it possible on 32 bit machines to address files larger than 2^31 bytes and up to 2^63 bytes. The file descriptor filedes must be opened using open64 since otherwise the large offsets possible with off64_t will lead to errors with a descriptor in small file mode.
When the source file is compiled with _FILE_OFFSET_BITS == 64 on a 32 bits machine this function is actually available under the name lseek and so transparently replaces the 32 bit interface.
关于fd
和stream
,来自Streams and File Descriptors
Since streams are implemented in terms of file descriptors, you can extract the file descriptor from a stream and perform low-level operations directly on the file descriptor. You can also initially open a connection as a file descriptor and then make a stream associated with that file descriptor.
在更深入地研究了这个问题并考虑了其他评论和答案(谢谢)之后,我认为最简单的方法是如果偏移量大于 2147483647 字节则进行两次查找。这允许我将偏移量保持为 uint32_t
并继续使用 fseek
。因此定位代码是这样的:
// note: error handling code omitted
uint32_t offset = ... (whatever it is)
if( offset > 2147483647 ){
fseek( file, 2147483647, SEEK_SET );
fseek( file, (long int)( offset - 2147483647 ), SEEK_CUR );
} else {
fseek( file, (long int) offset, SEEK_SET );
}
使用 64 位类型的问题是代码可能 运行 在 32 位架构上(除其他外)。有一个函数 fsetpos
使用结构 fpos_t
来管理任意大的偏移量,但这带来了一系列的复杂性。虽然 fsetpos
可能有意义,如果我真的使用任意大的偏移量,因为我知道最大可能的偏移量是 uint32_t,那么双重搜索满足了这个需要。
请注意,此解决方案允许在 32 位系统上处理所有 TIFF 文件。如果您考虑像 PixInsight 这样的商业程序,这样做的好处是显而易见的。在 32 位系统上 运行 时,PixInsight 只能处理小于 2147483648 字节的 TIFF 文件。要处理全尺寸 TIFF 文件,用户必须在 64 位计算机上使用 64 位版本的 PixInsight。这可能是因为 PixInsight 程序员使用 64 位类型在内部处理偏移量。由于我的解决方案仅使用 32 位类型,因此我可以在 32 位系统上处理全尺寸的 TIFF 文件(只要底层操作系统可以处理那么大的文件)。
我正在读取一种文件格式 (TIFF),它从文件开头开始有 32 位无符号偏移量。
不幸的是,fseek 的原型是:
int fseek ( FILE * stream, long int offset, int origin );
所以偏移量是有符号的。我应该如何处理这种情况?我应该使用不同的功能来寻找吗?
您可以尝试使用lseek64()
(man page)
#define _LARGEFILE64_SOURCE /* See feature_test_macros(7) */
#include <sys/types.h>
#include <unistd.h>
off64_t lseek64(int fd, off64_t offset, int whence);
有
int fd = fileno (stream);
来自 The GNU C lib - Setting the File Position of a Descriptor
的注释This function is similar to the lseek function. The difference is that the offset parameter is of type off64_t instead of off_t which makes it possible on 32 bit machines to address files larger than 2^31 bytes and up to 2^63 bytes. The file descriptor filedes must be opened using open64 since otherwise the large offsets possible with off64_t will lead to errors with a descriptor in small file mode.
When the source file is compiled with _FILE_OFFSET_BITS == 64 on a 32 bits machine this function is actually available under the name lseek and so transparently replaces the 32 bit interface.
关于fd
和stream
,来自Streams and File Descriptors
Since streams are implemented in terms of file descriptors, you can extract the file descriptor from a stream and perform low-level operations directly on the file descriptor. You can also initially open a connection as a file descriptor and then make a stream associated with that file descriptor.
在更深入地研究了这个问题并考虑了其他评论和答案(谢谢)之后,我认为最简单的方法是如果偏移量大于 2147483647 字节则进行两次查找。这允许我将偏移量保持为 uint32_t
并继续使用 fseek
。因此定位代码是这样的:
// note: error handling code omitted
uint32_t offset = ... (whatever it is)
if( offset > 2147483647 ){
fseek( file, 2147483647, SEEK_SET );
fseek( file, (long int)( offset - 2147483647 ), SEEK_CUR );
} else {
fseek( file, (long int) offset, SEEK_SET );
}
使用 64 位类型的问题是代码可能 运行 在 32 位架构上(除其他外)。有一个函数 fsetpos
使用结构 fpos_t
来管理任意大的偏移量,但这带来了一系列的复杂性。虽然 fsetpos
可能有意义,如果我真的使用任意大的偏移量,因为我知道最大可能的偏移量是 uint32_t,那么双重搜索满足了这个需要。
请注意,此解决方案允许在 32 位系统上处理所有 TIFF 文件。如果您考虑像 PixInsight 这样的商业程序,这样做的好处是显而易见的。在 32 位系统上 运行 时,PixInsight 只能处理小于 2147483648 字节的 TIFF 文件。要处理全尺寸 TIFF 文件,用户必须在 64 位计算机上使用 64 位版本的 PixInsight。这可能是因为 PixInsight 程序员使用 64 位类型在内部处理偏移量。由于我的解决方案仅使用 32 位类型,因此我可以在 32 位系统上处理全尺寸的 TIFF 文件(只要底层操作系统可以处理那么大的文件)。