IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ VC++ et MFCConsultez toutes les FAQ

Nombre d'auteurs : 20, nombre de questions : 545, dernière mise à jour : 5 avril 2013  Ajouter une question

 

Cette faq a été réalisée pour répondre aux questions les plus fréquement posées sur le forum Développement Visual C++

Je tiens à souligner que cette faq ne garantit en aucun cas que les informations qu'elle contient sont correctes ; Les auteurs font le maximum, mais l'erreur est humaine. Si vous trouvez une erreur, ou si vous souhaitez devenir redacteur, lisez ceci.

Sur ce, je vous souhaite une bonne lecture. Farscape

SommaireFichiers, Parcours, Recherche, Existence (24)
précédent sommaire suivant
 

Avec la fonction _access :

Code c++ : Sélectionner tout
1
2
  
int _access( const char *path, int mode );
Valeurs pour mode :

  • 00 : test de l'existence uniquement ;
  • 02 : permission d'écriture ;
  • 04 : permission lecture ;
  • 06 : permission lecture / écriture.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  
#include <io.h> 
#include <errno.h> 
  
//test si fichier existe 
if((_access( "troll.c", 0 )) != -1 ) 
{ 
   printf( "Fichier troll.c existe\n" ); 
   // Pour permission d'écriture 
   if( (_access( " troll.c ", 2 )) != -1 ) 
       printf( "le Fichier troll.c est ok pour l'écriture\n" ); 
} 
else 
{ 
     switch(errno) 
     { 
         case EACCES :printf("accès interdit\n "); 
                                 break; 
        case  ENOENT:printf("fichier ou chemin incorrect \n") ; 
                                  break ; 
      } 
}

Mis à jour le 5 avril 2013 farscape

Avec la fonction SHBrowseForFolderA:
Exemple complet d'implémentation:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  
CString strTmpPath; 
int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) 
{ 
    TCHAR szDir[MAX_PATH]; 
    switch(uMsg) 
    { 
        case BFFM_INITIALIZED: 
        if (lpData) 
        { 
            strcpy(szDir, strTmpPath.GetBuffer(strTmpPath.GetLength())); 
            SendMessage(hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)szDir); 
        } 
        break; 
  
        case BFFM_SELCHANGED: 
        { 
            if (SHGetPathFromIDList((LPITEMIDLIST) lParam ,szDir)) 
            { 
              SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);         
            } 
           break; 
  
        } 
  
        default:break; 
    }          
    return 0; 
} 
//--------------------------------------------------------------------------------------------- 
BOOL GetFolder(CString* strSelectedFolder, 
               const char* lpszTitle, 
               const HWND hwndOwner,  
               const char* strRootFolder,  
               const char* strStartFolder) 
{ 
    char pszDisplayName[MAX_PATH]; 
    LPITEMIDLIST lpID; 
    BROWSEINFOA bi; 
  
    bi.hwndOwner = hwndOwner; 
  
    if (strRootFolder == NULL) 
    { 
        bi.pidlRoot = NULL; 
    } 
    else 
    { 
        LPITEMIDLIST  pIdl = NULL; 
        IShellFolder* pDesktopFolder; 
        char          szPath[MAX_PATH]; 
        OLECHAR       olePath[MAX_PATH]; 
        ULONG         chEaten; 
        ULONG         dwAttributes; 
  
        strcpy(szPath, (LPCTSTR)strRootFolder); 
        if (SUCCEEDED(SHGetDesktopFolder(&pDesktopFolder))) 
        { 
            MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, olePath, MAX_PATH); 
            pDesktopFolder->ParseDisplayName(NULL, NULL, olePath, &chEaten, &pIdl, &dwAttributes); 
            pDesktopFolder->Release(); 
        } 
        bi.pidlRoot = pIdl; 
    } 
    bi.pszDisplayName = pszDisplayName; 
    bi.lpszTitle = lpszTitle; 
  
#if _MFC_VER < 0x0700 
    bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT; 
#else 
    bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT |BIF_NEWDIALOGSTYLE; 
    OleInitialize(NULL); 
