问题描述
||
我有一个无符号的16 \矩阵,正在使用以下命令将其写到文本文件中
void output() {
ofstream myfile;
myfile.open(\"output.raw\",ios::out | ios::binary);
for(int i=0; i< 100; i++) {
for(int j=0; j < 100; j++) {
myfile.write((char*)&r2[i][j],sizeof(uint16_t));
}
}
}
因为这是一个\ .raw \图像文件,所以我认为每个uint16应该只是连续写入该文件中,而不会造成任何中断(如果我错了,请更正我)。
当我读回数据时,该数组包含的值与输入文本文件中的值不同。我正在读回数据:
for(int i=0; i<NUM_COLS; i++) {
for(int j=0; j<NUM_ROWS; j++) {
fread(&q1[j][i],sizeof(uint16_t),1,fp);
}
}
为什么会这样呢?
解决方法
您不能按位写入浮点数据,也不能将其读为int。在编写浮点数之前,必须将其转换为整数数据类型。浮点数具有完全不同的二进制表示形式:IEEE_754
for(int i=0; i< 100; i++) {
for(int j=0; j < 100; j++) {
uint16_t val = (uint16_t)r2[i][j];
myfile.write((char*)&val,sizeof(uint16_t));
}
}
您还会以错误的顺序读回这些值:
fread(&q1[j][i],sizeof(uint16_t),1,fp);
应该
fread(&q1[i][j],fp); // i and j interchanged
, 只是为了好玩,我写了这些通用助手来将任意二维数组写入二进制流:
namespace arraystream
{
template <class T,size_t M> std::istream& operator>>(std::istream& is,const T (&t)[M])
{ return is.read ((char*) t,M*sizeof(T)); }
template <class T,size_t M> std::ostream& operator<<(std::ostream& os,const T (&t)[M])
{ return os.write((char*) t,M*sizeof(T)); }
template <class T,size_t N,const T (&tt)[N][M])
{ for (size_t i=0; i<N; i++) is >> tt[i]; return is; }
template <class T,const T (&tt)[N][M])
{ for (size_t i=0; i<N; i++) os << tt[i]; return os; }
}
您可以在代码中像这样使用它们:
char c [23] [5];
float f [7] [100];
uint16_t r2[100][100]; // yes that too
std::ofstream ofs(\"output.raw\",std::ios::binary || std::ios::out);
ofs << c << f << r2;
ofs.flush();
ofs.close();
////
std::ifstream ifs(\"output.raw\",std::ios::binary || std::ios::in);
ifs >> c >> f >> r2;
ifs.close();
唯一的次要缺点是,如果要在命名空间std中声明它们(或始终用use
声明),则编译器也会尝试使用这些重载来编写std::cout << \"hello world\"
(即那里的char[12]
)。我选择在需要的地方显式地将“ 7”命名为“ 11”命名空间,请参见下面的完整示例。
这是一个完整的可编译示例,其中显示了一个校验和哈希值,表明读回的数据确实相同。使用这些帮助程序不需要Boost。我使用boost :: random获取一组随机数据,使用boost :: hash进行校验和。您可以使用任何随机数生成器,也可以使用外部校验和工具。
无需再费周折:
#include <fstream>
#include <boost/random.hpp>
#include <boost/functional/hash.hpp>
namespace arraystream
{
template <class T,const T (&t)[M]) { return is.read ((char*) t,const T (&t)[M]) { return os.write((char*) t,const T (&tt)[N][M])
{ for (size_t i=0; i<N; i++) os << tt[i]; return os; }
}
template <class T,size_t M>
size_t hash(const T (&aa)[N][M])
{
size_t seed = 0;
for (size_t i=0; i<N; i++)
boost::hash_combine(seed,boost::hash_range(aa[i],aa[i]+M));
return seed;
}
int main()
{
uint16_t data[100][100];
{
// make some (deterministic noise)
boost::mt19937 rand(0);
for (int i=0; i<100; i++) for (int j=0; j<100; j++) data[i][j] = rand();
}
{
// write a file
std::ofstream ofs;
ofs.open(\"output.raw\",std::ios::out | std::ios::binary);
using namespace arraystream;
ofs << data;
ofs.flush();
ofs.close();
}
uint16_t clone[100][100];
{
// read a file
std::ifstream ifs;
ifs.open(\"output.raw\",std::ios::in | std::ios::binary);
using namespace arraystream;
ifs >> clone;
ifs.close();
}
std::cout << \"data: \" << hash(data) << std::endl;
std::cout << \"clone: \" << hash(clone) << std::endl;
return 0;
}