C++ 使用fstream加载二进制文件
我正试图通过以下方式使用C++ 使用fstream加载二进制文件,c++,stl,file-io,filestream,fstream,C++,Stl,File Io,Filestream,Fstream,我正试图通过以下方式使用fstream加载二进制文件: #include <iostream> #include <fstream> #include <iterator> #include <vector> using namespace std; int main() { basic_fstream<uint32_t> file( "somefile.dat", ios::in|ios::binary ); vector<uint32
fstream
加载二进制文件:
#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>
using namespace std;
int main()
{
basic_fstream<uint32_t> file( "somefile.dat", ios::in|ios::binary );
vector<uint32_t> buffer;
buffer.assign( istream_iterator<uint32_t, uint32_t>( file ), istream_iterator<uint32_t, uint32_t>() );
cout << buffer.size() << endl;
return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main()
{
基本流文件(“somefile.dat”,ios::in | ios::binary);
向量缓冲区;
assign(istream_迭代器(文件),istream_迭代器());
cout主要问题可能是您所说的“二进制文件”是什么意思。ios::binary
只确保istream
对象不会用“\n”替换特定于平台的换行符。其他什么都没有。这对您来说够了吗
istream\u迭代器
基本上只是调用运算符>>
的一种奇特方式。如果流中有真实的二进制数据,则会失败。文件中是否有真实的二进制数据?或者整数是否存储为字符串
如果您需要读取实二进制整数,您需要的是istream.read()
或直接使用流缓冲区对象。您可以重新加载运算符>>以正确读取整数。当然,它只需读取()4个字节。但所有其他运算符>>最终都会这样做
下面是一个示例(无错误检查,假设endianess与当前编译器使用的相同,等等)
为您自己的整数风格定制(可能需要一次读取一个字节并进行移位赋值,如果您不知道字节顺序,请在十六进制编辑器中查看文件),添加错误检查,您应该能够使用现有代码
编辑:啊,是的,确保这个stl操作符读取整数——可能必须从您正在使用的流派生您自己的类,并使用它而不是std::istream&in,这样编译器才知道首先检查谁
istream\u迭代器
希望basic\u istream
作为参数
在basic\u istream
类中不可能重载operator>
定义全局运算符>>
将导致编译时与类成员运算符>>
冲突
您可以为类型uint32\u t
专门化basic\u istream
。但是对于专门化,您应该重写basic\u istream
类的所有函数。相反,您可以定义虚拟类x
并为其专门化basic\u istream
,如下代码所示:
使用名称空间std;
结构x{};
名称空间标准{
模板
类基本流:公共基本流
{
公众:
显式基本流(常量wchar\u t*\u文件名,
ios_base::openmode_模式,
int _Prot=(int)ios_base::_Openprot):基本的_ifstream(_Filename,_Mode,_Prot){}
基本流和操作员>>(uint32测试和数据)
{
读取(和数据,1);
归还*这个;
}
};
}//名称空间std
int main()
{
基本istream文件(“somefile.dat”,ios::in | ios::binary);
向量缓冲区;
assign(istream_迭代器(文件),istream_迭代器());
可以用另一种方式来做与Alexey Malistov的回答相同的事情:
#include <fstream>
#include <iterator>
#include <vector>
#include <iostream>
struct rint // this class will allow us to read binary
{
// ctors & assignment op allows implicit construction from uint
rint () {}
rint (unsigned int v) : val(v) {}
rint (rint const& r) : val(r.val) {}
rint& operator= (rint const& r) { this->val = r.val; return *this; }
rint& operator= (unsigned int r) { this->val = r; return *this; }
unsigned int val;
// implicit conversion to uint from rint
operator unsigned int& ()
{
return this->val;
}
operator unsigned int const& () const
{
return this->val;
}
};
// reads a uints worth of chars into an rint
std::istream& operator>> (std::istream& is, rint& li)
{
is.read(reinterpret_cast<char*>(&li.val), 4);
return is;
}
// writes a uints worth of chars out of an rint
std::ostream& operator<< (std::ostream& os, rint const& li)
{
os.write(reinterpret_cast<const char*>(&li.val), 4);
return os;
}
int main (int argc, char *argv[])
{
std::vector<int> V;
// make sure the file is opened binary & the istream-iterator is
// instantiated with rint; then use the usual copy semantics
std::ifstream file(argv[1], std::ios::binary | std::ios::in);
std::istream_iterator<rint> iter(file), end;
std::copy(iter, end, std::back_inserter(V));
for (int i = 0; i < V.size(); ++i)
std::cout << std::hex << "0x" << V[i] << std::endl;
// this will reverse the binary file at the uint level (on x86 with
// g++ this is 32-bits at a time)
std::ofstream of(argv[2], std::ios::binary | std::ios::out);
std::ostream_iterator<rint> oter(of);
std::copy(V.rbegin(), V.rend(), oter);
return 0;
}
#包括
#包括
#包括
#包括
struct rint//这个类允许我们读取二进制文件
{
//CTOR和赋值op允许从uint隐式构造
rint(){}
rint(无符号整数v):val(v){
rint(rint const&r):val(r.val){}
rint&operator=(rint const&r){this->val=r.val;返回*this;}
rint&operator=(无符号int r){this->val=r;返回*this;}
无符号int-val;
//从rint到uint的隐式转换
运算符unsigned int&()
{
返回此->val;
}
运算符unsigned int const&()const
{
返回此->val;
}
};
//将一个单位的字符读入一个指纹
std::istream&operator>>(std::istream&is、rint&li)
{
is.read(重新解释铸型(&li.val),4);
回报是;
}
//从一个打印中写出一个单位的字符
std::ostream&operator有真正的二进制数据,而不是文本。主要问题是“为什么它不起作用”。我已经向istream_迭代器指出,我有uint32_t数据,而不是char(第二个模板参数)。是的,重载>>来读取sizeof(uint32_t)字节。根据写文件的人和方式,您可能还需要修复endianess。@Eugene,您可以发布一些示例吗?我认为运算符重载是不够的。“如果您需要读取实二进制整数,您需要的是istream.read()或直接使用流缓冲区对象。”发布的示例。确实没有自动的方法来跟踪这些注释线程,是吗?istream迭代器
使用basic\u istream
作为参数,所以我不能仅仅继承basic\u ifstream
并重写操作符>
。这正是我需要的。请注意,在专门研究uint32\t您实际上是专门处理一个基本类型,或者unsigned int
或者(不太可能)unsigned long
typedef
不生成通过模板(或者实际上通过C++中的任何其他类型重载)区分的类型所述二进制数据的来源是什么?二进制数据可以是图像或类似的东西。
using namespace std;
struct x {};
namespace std {
template<class traits>
class basic_istream<x, traits> : public basic_ifstream<uint32_t>
{
public:
explicit basic_istream<x, traits>(const wchar_t* _Filename,
ios_base::openmode _Mode,
int _Prot = (int)ios_base::_Openprot) : basic_ifstream<uint32_t>( _Filename, _Mode, _Prot ) {}
basic_istream<x, traits>& operator>>(uint32_t& data)
{
read(&data, 1);
return *this;
}
};
} // namespace std
int main()
{
basic_istream<x> file( "somefile.dat", ios::in|ios::binary );
vector<uint32_t> buffer;
buffer.assign( istream_iterator<uint32_t, x>( file ), istream_iterator<uint32_t, x>() );
cout << buffer.size() << endl;
return 0;
}
#include <fstream>
#include <iterator>
#include <vector>
#include <iostream>
struct rint // this class will allow us to read binary
{
// ctors & assignment op allows implicit construction from uint
rint () {}
rint (unsigned int v) : val(v) {}
rint (rint const& r) : val(r.val) {}
rint& operator= (rint const& r) { this->val = r.val; return *this; }
rint& operator= (unsigned int r) { this->val = r; return *this; }
unsigned int val;
// implicit conversion to uint from rint
operator unsigned int& ()
{
return this->val;
}
operator unsigned int const& () const
{
return this->val;
}
};
// reads a uints worth of chars into an rint
std::istream& operator>> (std::istream& is, rint& li)
{
is.read(reinterpret_cast<char*>(&li.val), 4);
return is;
}
// writes a uints worth of chars out of an rint
std::ostream& operator<< (std::ostream& os, rint const& li)
{
os.write(reinterpret_cast<const char*>(&li.val), 4);
return os;
}
int main (int argc, char *argv[])
{
std::vector<int> V;
// make sure the file is opened binary & the istream-iterator is
// instantiated with rint; then use the usual copy semantics
std::ifstream file(argv[1], std::ios::binary | std::ios::in);
std::istream_iterator<rint> iter(file), end;
std::copy(iter, end, std::back_inserter(V));
for (int i = 0; i < V.size(); ++i)
std::cout << std::hex << "0x" << V[i] << std::endl;
// this will reverse the binary file at the uint level (on x86 with
// g++ this is 32-bits at a time)
std::ofstream of(argv[2], std::ios::binary | std::ios::out);
std::ostream_iterator<rint> oter(of);
std::copy(V.rbegin(), V.rend(), oter);
return 0;
}