#endif 
    bi.lpfn = BrowseCallbackProc; 
    if (strStartFolder == NULL) 
    { 
        bi.lParam = FALSE; 
    } 
    else 
    { 
        strTmpPath.Format("%s", strStartFolder); 
        bi.lParam = TRUE; 
    } 
    bi.iImage = NULL; 
    lpID = SHBrowseForFolderA(&bi); 
    if (lpID != NULL) 
    { 
        BOOL b = SHGetPathFromIDList(lpID, pszDisplayName); 
        if (b == TRUE) 
        { 
            strSelectedFolder->Format("%s",pszDisplayName); 
            return TRUE; 
        } 
    } 
    else 
    { 
        strSelectedFolder->Empty(); 
    } 
    return FALSE; 
}
utilisation:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
  
CString strRepertoire="c:\\"; 
if(GetFolder(&strRepertoire,"Sélection du répertoire",this->m_hWnd, NULL, NULL)) 
{ 
     if (!strRepertoire.IsEmpty()) 
    { 
    } 
}
Une info intéressante pour rajouter un bouton de création de répertoire :

Code c++ : Sélectionner tout
1
2
  
 bi.ulFlags= BIF_NEWDIALOGSTYLE;
Le hic c'est que cette option fonctionne correctement à partir de Windows 2000 ,elle s'appuie sur shell32.dll et seulement la version 5.0 supporte cette nouvelle fonctionnalité.
Elle n'est pas disponible sous NT4,w95 ou 98 (traduction doc MSDN).
Il faudra rajouter à votre code

Code c++ : Sélectionner tout
1
2
3
4
  
#ifndef BIF_NEWDIALOGSTYLE 
#define BIF_NEWDIALOGSTYLE 0x0040 
#endif

Mis à jour le 5 avril 2013 farscape

Avec la fonction GetOpenFileName:
Exemple d'implémentation complet:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  
#include <direct.h> 
BOOL DlgSelFicName(CWnd *pParent,CString& rstrFileName,LPCTSTR pszExt,BOOL bUnlink=FALSE) 
{ 
    #define MAXPATH 256 
    char szDrive[_MAX_DRIVE]; 
    char szDir[_MAX_DIR]; 
    char szFname[_MAX_FNAME]; 
    char szExt[_MAX_EXT]; 
  
    OPENFILENAME ofn; 
    char szFileBuf[MAXPATH]; 
    char    szpathDir[128],*pszPath=NULL, 
    szbufDir[128]; 
    CString strRet; 
  
    pszPath=(char *)_getcwd(NULL,127); 
  
    szFileBuf[0] = 0; 
  
    if(!rstrFileName.IsEmpty()) 
    { 
        _splitpath((const char *)rstrFileName, szDrive, szDir, szFname, szExt); 
        strcpy(szpathDir,szDrive); 
        strcat(szpathDir,szDir); 
        strcpy(szFileBuf,szFname); 
        strcat(szFileBuf,szExt); 
     } 
    else 
    { 
        strRet=AfxGetApp()->GetProfileString( "OpenFileName","Path",""); 
        strcpy(szbufDir,strRet); 
        if(strlen(szbufDir)) strcpy(szpathDir,szbufDir); 
        else strcpy(szpathDir,pszPath); 
    } 
    ofn.lStructSize = sizeof(OPENFILENAME); 
    ofn.hwndOwner =(pParent?pParent->GetSafeHwnd():NULL); 
    ofn.lpstrFilter =pszExt; 
    ofn.lpstrCustomFilter = NULL; 
    ofn.nFilterIndex = 0; 
    ofn.lpstrFile = szFileBuf; 
    ofn.nMaxFile = MAXPATH; 
    ofn.lpstrFileTitle = NULL; 
    ofn.lpstrInitialDir = szpathDir; 
    ofn.lpstrTitle = NULL; 
    ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST; 
    ofn.lpstrDefExt = NULL; 
  
    rstrFileName=""; 
    BOOL bOK=FALSE; 
    if (GetOpenFileName(&ofn)) 
    { 
        CString e; 
        _splitpath(szFileBuf, szDrive, szDir, szFname, szExt); 
        sprintf(szpathDir,"%s%s",szDrive,szDir); 
        AfxGetApp()->WriteProfileString("OpenFileName","Path",szpathDir); 
        sprintf(szFileBuf,"%s%s%s",szDrive,szDir,(strlen(szFname)?szFname:"")); 
  
        e=pszExt; 
        e=e.Right(5); 
        e=e.Left(4); 
  
        strcat(szFileBuf,(strlen(szExt)?szExt:e)); 
        rstrFileName=szFileBuf; 
        if(bUnlink) _unlink(szFileBuf); 
        bOK=TRUE; 
    } 
    else rstrFileName=""; 
    if(pszPath) 
    { 
        _chdir(pszPath); 
        free(pszPath); 
    } 
    return bOK; 
}
Utilisation

