Salut dans ce cours tu vas voir
Si tu comprends mal les I/O :
* ton programme sera lent
* il bloquera
* il plantera sur des fichiers “bizarres”
* il se comportera différemment selon la machine
---
### 1) Tout est un handle sous Windows
Sous Windows, presque tout passe par un HANDLE.
Fichiers, pipes, events, mutex, etc.
Tu ouvres, tu utilises, tu fermes.
Un handle, ce n’est pas un pointeur.
C’est une référence gérée par le noyau.
Oublier CloseHandle = fuite de ressources.
---
### 2) Ouvrir un fichier : CreateFile
CreateFile sert à créer ou ouvrir un fichier.
Code: Select all
HANDLE hFile = CreateFileW(
L"test.txt",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE)
{
DWORD err = GetLastError();
return 1;
}
* les droits (GENERIC_READ/WRITE)
* le partage (FILE_SHARE_*)
* le mode (OPEN_EXISTING, CREATE_ALWAYS, etc.)
---
### 3) Lire et écrire : ReadFile et WriteFile
Les deux fonctions de base :
* ReadFile
* WriteFile
Lecture :
Code: Select all
DWORD bytesRead = 0;
char buffer[128] = {0};
BOOL ok = ReadFile(
hFile,
buffer,
sizeof(buffer) - 1,
&bytesRead,
NULL
);
Code: Select all
DWORD bytesWritten = 0;
const char* msg = "Hello from Win32\r\n";
BOOL ok = WriteFile(
hFile,
msg,
(DWORD)strlen(msg),
&bytesWritten,
NULL
);
* bytesRead/bytesWritten indiquent ce qui a été réellement traité
* toujours vérifier le retour (ok)
* ReadFile/WriteFile sont bloquantes par défaut
---
### 4) Le pointeur de fichier (file pointer)
Chaque handle de fichier a une position interne.
Lire/écrire avance automatiquement cette position.
Pour déplacer la position :
Code: Select all
LARGE_INTEGER off;
off.QuadPart = 0;
SetFilePointerEx(hFile, off, NULL, FILE_BEGIN);
Code: Select all
LARGE_INTEGER size;
GetFileSizeEx(hFile, &size);
### 5) I/O bloquantes (synchrones)
Par défaut, ReadFile et WriteFile bloquent le thread appelant jusqu’à la fin.
Donc :
* si tu fais ça dans le thread principal
* ton programme peut se figer
---
### 6) I/O asynchrones (OVERLAPPED)
Pour éviter de bloquer, Windows propose les I/O overlapped.
Tu dois :
* ouvrir le fichier avec FILE_FLAG_OVERLAPPED
* utiliser un OVERLAPPED
Exemple ouverture :
Code: Select all
HANDLE hFile2 = CreateFileW(
L"test.txt",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL
);
Code: Select all
OVERLAPPED ov = {0};
BOOL ok = WriteFile(
hFile2,
msg,
(DWORD)strlen(msg),
NULL,
&ov
);
if (!ok && GetLastError() == ERROR_IO_PENDING)
{
// I/O en cours, tu attendras le résultat plus tard
}
* GetOverlappedResult
ou via un event dans ov.hEvent + WaitForSingleObject
---
### 7) Lister des fichiers et dossiers
Lister un dossier :
Code: Select all
WIN32_FIND_DATAW data;
HANDLE hFind = FindFirstFileW(L"*.*", &data);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
// data.cFileName
} while (FindNextFileW(hFind, &data));
```
FindClose(hFind);
```
}
* CreateDirectory / RemoveDirectory
* DeleteFile
* MoveFile / CopyFile
---
### 8) Infos et attributs
Attributs :
Code: Select all
DWORD attr = GetFileAttributesW(L"test.txt");
Code: Select all
BY_HANDLE_FILE_INFORMATION info;
GetFileInformationByHandle(hFile, &info);
### 9) Cache système et flush
Windows utilise un cache disque.
WriteFile ne signifie pas forcément “écrit sur le disque maintenant”.
Pour forcer :
Code: Select all
FlushFileBuffers(hFile);
### 10) Erreurs classiques
* oublier CloseHandle
* ne pas vérifier les retours
* bloquer le thread principal avec ReadFile/WriteFile
* ignorer bytesRead/bytesWritten
* mauvaise gestion des chemins
---
### À retenir
CreateFile est la base du filesystem.
ReadFile lit, WriteFile écrit.
Par défaut c’est bloquant.
OVERLAPPED permet l’asynchrone.
Le cache existe, FlushFileBuffers force l’écriture.
Bien gérer les handles et les erreurs, c’est la moitié du boulot.
Dans la suite, on pourra faire :
* Named Pipes (IPC)
* I/O Completion Ports
* ou une partie “chemins, MAX_PATH, \?\ et pièges réels”
