2012-12-12 33 views
8

Tôi đã cố gắng tìm ra một cách để giải quyết một số thiếu sót của các ràng buộc HDF5 C++. Hiện nay, mã của tôi là rải rác với khối try/catch tương tự như sau:Cách tốt hơn để mở các tệp HDF5 trong C++

H5::Exception::dontPrint(); 
H5::H5File *file = NULL; 
try { 
    file = new H5::H5File(fname.c_str(), H5F_ACC_RDWR); 
} catch(H5::FileIException &file_exists_err) { 
    file = new H5::H5File(fname.c_str(), H5F_ACC_TRUNC); 
} 

này không phải là cần thiết - tất cả tôi muốn làm là để mở một tập tin để truy cập đọc/ghi, và nếu nó doesn không tồn tại, để tạo ra nó. Một vấn đề phức tạp khác là tạo một nhóm lồng nhau (ví dụ: "/ parent/group"), nơi nhóm cha không nhất thiết tồn tại. Trong Unix/Linux, tương đương sẽ là

mkdir -p parent/group 

Tuy nhiên, trong các ràng buộc HDF5 C++, tạo nhóm có nhóm gốc không tồn tại tăng ngoại lệ.

Vì những lý do này, tôi đã có động lực để tạo một tệp tiêu đề liên quan đến một số vấn đề thường gặp này. Ý tưởng đầu tiên của tôi là tạo một tập hợp các hàm, ví dụ, lấy tên tệp và chế độ truy cập và trả về đối tượng H5 :: H5File hoặc lấy tên nhóm và trả về một đối tượng nhóm. Tuy nhiên, tôi nghĩ điều này ít lý tưởng vì nó để lại lập trình viên sử dụng tệp tiêu đề này để gọi "xóa" trên các đối tượng được trả về, mặc dù lập trình viên không bao giờ gọi một cách rõ ràng "mới" trong mã riêng của họ. Điều này dường như yêu cầu rò rỉ bộ nhớ. Do đó, ý tưởng thứ hai của tôi là tạo ra một tập hợp các lớp dẫn xuất từ ​​H5 :: H5File và H5 :: H5Group, với các nhà xây dựng không ném ngoại lệ khi tệp chưa tồn tại hoặc khi nhóm cha của nhóm chưa tồn tại. Nỗ lực của tôi đối với lớp tệp dẫn xuất như sau:

namespace H5Utils { 

class H5File : public H5::H5File { 
public: 
    H5File(std::string fname); 
    ~H5File(); 
}; 

} 

H5Utils::H5File::H5File(std::string fname) 
try : H5::H5File(fname.c_str(), H5F_ACC_RDWR) 
{ 
    std::cerr << "Opened existing file." << std::endl; 
} catch(H5::FileIException &file_exists_err) { 
    std::cerr << "File does not exist. Creating new file." << std::endl; 
    H5::H5File(fname.c_str(), H5F_ACC_TRUNC); 
} 

H5Utils::H5File::~H5File() { } 

Sự cố mà tôi đang gặp phải là gấp đôi. Đầu tiên, khối try/catch trong hàm tạo lại ném ngoại lệ được tạo bởi

H5::H5File(fname.c_str(), H5F_ACC_RDWR) 

khi tệp không tồn tại, vì vậy chương trình vẫn chấm dứt. Vấn đề thứ hai là tôi không chắc chắn rằng các nhà xây dựng thứ hai,

H5::H5File(fname.c_str(), H5F_ACC_TRUNC); 

là đúng (tức là nó xây dựng các tầng lớp phụ huynh?) Có cách nào để có những ngoại lệ lớp bắt nguồn gốc trong lớp cơ sở constructor , và sau đó gọi một hàm tạo khác cho lớp cơ sở?

Nói chung, bất cứ ai cũng có thể nghĩ ra cách tốt hơn/thanh lịch hơn để đối phó với những thiếu sót này của liên kết HDF5 C++?

+0

"Một vấn đề phức tạp hơn là tạo nhóm lồng nhau (ví dụ"/parent/group "), nơi nhóm mẹ không nhất thiết tồn tại. Trong Unix/Linux, tương đương sẽ là .. "- Bạn đã bao giờ tìm ra cách tốt đẹp để làm điều này? –

+2

Nếu bạn được đặt tên nhóm lồng nhau, như "/ parent/group/subgroup", trước tiên hãy chia nó thành "/ parent", "/ parent/group" và "/ parent/group/subgroup", sau đó cố mở từng cái theo thứ tự. Nếu một nhóm đã cho không tồn tại (trong C++ API, bạn sẽ nhận được một 'H5 :: FileIException'), tạo nó. Tôi đã viết lên [một số hàm trợ giúp để giải quyết vấn đề này] (https://github.com/gregreen/h5utils/blob/master/src/h5utils.cpp#L92). – Thucydides411

+0

Đã xảy ra sự cố tương tự gần đây http://stackoverflow.com/questions/35668056/test-group-existence-in-hdf5-c. Không có giải pháp. Trên hết, tôi chỉ lưu ý rằng H5 :: Ngoại lệ không xuất phát từ std :: exception ...? – eudoxos

Trả lời

8

Tôi thích ý tưởng ban đầu của bạn về việc tạo một số hàm trợ giúp đơn giản - nó sẽ đơn giản hơn và giảm thiểu số lượng mã bạn sẽ phải viết và ghi lại. Ngoài ra, để đảm bảo quản lý bộ nhớ phù hợp, bạn có thể sử dụng shared_ptr.

Dưới đây là một chức năng wrapper đơn giản tương đương với ví dụ đầu tiên của bạn:

// a typedef for our managed H5File pointer 
typedef std::shared_ptr<H5::H5File> H5FilePtr; 

// create or open a file 
H5FilePtr create_or_open(const std::string& fname) 
{ 
    H5::Exception::dontPrint(); 
    H5::H5File* file = 0; 

    try { 
     file = new H5::H5File(fname.c_str(), H5F_ACC_RDWR); 
    } catch(const H5::FileIException&) { 
     file = new H5::H5File(fname.c_str(), H5F_ACC_TRUNC); 
    } 

    return H5FilePtr(file); 
} 
3

Tuy nhiên, trong các ràng buộc HDF5 C++, tạo ra một nhóm có mẹ nhóm không tồn tại đặt ra một ngoại lệ.

Bạn có thể đặt danh sách thuộc tính tạo liên kết thành create missing intermediate groups và tránh ngoại lệ này.Ví dụ:

#include "hdf5.h" 

int main (void){ 
    hid_t lcpl, file_id, group_id; 
    herr_t status; 
    unsigned flag=1; 

    lcpl = H5Pcreate(H5P_LINK_CREATE); 
    status = H5Pset_create_intermediate_group(lcpl, flag); 
    file_id = H5Fcreate("nested_groups.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); 
    group_id = H5Gcreate(file_id, "/foo/bar/bop", lcpl, H5P_DEFAULT, H5P_DEFAULT); 

    H5Pclose(lcpl); 
    H5Gclose(group_id); 
    H5Fclose(file_id); 

    return status; 
} 
+0

Đây là một đối số khác để sử dụng API C, ngay cả khi viết bằng C++. Rất nhiều chức năng bị thiếu trong C++ API hướng đối tượng, và một số lựa chọn thiết kế, như ném ngoại lệ thay vì thiết lập cờ, khá khó chịu. – Thucydides411

Các vấn đề liên quan