2013-03-07 82 views
3

我正在编写读取DICOM文件的应用程序,我必须使用其他库来执行此操作。我发现图书馆将打开文件,但完成后不会关闭文件。而图书馆不是开源的。我知道在Linux中打开文件限制是1024,我可以更改数字。但我不想这样做。我喜欢关闭由库打开的文件。如果我知道它正在打开,如何在C中关闭文件。我正在使用从http://cbi.nyu.edu/software/dinifti.php获得的DICOM2NII库。 这是打开文件的代码,但它不会关闭如何关闭已打开的C文件

bool DICOMImage::OpenFile(const char *path) 
{ 
    bool retValue = true; 
    DCM_Objects handle_; 
    unsigned long options = DCM_ORDERLITTLEENDIAN | DCM_FORMATCONVERSION | DCM_VRMASK; 
    // Try opening as PART10, if it fails it's might be bcause it does not have 
    // a preable and the try it that way 
    if (DCM_OpenFile(path, options | DCM_PART10FILE, &handle_) != DCM_NORMAL) 
    { 
     DCM_CloseObject(&handle_); 
     COND_PopCondition(TRUE); 
     if (DCM_OpenFile(path, options, &handle_) != DCM_NORMAL) 
     {  
      retValue = false; 
     } 
     else 
      retValue=true; 
    } 

    return retValue; 
} 
+2

当您完成这些操作后,库是否不提供关闭文件的单独功能? – 2013-03-07 07:15:00

+0

是的。我在这个头文件中找到但没有。这是主要问题 – user2143123 2013-03-07 07:15:50

+0

它看起来像库的来源是可用的(ftp://ftp.erl.wustl.edu/pub/dicom/software/ctn/)。它看起来像'DCM_OpenFile()'可以在文件句柄返回DCM_FILEACCESSERROR错误时泄漏,但只有在调用fstat()失败或者文件大小大于INT_MAX时才会发生。这就是你遇到的情况?)。毫无意义:在我看来'DCM_OpenFile()'命名不好,因为它不仅仅是打开文件(事实上,它通常会在文件完成时关闭文件)。 – 2013-03-07 08:18:42

回答

1

你可以先测试所有文件描述符,看看哪些正在使用的从0每FD做一个虚拟fcntl(fd, F_GETFD)高达getdtablesize()。当库函数返回时,将会有一个更开放的fd,您可以用close()关闭。你也可以在以前没有打开过的所有东西上打电话close(fd),其中一个会成功(你可以在搜索时停止)。

很可能您可以对最初未使用的fd进行初始探测,并且库最终会使用该fd,前提是它不会执行比打开一个文件更复杂的任何操作。如果它打开多个文件或使用dup()它可能会在其他地方结束。

要拼了这一点:

#include <iostream> 
#include <vector> 
#include <unistd.h> 
#include <fcntl.h> 

std::vector<bool> getOpenFileMap() 
{ 
    int limit = getdtablesize(); 
    std::vector<bool> result(limit); 

    for (int fd = 0; fd < limit; ++fd) 
     result[fd] = fcntl(fd, F_GETFD) != -1; 
    return result; 
} 

void closeOpenedFiles(const std::vector<bool> &existing) 
{ 
    int limit = existing.size(); 
    for (int fd = 0; fd < limit; ++fd) 
     if (!existing[fd]) 
      close(fd); 
} 

int getLikelyFd() 
{ 
    int limit = getdtablesize(); 

    for (int fd = 0; fd < limit; ++fd) 
     if (fcntl(fd, F_GETFD) != -1) 
      return fd; 
} 

int main() 
{ 
    std::vector<bool> existing = getOpenFileMap(); 
    int fd = open("/dev/null", O_RDONLY); 
    closeOpenedFiles(existing); 
    bool closed = write(fd, "test", 4) == -1; 
    std::cout << "complex pass " << std::boolalpha << closed << std::endl; 

    int guess = getLikelyFd(); 
    fd = open("/dev/null", O_RDONLY); 
    bool match = fd == guess; 
    std::cout << "simple pass " << std::boolalpha << match << std::endl; 
} 
+0

什么是fd参数。因为在库中函数的返回是不正常的。 #include fcntl(fd,F_GETFD)关闭(fd)。而Kdevelop通知错误:'fd'未在此范围内声明 – user2143123 2013-03-07 07:41:56

+0

@ user2143123:好的,我拼出来了 – 2013-03-07 07:56:33

+0

谢谢。它运作良好。我只使用int guess = getLikelyFd();关闭(猜测); – user2143123 2013-03-07 08:17:37

2

在你DICOMImage类,添加成员

DCM_OBJECT *handle_; 

,并在你的析构函数关闭文件

DICOMImage::DICOMImage() : handle_(0) { ... } 

DICOMImage::~DICOMImage() { 
    if (handle_ != 0) 
     DCM_CloseObject(&handle_); 
} 

,并用这个成员handle_当然在DICOMImage::OpenFile()也是如此。

相关问题