Code c++ : Sélectionner tout
1
2
3
4
5
6
  
CString strFileName; 
::DlgSelFicName(this,strFileName,"Fichiers Txt (*.txt)\0*.txt\0"); 
// ou multi extensions 
::DlgSelFicName(this,strFileName, 
"Fichiers Texte (*.txt)\0*.txt\0Fichiers csv (*.csv)\0*.csv\0Fichiers tabulations (*.txt)\0*.txt\0");

Mis à jour le 23 mars 2008 farscape

Affiche tous les fichiers et répertoires en utilisant le filtre c:\*.*
La première version est avec les MFC:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
  
CFileFind f; 
BOOL bMoreFiles = f.FindFile("c:\\*.*"); 
while (bMoreFiles) 
{ 
    bMoreFiles = f.FindNextFile(); 
    if (f.IsDirectory()) 
    cout << (LPCSTR)f.GetFileName() << " : Repertoire" << endl; 
    else 
    cout << (LPCSTR)f.GetFileName() << " : Taille=" << f.GetLength() << endl; 
}
version sans les MFC

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  
WIN32_FIND_DATA data; 
HANDLE h = FindFirstFile("c:\\*.*", &data); 
BOOL bMoreFiles =  (h != INVALID_HANDLE_VALUE); 
while (bMoreFiles) 
{ 
    if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
    cout << data.cFileName << " : Repertoire" << endl; 
    else 
    cout << data.cFileName << " : Taille=" << (data.nFileSizeHigh * MAXDWORD) + data.nFileSizeLow << endl; 
    bMoreFiles = FindNextFile(h, &data); 
} 
if (GetLastError() != ERROR_NO_MORE_FILES) 
    cout << "erreur  = " << GetLastError() << endl; 
if (h!= INVALID_HANDLE_VALUE) FindClose(h);

Mis à jour le 5 avril 2013 abelman

Code c++ : Sélectionner tout
1
2
3
4
5
6
  
TCHAR szDir[MAX_PATH] = ""; 
if(!::GetCurrentDirectory(sizeof(szDir) - 1, szDir)) 
{ 
  // ::GetLastError() 
}

Mis à jour le 5 avril 2013 farscape

Code c++ : Sélectionner tout
1
2
3
4
5
  
if(::SetCurrentDirectory("c:\\MyProjects\\Dvp") == FALSE) 
{ 
  // GetLastError() 
}

Mis à jour le 5 avril 2013 farscape

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  
TCHAR szWindDir[MAX_PATH] = ""; 
UINT nRetLen = ::GetWindowsDirectory(szWindDir, sizeof(szWindDir)); 
if(!nRetLen) 
{ 
  // Erreur voir ::GetLastError() 
} 
else if(nRetLen > sizeof(szWindDir)) 
{ 
  // buffer trop petit. 
} 
else 
{ 
  // ok! 
}

Mis à jour le 5 avril 2013 farscape

