如何阅读NetCDF"全局属性"在C ++中

时间:2015-01-16 16:02:55

标签: c++ netcdf

这是我的第一个问题:

我正在尝试从NetCDF文件中读取“全局属性”(使用C ++遗留API)。 “全局属性”是指添加到NcFile的属性,而不是NcVar。

对于大多数事情,“Example netCDF programs”很有用 - 但“全局属性”没有示例。

咨询“netcdfcpp.h”我发现了一些事情:

  • NcFile有一个成员函数:NcAtt* get_att(NcToken) const;
  • NcAtt没有公共构造函数
  • NcAtt是NcFile的朋友:friend class NcFile;
  • NcAtt有一个私人构造函数:NcAtt( NcFile*, NcToken);
  • NcAtt有一个公共成员函数NcValues* values( void ) const;
  • NcValues具有通过ncvalues.h标题
  • 定义的API

我的编码技巧不足以理解我如何在NcFile中的NcAtt类中返回存储为NcValue的字符串/ int / float。

附件是我的问题“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";
}

2 个答案:

答案 0 :(得分:1)

在C ++用户指南中非常清楚地说明了这一点:http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx/Class-NcAtt.html#Class-NcAtt

&#34;因为属性仅与打开的netCDF文件相关联,所以此类没有公共构造函数。使用NcFile和NcVar的成员函数来获取netCDF属性或添加新属性。&#34;

全局属性是文件的属性(与变量属性相反,而变量属性是变量的属性)

NetCDF_File.num_atts()返回多少个全局属性。 get_att()方法(以各种方式重载)将为您提供属性。

咨询http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-cxx/Class-NcFile.html#Class-NcFile

答案 1 :(得分:1)

非常感谢Rob Latham提供了对NetCDF API(旧版C ++)的注释描述的链接。根据那里给出的信息,我能够弄清楚:

NcAtt inherents形成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 - 它只返回一个指针。因此,直接使用不起作用:

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;
}