如何在 C++ 中读取 NetCDF "global attribute"
How to read NetCDF "global attribute" in C++
这是我的第一个问题:
我正在尝试从 NetCDF 文件中读取 "global attributes"(使用旧版 C++ API)。 "global attribute" 我的意思是添加到 NcFile 而不是 NcVar 的属性。
对于大多数情况,“Example netCDF programs”很有用——但没有 "global attributes".
的示例
咨询 "netcdfcpp.h" 我发现了一些事情:
- NcFile 有一个成员函数:
NcAtt* get_att(NcToken) const;
- NcAtt 没有 public 构造函数
- NcAtt 是 NcFile 的好友:
friend class NcFile;
- NcAtt 有一个私有构造函数:
NcAtt( NcFile*, NcToken);
- NcAtt 有一个 public 成员函数
NcValues* values( void ) const;
- NcValues 有一个 API 通过
ncvalues.h
header 定义
我的编码技能不足以理解我如何返回存储为 NcValue 的 string/int/float,在 NcFile 中的 NcAtt class 中。
附件是我的问题 "NetCDF_test.cpp" 的示例代码,"LoadNetCDF" 函数的实现中缺少关键部分。
代码编译正常:(编辑:另外,"TestFile.nc" 已正确创建)
g++ -c NetCDF_test.cpp -o NetCDF_test.o
g++ -o NCTEST NetCDF_test.o -lnetcdf_c++ -lnetcdf
示例代码:
#include <iostream> // provides screen output (i.e. std::cout<<)
#include <netcdfcpp.h>
struct MyStructure {
std::string MyString;
int MyInt;
float MyFloat;
MyStructure(); // default constructor
int SaveNetCDF(std::string); // Save the struct content to "global attributes" in NetCDF
int LoadNetCDF(std::string); // Load the struct content from "global attributes" in NetCDF
};
MyStructure::MyStructure(void)
{
MyString = "TestString";
MyInt = 123;
MyFloat = 1.23;
}
int MyStructure::SaveNetCDF(std::string OUTPUT_FILENAME)
{
NcError err(NcError::silent_nonfatal);
static const int NC_ERR = 2;
NcFile NetCDF_File(OUTPUT_FILENAME.c_str(), NcFile::Replace);
if(!NetCDF_File.is_valid()) {return NC_ERR;}
if(!(NetCDF_File.add_att("MyString",MyString.c_str()))) {return NC_ERR;}
if(!(NetCDF_File.add_att("MyInt",MyInt))) {return NC_ERR;}
if(!(NetCDF_File.add_att("MyFloat",MyFloat))) {return NC_ERR;}
return 0;
}
int MyStructure::LoadNetCDF(std::string INPUT_FILENAME)
{
NcError err(NcError::silent_nonfatal);
static const int NC_ERR = 2;
NcFile NetCDF_File(INPUT_FILENAME.c_str(), NcFile::ReadOnly);
if(!NetCDF_File.is_valid()) {return NC_ERR;}
// ???? This is where I am stuck.
// How do I read the global attribute from the NetCDF_File ??
return 0;
}
int main()
{
std::cout<< "START OF TEST.\n";
MyStructure StructureInstance; // datamembers initialized by constructor
StructureInstance.SaveNetCDF("TestFile.nc");
StructureInstance.MyString = "Change string for sake of testing";
StructureInstance.MyInt = -987;
StructureInstance.MyFloat = -9.87;
StructureInstance.LoadNetCDF("TestFile.nc"); // data members are supposed to be read from file
std::cout<< "Now the data members of StructureInstance should be TestString, 123, and 1.23\n";
std::cout<< StructureInstance.MyString << " ; " << StructureInstance.MyInt << " ; " << StructureInstance.MyFloat <<"\n";
std::cout<< "END OF TEST.\n";
}
C++ 用户指南中的说明非常清楚:http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx/Class-NcAtt.html#Class-NcAtt
"Because attributes are only associated with open netCDF files, there are no public constructors for this class. Use member functions of NcFile and NcVar to get netCDF attributes or add new attributes."
全局属性是文件的属性(与变量属性相反,变量属性是变量的属性)
NetCDF_File.num_atts() returns 有多少全局属性。 get_att() 方法(以各种方式重载)将为您提供一个属性。
咨询http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx/Class-NcFile.html#Class-NcFile
非常感谢 Rob Latham 提供指向 NetCDF API(旧版 C++)的注释描述的链接。根据那里提供的信息,我能够弄清楚:
NcAtt
固有形式 NcTypedComponent
一组成员函数,用于访问存储在给定 NcAtt
中的数据:(int n == n-th element)
ncbyte as_ncbyte( int n ) const
char as_char( int n ) const
short as_short( int n ) const
int as_int( int n ) const
nclong as_nclong( int n ) const // deprecated
long as_long( int n ) const
float as_float( int n ) const
double as_double( int n ) const
char* as_string( int n ) const
但是,NcAtt 的构造函数仍然是私有的,并且对现有 NcAtt 的唯一访问点是通过 NcFile 成员函数 NcVar* get_var(NcToken name) const
——它只有 returns 一个指针。因此直接使用是行不通的:
int MyInt = MyNcFile.get_att("MyInt").as_int(0); // DOES NOT COMPILE
但是,取消引用 get_att
返回的指针就可以了。
int MyInt = (*MyNcFile.get_att("MyInt")).as_int(0); // WORKS
为了完整起见,我在下面包含了 MyStructure::LoadNetCDF
的实现,作为我最初问题的示例代码。
int MyStructure::LoadNetCDF(std::string INPUT_FILENAME)
{
NcError err(NcError::silent_nonfatal);
static const int NC_ERR = 2;
NcFile NetCDF_File(INPUT_FILENAME.c_str(), NcFile::ReadOnly);
if(!NetCDF_File.is_valid()) {return NC_ERR;}
// NcAtt constructor is private, but one can obtain the pointer to an existing NcAtt
NcAtt* PointerToMyIntNcAtt = NetCDF_File.get_att("MyInt");
// Now, using the dereferencing operator one has access to the member functions that NcAtt inherents from NcTypedComponent
if(!(*PointerToMyIntNcAtt).is_valid()) {return NC_ERR;}
std::cout<< "Is MyInt a valid NcAtt? "<< (*PointerToMyIntNcAtt).is_valid()<<"\n";
// The concise way of writing the access to NetCDF "global attributes"" of type int/float/string
MyInt = (*NetCDF_File.get_att("MyInt")).as_int(0);
MyFloat = (*NetCDF_File.get_att("MyFloat")).as_float(0);
MyString = (*NetCDF_File.get_att("MyString")).as_string(0);
return 0;
}
这是我的第一个问题:
我正在尝试从 NetCDF 文件中读取 "global attributes"(使用旧版 C++ API)。 "global attribute" 我的意思是添加到 NcFile 而不是 NcVar 的属性。
对于大多数情况,“Example netCDF programs”很有用——但没有 "global attributes".
的示例咨询 "netcdfcpp.h" 我发现了一些事情:
- NcFile 有一个成员函数:
NcAtt* get_att(NcToken) const;
- NcAtt 没有 public 构造函数
- NcAtt 是 NcFile 的好友:
friend class NcFile;
- NcAtt 有一个私有构造函数:
NcAtt( NcFile*, NcToken);
- NcAtt 有一个 public 成员函数
NcValues* values( void ) const;
- NcValues 有一个 API 通过
ncvalues.h
header 定义
我的编码技能不足以理解我如何返回存储为 NcValue 的 string/int/float,在 NcFile 中的 NcAtt class 中。
附件是我的问题 "NetCDF_test.cpp" 的示例代码,"LoadNetCDF" 函数的实现中缺少关键部分。
代码编译正常:(编辑:另外,"TestFile.nc" 已正确创建)
g++ -c NetCDF_test.cpp -o NetCDF_test.o
g++ -o NCTEST NetCDF_test.o -lnetcdf_c++ -lnetcdf
示例代码:
#include <iostream> // provides screen output (i.e. std::cout<<)
#include <netcdfcpp.h>
struct MyStructure {
std::string MyString;
int MyInt;
float MyFloat;
MyStructure(); // default constructor
int SaveNetCDF(std::string); // Save the struct content to "global attributes" in NetCDF
int LoadNetCDF(std::string); // Load the struct content from "global attributes" in NetCDF
};
MyStructure::MyStructure(void)
{
MyString = "TestString";
MyInt = 123;
MyFloat = 1.23;
}
int MyStructure::SaveNetCDF(std::string OUTPUT_FILENAME)
{
NcError err(NcError::silent_nonfatal);
static const int NC_ERR = 2;
NcFile NetCDF_File(OUTPUT_FILENAME.c_str(), NcFile::Replace);
if(!NetCDF_File.is_valid()) {return NC_ERR;}
if(!(NetCDF_File.add_att("MyString",MyString.c_str()))) {return NC_ERR;}
if(!(NetCDF_File.add_att("MyInt",MyInt))) {return NC_ERR;}
if(!(NetCDF_File.add_att("MyFloat",MyFloat))) {return NC_ERR;}
return 0;
}
int MyStructure::LoadNetCDF(std::string INPUT_FILENAME)
{
NcError err(NcError::silent_nonfatal);
static const int NC_ERR = 2;
NcFile NetCDF_File(INPUT_FILENAME.c_str(), NcFile::ReadOnly);
if(!NetCDF_File.is_valid()) {return NC_ERR;}
// ???? This is where I am stuck.
// How do I read the global attribute from the NetCDF_File ??
return 0;
}
int main()
{
std::cout<< "START OF TEST.\n";
MyStructure StructureInstance; // datamembers initialized by constructor
StructureInstance.SaveNetCDF("TestFile.nc");
StructureInstance.MyString = "Change string for sake of testing";
StructureInstance.MyInt = -987;
StructureInstance.MyFloat = -9.87;
StructureInstance.LoadNetCDF("TestFile.nc"); // data members are supposed to be read from file
std::cout<< "Now the data members of StructureInstance should be TestString, 123, and 1.23\n";
std::cout<< StructureInstance.MyString << " ; " << StructureInstance.MyInt << " ; " << StructureInstance.MyFloat <<"\n";
std::cout<< "END OF TEST.\n";
}
C++ 用户指南中的说明非常清楚:http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx/Class-NcAtt.html#Class-NcAtt
"Because attributes are only associated with open netCDF files, there are no public constructors for this class. Use member functions of NcFile and NcVar to get netCDF attributes or add new attributes."
全局属性是文件的属性(与变量属性相反,变量属性是变量的属性)
NetCDF_File.num_atts() returns 有多少全局属性。 get_att() 方法(以各种方式重载)将为您提供一个属性。
咨询http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx/Class-NcFile.html#Class-NcFile
非常感谢 Rob Latham 提供指向 NetCDF API(旧版 C++)的注释描述的链接。根据那里提供的信息,我能够弄清楚:
NcAtt
固有形式 NcTypedComponent
一组成员函数,用于访问存储在给定 NcAtt
中的数据:(int n == n-th element)
ncbyte as_ncbyte( int n ) const
char as_char( int n ) const
short as_short( int n ) const
int as_int( int n ) const
nclong as_nclong( int n ) const // deprecated
long as_long( int n ) const
float as_float( int n ) const
double as_double( int n ) const
char* as_string( int n ) const
但是,NcAtt 的构造函数仍然是私有的,并且对现有 NcAtt 的唯一访问点是通过 NcFile 成员函数 NcVar* get_var(NcToken name) const
——它只有 returns 一个指针。因此直接使用是行不通的:
int MyInt = MyNcFile.get_att("MyInt").as_int(0); // DOES NOT COMPILE
但是,取消引用 get_att
返回的指针就可以了。
int MyInt = (*MyNcFile.get_att("MyInt")).as_int(0); // WORKS
为了完整起见,我在下面包含了 MyStructure::LoadNetCDF
的实现,作为我最初问题的示例代码。
int MyStructure::LoadNetCDF(std::string INPUT_FILENAME)
{
NcError err(NcError::silent_nonfatal);
static const int NC_ERR = 2;
NcFile NetCDF_File(INPUT_FILENAME.c_str(), NcFile::ReadOnly);
if(!NetCDF_File.is_valid()) {return NC_ERR;}
// NcAtt constructor is private, but one can obtain the pointer to an existing NcAtt
NcAtt* PointerToMyIntNcAtt = NetCDF_File.get_att("MyInt");
// Now, using the dereferencing operator one has access to the member functions that NcAtt inherents from NcTypedComponent
if(!(*PointerToMyIntNcAtt).is_valid()) {return NC_ERR;}
std::cout<< "Is MyInt a valid NcAtt? "<< (*PointerToMyIntNcAtt).is_valid()<<"\n";
// The concise way of writing the access to NetCDF "global attributes"" of type int/float/string
MyInt = (*NetCDF_File.get_att("MyInt")).as_int(0);
MyFloat = (*NetCDF_File.get_att("MyFloat")).as_float(0);
MyString = (*NetCDF_File.get_att("MyString")).as_string(0);
return 0;
}