Le petit exemple ci-dessus explore les lettres de B à Z et récupère L'information concernant l'unité trouvée,
Les lecteurs réseaux sont aussi détectés et reconnectés le cas échéant.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  
void ExploreDrives() 
{ 
    char let,szbuf[5]; 
    int nError; 
    char szRemote[256]; 
    DWORD l=255; 
    short int *pt=NULL; 
    CString str; 
    UINT ntyp; 
    for(let='B';let<='Z';let++) 
    { 
        sprintf(szbuf,"%c:",let); 
        if((nError=WNetGetConnection(szbuf,szRemote,&l))==NO_ERROR) 
        { 
            TRACE("\nWnet:%s",szRemote); 
        } 
        else  
        { 
            str.Format("%c:\\",let); 
            ntyp=GetDriveType(str); 
            TRACE("\nDrive :%s :%d"",(const char *)str,ntyp); 
            if(ntyp==DRIVE_CDROM) 
            { 
                //  
                continue; 
            } 
            if(ntyp==DRIVE_REMOVABLE) 
            { 
                //  
                continue; 
            } 
            if(ntyp==DRIVE_FIXED) 
            { 
                //  
                continue; 
            } 
            else 
            // tentative de reconnection lettre reseau 
            if(nError==ERROR_CONNECTION_UNAVAIL) 
            { 
                if(WNetAddConnection(szRemote,NULL,szbuf)==NO_ERROR) 
                { 
                    // si pas d'erreur 
  
                } 
            } 
        } 
    } 
}

Mis à jour le 5 avril 2013 farscape

il faut utiliser l'api32 : GetVolumeInformation le type de fat est chargé dans la zone lpFileSystemNameBuffer

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
  
BOOL GetVolumeInformation( 
  LPCTSTR lpRootPathName,           // root directory 
  LPTSTR lpVolumeNameBuffer,        // volume name buffer 
  DWORD nVolumeNameSize,            // length of name buffer 
  LPDWORD lpVolumeSerialNumber,     // volume serial number 
  LPDWORD lpMaximumComponentLength, // maximum file name length 
  LPDWORD lpFileSystemFlags,        // file system options 
  LPTSTR lpFileSystemNameBuffer,    // file system name buffer 
  DWORD nFileSystemNameSize         // length of file system name buffer 
);
Exemple:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  
BOOL bSuccess; 
char szVolName[MAX_PATH]; 
DWORD dwVolSerialNumber; 
DWORD dwMaxNameLength; 
DWORD dwFileSystemFlags; 
char szSystemName[MAX_PATH]; 
  
bSuccess= GetVolumeInformation("c:\\", 
szVolName,MAX_PATH, 
&dwVolSerialNumber, 
&dwMaxNameLength, 
&dwFileSystemFlags, 
szSystemName,MAX_PATH); 
  
   cout << "Nom du volume " << szVolName << endl; 
   cout << "Numero de serie " << dwVolSerialNumber << endl; 
   cout << "Systeme de Fichier " << szSystemName << endl; 
   cout << "Longueur maximale d'un nom de fichier " << dwMaxNameLength << endl;

Mis à jour le 5 avril 2013 farscape

En utilisant SHGetSpecialFolderPath, la liste des attributs que l'on peut récupérer est disponible ici.

Voilà à titre d'exemple quelques emplacement spéciaux, pour récupérer le path de "mes documents" ou bien du bureau, etc.

Code C++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
char mesDocumentsPath[MAX_PATH]; 
SHGetSpecialFolderPath(0,mesDocumentsPath,CSIDL_PERSONAL,0); 
  
char applicationData[MAX_PATH]; 
SHGetSpecialFolderPath(0,applicationData,CSIDL_COMMON_APPDATA,0); 
  
char bureau[MAX_PATH]; 
SHGetSpecialFolderPath(0,bureau,CSIDL_DESKTOPDIRECTORY,0); 
  
char favoris[MAX_PATH]; 
SHGetSpecialFolderPath(0,favoris,CSIDL_FAVORITES,0); 
  
char maMusique[MAX_PATH]; 
SHGetSpecialFolderPath(0,maMusique,CSIDL_MYMUSIC,0); 
  
char mesImages[MAX_PATH]; 
SHGetSpecialFolderPath(0,mesImages,CSIDL_MYPICTURES,0); 
  
char profile[MAX_PATH]; 
SHGetSpecialFolderPath(0,profile,CSIDL_PROFILE,0); 
  
char programFiles[MAX_PATH]; 
SHGetSpecialFolderPath(0,programFiles,CSIDL_PROGRAM_FILES,0); 
  
char sendTo[MAX_PATH]; 
SHGetSpecialFolderPath(0,sendTo,CSIDL_SENDTO,0);

Note : Si le dernier paramètre est positionné à 1, il permet de créer l'entrée.

Mis à jour le 5 avril 2013 nico-pyright(c)

il y a plusieurs façons de le faire, le but étant d'obtenir une variable de type FILETIME correctement renseignée.
Voilà un exemple en utilisant l'API GetFileAttributesEx

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
  
char nomFichier[] = "test.txt"; 
WIN32_FILE_ATTRIBUTE_DATA attr; 
FILETIME ftlocal; 
SYSTEMTIME st; 
GetFileAttributesEx( nomFichier, GetFileExInfoStandard, &attr); 
FileTimeToLocalFileTime(&attr.ftCreationTime, &ftlocal); 
FileTimeToSystemTime(&ftlocal, &st); 
  
char date[50]; 
wsprintf(date,"%02d/%02d/%04d-%02d:%02d:%02d", 
st.wDay,st.wMonth,st.wYear,st.wHour,st.wMinute,st.wSecond); 
MessageBox(0,date,"Date de création du fichier",MB_ICONSTOP);
la structure WIN32_FILE_ATTRIBUTE_DATA nous donne aussi la possibilité d'utiliser
la date de dernier accès ftLastAccessTime
la date de derniere écriture ftLastWriteTime

Mis à jour le 19 septembre 2005 nico-pyright(c)

On peut éviter de faire une fonction récursive qui supprime tous les fichiers dans tous les répertoires en déléguant ceci aux fonctions Shell de l'API.
Ici en l'occurence, on se sert d'une fonctionnalité de l'API SHFileOperation.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <shellapi.h> 
  
bool myDeleteDirectory(LPCTSTR repertoire, bool suppressionDefinitive = true) 
{ 
    int s = strlen(repertoire); 
    TCHAR * rep = new TCHAR[strlen(repertoire)+2]; 
    strcpy(rep, repertoire); 
    rep[strlen(repertoire)+1] = '\0'; 
    SHFILEOPSTRUCT sh; 
    sh.hwnd = NULL; 
    sh.wFunc = FO_DELETE; 
    sh.pFrom = rep; 
    sh.pTo = NULL; 
    sh.fFlags = FOF_NOCONFIRMATION|FOF_SILENT; 
    if(!suppressionDefinitive) 
        sh.fFlags |= FOF_ALLOWUNDO; 
    sh.fAnyOperationsAborted = FALSE; 
    sh.lpszProgressTitle = NULL; 
    sh.hNameMappings = NULL; 
  
    delete [] rep; 
    return (SHFileOperation(&sh)==0); 
}
Code c++ : Sélectionner tout
   myDeleteDirectory("d:\\test", false);
NB : Prendre garde à ne pas utiliser de chemin relatif et à toujours utiliser un chemin absolu.
Sinon, cette utilisation n'est pas garantie et peut provoquer un comportement indéterminé.
On utilise une liste d'emplacements à supprimer, séparés par des \0, et qui se termine par un double \0

Mis à jour le 19 septembre 2005 nico-pyright(c)

En utilisant la fonction :

Code c++ : Sélectionner tout
1
2
  
BOOL PathFileExists(LPCTSTR pszPath);
Cette fonction détermine si un fichier ou un chemin existe.
Pour l'utiliser vous devrez inclure l'entête "Shlwapi.h"
et rajouter la librairie Shlwapi.lib à l'assemblage des liens (link) .

Mis à jour le 19 septembre 2005 farscape

En parcourant la chaîne renvoyée par GetLogicalDriveStrings() qui contient la liste des lecteurs On peut observer aussi comment calculer l'espace disque disponible avec l'API GetDiskFreeSpaceEx().

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  
void exploreDisque() 
{ 
    char buff[264]; 
    GetLogicalDriveStrings(264,buff); 
    char *c; 
    c=buff; 
    while(*c!=NULL) 
    { 
        printf("%s",c); 
        char disqueReseau[20] = " --> disque réseau"; 
        UINT type = GetDriveType(c); 
        switch (type) 
        { 
        case DRIVE_UNKNOWN: 
            printf(" --> type inconnu"); 
            break; 
        case DRIVE_REMOVABLE: 
            printf(" --> disque extractible"); 
            break; 
        case DRIVE_FIXED: 
            printf(" --> disque dur"); 
            break; 
        case DRIVE_REMOTE: 
            CharToOem(disqueReseau,disqueReseau); 
            printf(disqueReseau); 
            break; 
        case DRIVE_CDROM: 
            printf(" --> CDROM"); 
            break; 
        case DRIVE_RAMDISK: 
            printf(" --> Ram disque"); 
            break; 
        } 
  
        // calcul l'espace disque 
        __int64 FreeBytesToCaller; 
        __int64 TotalBytes; 
        __int64 FreeBytes; 
        if (GetDiskFreeSpaceEx(c, 
            (PULARGE_INTEGER)&FreeBytesToCaller, 
            (PULARGE_INTEGER)&TotalBytes, 
            (PULARGE_INTEGER)&FreeBytes)) 
        { 
            printf(" ; %d Ko",FreeBytesToCaller/1024); 
        } 
        printf("\n"); 
        while (*c!=NULL) 
            c++; 
        c++; 
    } 
}

Mis à jour le 19 septembre 2005 nico-pyright(c)

Pour manipuler un fichier en C/C++ il existe différentes méthodes.

  • On peut utiliser les fonctions C classiques fopen, fread, etc. (voir FAQ C)
  • On peut utiliser les flux standards c++ (voir FAQ C++)

Sous Windows, on utilisera directement les API Win32 (CreateFile, ReadFile...) ou une surcouche comme les MFC (CFile et ses dérivées)

Mis à jour le 20 mai 2006 nico-pyright(c)

Tant qu'à utiliser les bibliothèques MFC, il est plus intéressant de privilégier les classes CFile ou CStdioFile qui sont plus faciles à manipuler que les fonctions de l'API. On utilisera les fonctions de l'API que lorsque le projet ne doit pas utiliser les MFC.
Globalement, on choisit d'utiliser CFile lorsqu'on utilise des fichiers en mode binaire et CStdioFile pour des fichiers en mode texte.
L'API Win32 manipule les fichiers comme étant des fichiers binaires.

Mis à jour le 20 mai 2006 nico-pyright(c)

Un fichier est une suite d'octets. Donc tout fichier est un fichier binaire en soit. On va lire une suite d'octets dans ce fichier. L'abstraction d'un fichier en mode texte, permet d'établir un séparateur de lignes dans un fichier texte.
Ce séparateur va permettre de lire plutôt des lignes dans un fichier qu'une suite d'octets.
Ce séparateur de lignes correspond à un ou plusieurs caractères suivant les plateformes.

Par exemple, sur MAC, le séparateur est un simple retour chariot (0x0D en ascii), tandis que sur des OS basés sur Unix, on utilise le caractère de retour en début de ligne (0x0A en ascii).
Par contre, sous DOS/OS2 et Windows, c'est une combinaison de ces deux caractères (à savoir 0x0D0A). Donc si on utilise un fichier en mode texte en lisant octet par octet, il faudra faire attention au séparateur suivant les OS.
Heureusement, les fonctions du C/C++ nous permettent de manipuler les fichiers sans se soucier de la plateforme tant que nous ouvrons le fichier en mode texte.

On a tendance à dire que l'utilisation d'un fichier binaire, bien que pratique dans certains cas, peut présenter des inconvénients à long terme.
Imaginons que l'on veuille stocker les coordonnées de sa souris dans un fichier.
On va utiliser deux entier (int) pour les stocker, soit à l'heure actuelle 2*4 = 8 octets dans le fichier.
Mais imaginons que d'ici quelques années, les entiers ne soient plus stockés sur 4 octets mais sur 8.
Si on recompile notre programme avec des entier sur 8 octets, la lecture d'un entier dans ce fichier ne produira pas le même résultat.
L'inconvénient d'un fichier texte bien sur est qu'il est plus délicat de stocker n'importe quelle suite d'octet.

Il faut donc bien choisir son type de fichier en fonction de ses besoins.

Mis à jour le 20 mai 2006 nico-pyright(c)

API Win32 : on utilise SetFilePointer

Code c++ : Sélectionner tout
SetFilePointer(fichier,NULL,NULL,FILE_END);
CFile et ses dérivées : on utilise Seek, SeekToBegin ou SeekToEnd

Code c++ : Sélectionner tout
cfile.SeekToEnd();

Mis à jour le 20 mai 2006 nico-pyright(c)

Cette pratique est souvent utilisée pour éviter les multiaccès au fichier Api Win32

Code C++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
HANDLE hFile;  
hFile = CreateFile("test.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); 
if (hFile == INVALID_HANDLE_VALUE) 
    return false; 
DWORD dwSize; 
dwSize = GetFileSize (hFile, NULL); 
if (dwSize == INVALID_FILE_SIZE) 
    return false; 
char *buffer = new char[dwSize+1]; 
DWORD bLu; 
ReadFile(hFile,buffer,dwSize,&bLu,NULL); 
// ... 
delete [] buffer;

CFile

Code C++ : Sélectionner tout
1
2
3
4
5
6
7
8
CFile f2 ("c:\\test.txt", CFile::modeRead | CFile::typeBinary ); 
ULONGLONG taille = f2.GetLength(); 
char *buffer = new char[(int)taille+1]; 
CString str; 
UINT nOctetsLu = f2.Read(buffer, (int)taille); 
str = buffer; 
f2.Close(); 
delete [] buffer;

NB : Lorsqu'on utilise des gros fichiers, new peut échouer par manque de place sur le tas. Il est recommandé d'avoir recours à une allocation dynamique.

Code C++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
// initialisation du buffer (remplace le new) 
char * buffer = (char *) VirtualAlloc(NULL, dwSize * sizeof(char), MEMDISPO, PAGE_READWRITE); 
if (!buffer) 
{ 
    return 1; // erreur de mémoire 
} 
  
// ... 
  
// Libération du buffer 
VirtualFree(buffer, 0, MEM_RELEASE);

Mis à jour le 20 mai 2006 nico-pyright(c)

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
CStdioFile f1 ("c:\\test.txt", CFile::modeCreate | CFile::modeWrite | CFile::typeText ); 
f1.WriteString("premiere ligne\n"); 
f1.WriteString("deuxieme ligne"); 
f1.Close(); 
  
CStdioFile f2 ("c:\\test.txt", CFile::modeRead | CFile::typeText ); 
CString s1, s2; 
f2.ReadString(s1); // s1 contient "premiere ligne" 
f2.ReadString(s2); // s2 contient "deuxieme ligne" 
f2.Close();
Nb : pour ajouter un caractère de séparation de ligne, on utilise \n (0x0A).
La fonction WriteString le transforme alors en 0x0D, 0x0A. Inversement, lorsqu'on lit la paire 0x0D, 0x0A, la fonction ReadString le transforme en \n (0x0A)

Mis à jour le 20 mai 2006 nico-pyright(c)

par exemple, lire et ecrire un tableau de 5 entiers
avec les API Win32

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int t1[5] = {1,2,3,4,5}; 
HANDLE fichier;  
DWORD octetsEcrits; 
fichier = CreateFile("test.txt", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
if( fichier == INVALID_HANDLE_VALUE) 
   return false; 
if (!WriteFile(fichier, t1 ,sizeof(int)*5,&octetsEcrits,NULL)) 
{ 
   // erreur; 
} 
CloseHandle(fichier); 
  
hFile = CreateFile("test.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); 
if (hFile == INVALID_HANDLE_VALUE) 
   return false; 
int t2[5]; 
DWORD octetsLu; 
if (!ReadFile(hFile,t2,sizeof(int)*5,&octetsLu,NULL)) 
{ 
   // erreur; 
} 
CloseHandle(fichier);
Avec CFile

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
   int t1[5] = {1,2,3,4,5}; 
   CFile f1 ("c:\\test.txt", CFile::modeCreate | CFile::modeWrite | CFile::typeBinary ); 
   f1.Write(t1,sizeof(int)*5); 
   f1.Close(); 
  
   int t2[5]; 
   CFile f2 ("c:\\test.txt", CFile::modeRead | CFile::typeBinary ); 
   UINT nOctetsLu = f2.Read( t2, sizeof(int)*5); 
   f2.Close();

Mis à jour le 20 mai 2006 nico-pyright(c)

En utilisant les IOCTL (donc devrait marcher avec les lecteurs Zip etc.).
On peut aussi spécifier quel lecteur éjecter / refermer.

Code C++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <windows.h> 
  
// Envoie un IOCTL simple vers le périphérique donné 
bool SendSimpleIOCTL( LPCTSTR DeviceName, DWORD IoControlCode ) 
{ 
    // ouvrir le driver associé au périphérique donné 
    HANDLE hDevice = ::CreateFile( 
        DeviceName, 
        GENERIC_READ, 
        0, 
        0, 
        OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, 
        0 );  
    if ( hDevice == INVALID_HANDLE_VALUE ) 
    { 
        return false; 
    } 
  
    // envoyer l'IOCTL 
    DWORD unused; 
    BOOL res = ::DeviceIoControl( 
        hDevice, 
        IoControlCode, 
        NULL, 
        0, 
        NULL, 
        0, 
        &unused, 
        NULL );  
  
    // libérer les ressource 
    ::CloseHandle( hDevice );  
  
    return res == TRUE;  
} 
  
// ouvre le tiroir d'un CD-ROM, ou autre... 
bool EjectDevice( LPCTSTR DeviceName )  
{  
    return SendSimpleIOCTL( 
        DeviceName,  
        IOCTL_STORAGE_EJECT_MEDIA ); 
}  
  
// ferme le tiroir d'un CD-ROM, ou autre... 
bool CloseDeviceDoor( LPCTSTR DeviceName )  
{  
    return SendSimpleIOCTL( 
        DeviceName,  
        IOCTL_STORAGE_LOAD_MEDIA ); 
} 
  
int main() 
{ 
    // le disque peut être désigné soit via son nom logique (par exemple "D:") 
    // soit par son nom de périphérique ("CdRom0") 
    // Dans les deux cas, ils doivent être précédés du caractère antislash  
// en C/C++ il ne faut pas oublier de les doubler: 
    EjectDevice( "\\\\.\\D:" ); 
    CloseDeviceDoor( "\\\\.\\CdRom0" ); 
}

Ne fonctionne que sous NT.

Petit lien pour spécifier le lecteur à ouvrir avec mciSendStringLecteurs

Mis à jour le 20 mai 2006 Aurelien.Regat-Barrel

En utilisant les commandes MCI, exemple : pour éjecter le CD

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  
#include <mmsystem.h> 
bool ejectCD(void) 
{ 
    bool ejected=false; 
    if(mciSendString("open cdaudio",NULL,0,NULL)==0) 
    { 
        char buffer[10]; 
        if(mciSendString("capability cdaudio can eject",buffer,sizeof(buffer),NULL)==0) 
        { 
            if(stricmp(buffer,"true")==0) 
            { 
                ejected=mciSendString("set cdaudio door open",NULL,0,NULL)==0; 
            } 
        } 
        mciSendString("close cdaudio",NULL,0,NULL); 
    } 
    return(ejected); 
}
Pour fermer le lecteur :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  
bool closeCD(void) 
{ 
    bool closed=false; 
    if(mciSendString("open cdaudio",NULL,0,NULL)==0) 
    { 
        char buffer[10]; 
        if(mciSendString("capability cdaudio can eject",buffer,sizeof(buffer),NULL)==0) 
        { 
            if(stricmp(buffer,"true")==0) 
            { 
                closed=mciSendString("Set cdaudio door closed wait",NULL,0,NULL)==0; 
            } 
        } 
        mciSendString("close cdaudio",NULL,0,NULL); 
    } 
    return(closed); 
}
NB : Ces fonctions nécessitent le link de la librairie Winmm.lib

Code c++ : Sélectionner tout
#pragma comment (lib, "Winmm.lib")

Mis à jour le 20 mai 2006 nico-pyright(c)

Il faut parcourir récursivement tous les fichiers à partir du répertoire racine.

Voici, une petite fonction qui fait le travail

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <windows.h> 
  
void mycalculTaille(char * rep, __int64 *taille) 
{ 
    WIN32_FIND_DATA FindFileData; 
    char path[MAX_PATH]; 
    strcpy(path,rep); 
    strcat(path,"\\*.*"); 
    HANDLE hFind = FindFirstFile(path, &FindFileData); 
    if (hFind==INVALID_HANDLE_VALUE) 
        return; 
    if (strcmp(FindFileData.cFileName,".")!=0 && strcmp(FindFileData.cFileName,"..")!=0) 
    { 
        strcpy(path,rep); 
        strcat(path,"\\"); 
        strcat(path,FindFileData.cFileName); 
        mycalculTaille(path, taille); 
    } 
    DWORD a = 0; 
    while (a != ERROR_NO_MORE_FILES) 
    { 
        if (!FindNextFile(hFind, &FindFileData)) 
            a = GetLastError(); 
        else 
        { 
            if (strcmp(FindFileData.cFileName,".")!=0 && strcmp(FindFileData.cFileName,"..")!=0) 
            { 
                strcpy(path,rep); 
                strcat(path,"\\"); 
                strcat(path,FindFileData.cFileName); 
                if (FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) 
                    mycalculTaille(path, taille); 
                else 
                { 
                    *taille = *taille + (FindFileData.nFileSizeHigh * ((long)MAXDWORD+1) + FindFileData.nFileSizeLow); 
                } 
            } 
        } 
    } 
    FindClose(hFind); 
} 
  
__int64 calculTaille(char * rep) 
{ 
   __int64 taille; 
   taille = 0; 
    mycalculTaille(rep, &taille); 
    return taille; 
} 
  
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) 
{ 
   __int64 taille = calculTaille("d:\\truc"); 
   return 1; 
}

Mis à jour le 20 mai 2006 nico-pyright(c)

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2022 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.