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
- Comment savoir si un fichier existe ?
- Comment faire une sélection d'un répertoire de destination?
- Comment sélectionner un fichier dans un répertoire ?
- Comment rechercher des fichiers ?
- Comment retrouver le répertoire courant ?
- Comment changer le répertoire courant ?
- Comment récupérer le répertoire Windows ?
- Comment scanner les unités d'un poste de travail ?
- Comment détecter le type de système de fichiers d'un disque ?
- Comment déterminer les répertoires spéciaux ?
- Comment afficher la date de création d'un fichier ?
- Comment supprimer un répertoire non vide ?
- Comment vérifier qu'un chemin de fichier existe ?
- Comment calculer l'espace disque disponible sur un lecteur ?
- Quelles sont les différentes méthodes pour manipuler un fichier ?
- Que choisir entre l'API Win32 et la surcouche MFC (CFile, CStdioFile) ?
- Dois-je créer un fichier binaire ou un fichier texte ?
- Comment déplacer le pointeur de fichier ?
- Comment lire tout mon fichier dans un buffer ?
- Comment lire et écrire dans un fichier en mode texte ?
- Comment lire et écrire dans un fichier en mode binaire ?
- Comment ouvrir/fermer le lecteur de CD (IOCTL)?
- Comment ouvrir/fermer le lecteur de CD (MCI)?
- Comment calculer la taille d'un répertoire et de ses sous-répertoires ?
Avec la fonction _access :
Code c++ : | Sélectionner tout |
1 2 | int _access( const char *path, int 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 ; } } |
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; } |
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()) { } } |
Code c++ : | Sélectionner tout |
1 2 | bi.ulFlags= BIF_NEWDIALOGSTYLE; |
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 |
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; } |
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"); |
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; } |
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); |
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 | TCHAR szDir[MAX_PATH] = ""; if(!::GetCurrentDirectory(sizeof(szDir) - 1, szDir)) { // ::GetLastError() } |
Code c++ : | Sélectionner tout |
1 2 3 4 5 | if(::SetCurrentDirectory("c:\\MyProjects\\Dvp") == FALSE) { // GetLastError() } |
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! } |
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 } } } } } |
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 ); |
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; |
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.
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 date de dernier accès ftLastAccessTime
la date de derniere écriture ftLastWriteTime
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);
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
En utilisant la fonction :
Code c++ : | Sélectionner tout |
1 2 | BOOL PathFileExists(LPCTSTR pszPath); |
Pour l'utiliser vous devrez inclure l'entête "Shlwapi.h"
et rajouter la librairie Shlwapi.lib à l'assemblage des liens (link) .
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++; } } |
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)
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.
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.
API Win32 : on utilise SetFilePointer
Code c++ : | Sélectionner tout |
SetFilePointer(fichier,NULL,NULL,FILE_END);
Code c++ : | Sélectionner tout |
cfile.SeekToEnd();
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); |
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(); |
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)
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); |
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(); |
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 mciSendString: Lecteurs
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); } |
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); } |
Code c++ : | Sélectionner tout |
#pragma comment (lib, "Winmm.lib")
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; } |
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 çaLes 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 © 2024 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.