【问题标题】:Can't read file larger than 2GB in Ubuntu 64 bit OS在 Ubuntu 64 位操作系统中无法读取大于 2GB 的文件
【发布时间】:2015-07-23 20:00:08
【问题描述】:

已解决 @nsilent22,感谢您的建议。我所做的唯一更改是在 seekg() 函数参数中。

ND_file.seekg( (long)(block_number)*DISK_BLOCK_SIZE );
ND_file.read((char*)(&count), sizeof(int));

原帖

我知道之前有人提出并回答了类似的问题。现有程序仍需要帮助。

硬件规格:Ubuntu 14.04,64位,ext4文件系统

我有一个用于创建基于磁盘的索引的旧程序。当索引文件达到 2.1GB 时,后面的 read() 函数输入了错误的值,程序中止。

ND_file.seekg(block_number*DISK_BLOCK_SIZE);
ND_file.read((char*)(&count), sizeof(int));

根据类似的帖子,我把#define _FILE_OFFSET_BITS 64 放在每个文件的开头。

以下是make文件:

GCC=g++ -D_FILE_OFFSET_BITS=64
NDT: main.o utility.o logClass.o
     g++ -g -o ndTree main.o utility.o logClass.o
     rm *.o
main.o: main.cpp config.h Box_queries.h Meta_entry.h Meta_node.h Dir_entry.h Dir_node.h Leaf_entry.h Leaf_node.h logClass.h ND_tree.h Node.h utility.h
     g++ -g -c main.cpp
utility.o: utility.cpp utility.h
     g++ -g -c utility.cpp
logClass.o: logClass.cpp logClass.h
     g++ -g -c logClass.cpp
clean:
    rm -f *.o

@已更新

输出日志的一部分:这里 Block-174 被调用了两次。在第一种情况下,读取函数正确输入了磁盘数据。但是,在最后一行中,#Entries 为 0,这是不正确的。这发生在分配 block::524288 时。因此,我猜 read() 和 seekg() 不能正常工作。

Id       NewBlockId   ParentBlockId  #EntriesInBlock  Index #MaxEntries   
554192   524280       463255         149              61    255       
554193   524281       463255         149              75    255
554194   524282       497389         131              80    255
**554195     524283       174            250              26    255**
554196   524284       125426         142              77    255
554197   524285       223509         130             118    255
554198   524286       262212         136              72    255
554199   524287       224407         142             121    255
terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check
**554200     524288       174              0             227    255** Aborted (core dumped)

是否需要使用不同的函数来读取文件内容?任何建议将不胜感激。

【问题讨论】:

  • 你能解释一下为什么前面的答案没有帮助吗?
  • 我的操作系统是64位的,文件系统是ext4,off_t也可以。此外,我明确定义了 -D_FILE_OFFSET_BITS=64。仍然遇到同样的问题。所以,我想知道问题是否出在 read() 和 seekg() 上。
  • block_numberDISK_BLOCK_SIZE是什么类型?
  • const int DISK_BLOCK_SIZE; unsigned int block_number;
  • 那么您认为 unsigned int * int 隐式转换为有符号的 64 位值可能会导致问题吗?也许使用uint64_t 至少其中一个可以解决这个问题?

标签: c++ linux ubuntu limit


【解决方案1】:

答案很简单。根据您的评论:

const int DISK_BLOCK_SIZE; unsigned int block_number;

两个变量的类型都是int(一个是unsigned),所以计算的值是...int。 而int 在 64 位 Ubuntu 系统上的大小是... 32 位。在你的 64 位系统上编译这个简单的代码:

#include <stdio.h>

int main(void) {
    int x = 2000000000;
    int y = 4;
    printf("x = %d\n", x);
    printf("y = %d\n", y);
    printf("x * y = %d\n", x * y);
    printf("x * y = %ld\n", (long)(x * y));
    printf("x * y = %ld\n", (long)(x) * y);
    return 0;
}

你会看到你应该做什么。

【讨论】:

  • 感谢您的回复。您的建议肯定有助于解决我的代码的另一个潜在问题。但是,原来的问题仍然存在。请参阅更新后的文本了解更多详情。
  • 您需要更改您的程序以在适当的情况下使用off_tsize_t。在启用警告的情况下编译它,并修复所有关于丢失数据的警告,以将结果存储到更窄的类型而不进行强制转换。 (我忘记是否有这样的警告,但希望如此)。快速&肮脏的解决方案可能是将每个 int 更改为 long,如果这不会影响它需要读取的任何二进制数据。
  • @user2185422:块 524288 正好是十六进制的 0x80000。将其乘以 4096,您就会发现问题所在。
  • 是的,我试过你的方法。 ND_file.seekg((long)(block_number*DISK_BLOCK_SIZE) )。但是从输出中,您可以看到当我尝试访问块 174 时出现了问题。对于块 524283,这个 174 给出了正确的结果。读取函数将父块 ID 与块大小相乘。我的观点是它可能是 read() 函数。我正在请求一个可以处理任何文件大小的库函数。不确定 seekg() 和 read() 是否可以做到。
  • @user2185422:这是错误的方式。将整个操作转换为 long 不会改变任何事情。我们正在讨论 NewBlockId 等于 524288 的行。
猜你喜欢
  • 2012-12-02
  • 1970-01-01
  • 1970-01-01
  • 2011-04-18
  • 2011-02-20
  • 2013-08-29
  • 2014-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多