【问题标题】:Reading in 4 bytes at a time一次读取 4 个字节
【发布时间】:2010-06-07 02:53:36
【问题描述】:

我有一个充满整数的大文件正在加载。我刚刚开始使用 C++,并且正在尝试使用文件流的东西。从我读过的所有内容来看,我似乎只能以字节为单位读取,所以我必须设置一个 char 数组,然后将其转换为 int 指针。

有没有一种方法可以一次读取 4 个字节,并且不需要 char 数组?

const int HRSIZE = 129951336;  //The size of the table
char bhr[HRSIZE];   //The table
int *dwhr;

int main()
{
    ifstream fstr;

    /* load the handranks.dat file */
    std::cout << "Loading table.dat...\n";
    fstr.open("table.dat");
    fstr.read(bhr, HRSIZE);
    fstr.close();
    dwhr = (int *) bhr;    
}

【问题讨论】:

  • 那么你的“充满整数的大文件”实际上是以二进制形式存储的吗?您是否考虑了字节序?

标签: c++


【解决方案1】:

要读取单个整数,请将整数的地址传递给 read 函数,并确保您只读取 sizeof int 字节。

int myint;

//...

fstr.read(reinterpret_cast<char*>(&myint), sizeof(int));

您可能还需要以二进制模式打开文件

fstr.open("table.dat", std::ios::binary);

【讨论】:

  • @Daniel: reinterpret_cast 并不比 C 风格的演员“更安全”。
  • 运行时同样安全,但在截止日期前的周日晚上阅读代码更安全。
  • 如果你想读取原始整数,你需要处理字节序问题。一种技术是以网络字节序存储,这意味着您在写入之前使用htonl,在阅读之后使用ntohl
【解决方案2】:

要从ifstream 读取4 个字节,您可以重载operator&gt;&gt;,如下所示(它实际上是basic_istream 类模板的部分特化,因此istream_iterator 可以从中使用operator&gt;&gt;。类basic_ifstream此处用于继承所有输入文件流功能):

#include <fstream>

typedef unsigned int uint32_t;    
struct uint32_helper_t {};

namespace std {
template<class traits>
class basic_istream<uint32_helper_t, traits> : public basic_ifstream<uint32_t> {
public:
    explicit basic_istream<uint32_helper_t, traits>(const char* filename, 
        ios_base::openmode mode ) : basic_ifstream<uint32_t>( filename, mode ) {}

    basic_istream<uint32_helper_t, traits>& operator>>(uint32_t& data) {
        read(&data, 1);
        return *this;
    }
};
} // namespace std {}

那么你可以通过以下方式使用它:

std::basic_istream<uint32_helper_t> my_file( FILENAME, std::ios::in|std::ios::binary );
// read one int at a time
uint32_t value;
my_file >> value;

// read all data in file
std::vector<uint32_t> data;
data.assign( std::istream_iterator<uint32_t, uint32_helper_t>(my_file),
  std::istream_iterator<uint32_t, uint32_helper_t>() );

【讨论】:

  • @camh,代码解释了这个想法。我们在这里为我们的类型重载operator&gt;&gt;。然后在第一种情况下显式使用它,在第二种情况下隐式使用它。哪一部分不清楚?
  • 那里不仅仅是一个重载的运算符。我不明白为什么你的 basic_istream 继承自 basic_ifstream。它也无法编译 (g++ 4.4.4)。
  • @camh,我在回答中添加了额外的解释。我已经做了一些修复以使其更符合要求。希望这会有所帮助。
  • 好的。我已经删除了-1。问题一定出在我脑子里的某个地方。我不明白 basic_istream 如何从 basic_ifstream 继承,因为 basic_ifstream 已经从 basic_istream 继承。
  • 诀窍在于这是basic_istream模板类的部分特化,而不是标准的basic_istream
【解决方案3】:

你可以做到:

int i;
fstr.read((int*)&i, sizeof(int));

【讨论】:

  • 这会引发以下错误 -> 'error: no matching function for call to 'std::basic_ifstream::read(int*, long unsigned int)' f.read((int *)&i, sizeof(int));'
【解决方案4】:

这是你的意思吗?顺便说一句,您的代码(和这个)假定数据的本机字节顺序。

const int HRSIZE = 129951336;  //The size of the table
int dhr[HRSIZE/sizeof(int)];   //The table

int main()
{
    ifstream fstr;

    /* load the handranks.dat file */
    std::cout << "Loading table.dat...\n";
    fstr.open("table.dat");
    fstr.read((char*)dhr, HRSIZE);
    fstr.close();
}

【讨论】:

    【解决方案5】:

    你可以试试这个:

    const int HRSIZE = 129951336/sizeof(int);  //The size of the table
    int bhr[HRSIZE];   //The table
    
    int main(int argc, char *argv[])
    {
        ifstream fstr;
    
        /* load the handranks.dat file */
        std::cout << "Loading table.dat...\n";
        fstr.open("table.dat");
        for (int i=0; i<HRSIZE; ++i)
        {
            fstr.read((char *)(bhr+i), sizeof(int));
        }
        fstr.close();
    
        // for correctness
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-11
      • 2017-04-14
      • 2015-10-25
      • 2010-10-30
      • 2012-07-15
      相关资源
      最近更新 更多