3 votes

Comment fermer un fichier en C qui est déjà ouvert

Je suis en train d'écrire une application pour lire des fichiers DICOM et je dois utiliser une autre bibliothèque pour le faire. J'ai remarqué que la bibliothéque ouvre le fichier mais ne le ferme pas à la fin. De plus, cette bibliothèque n'est pas open source. Je sais que la limitation d'ouverture de fichiers est de 1024 sous Linux et que je peux modifier ce nombre. Cependant, je ne veux pas faire de cette façon. Je préfère fermer le fichier ouvert par la bibliothèque. Comment fermer un fichier en C si je sais qu'il est ouvert? J'utilise la bibliothèque DICOM2NII qui est disponible sur http://cbi.nyu.edu/software/dinifti.php. Voici le code pour ouvrir un fichier mais qui ne le ferme pas :

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

2voto

Olaf Dietsche Points 35264

Dans votre classe DICOMImage, ajoutez un membre

DCM_OBJECT *handle_;

et dans votre destructeur, fermez le fichier

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

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

et utilisez ce membre handle_ dans DICOMImage::OpenFile() également, bien sûr.

1voto

Ben Jackson Points 28358

Vous pourriez d'abord tester tous les descripteurs de fichier pour voir lesquels sont utilisés en effectuant une fausse fcntl(fd, F_GETFD) sur chaque fd de 0 jusqu'à getdtablesize(). Lorsque la fonction de bibliothèque retourne, il y aura un fd ouvert de plus que vous pouvez simplement fermer avec close(). Vous pourriez aussi simplement appeler close(fd) sur tout ce qui n'était pas ouvert auparavant et l'un d'entre eux réussira (et vous pouvez arrêter à ce moment-là dans votre recherche).

Il est probable que vous puissiez effectuer la sonde initiale jusqu'au premier fd inutilisé et que la bibliothèque finira par utiliser ce fd à condition de ne rien faire de plus complexe que d'ouvrir un fichier. S'il ouvre plusieurs fichiers ou utilise dup(), il pourrait finir ailleurs.

Pour expliquer cela clairement :

#include 
#include 
#include 
#include 

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

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

void closeOpenedFiles(const std::vector &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 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;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X