Tworzenie i otwieranie plików
Funkcja CreateFile może utworzyć nowy plik lub otworzyć istniejący plik. Musisz określić nazwę pliku, instrukcje tworzenia i inne atrybuty. Gdy aplikacja tworzy nowy plik, system operacyjny dodaje go do określonego katalogu.
System operacyjny przypisuje unikatowy identyfikator o nazwie dojściado każdego pliku otwartego lub utworzonego przy użyciu CreateFile. Aplikacja może używać tego uchwytu z funkcjami do odczytu, zapisu i opisywania pliku. Jest ważna do momentu zamknięcia wszystkich odwołań do tego uchwytu. Po uruchomieniu aplikacji dziedziczy wszystkie otwarte dojścia z procesu, który go uruchomił, jeśli dojścia zostały utworzone jako dziedziczone.
Aplikacja powinna sprawdzić wartość dojścia zwróconego przez CreateFile przed podjęciem próby uzyskania dostępu do pliku za pomocą dojścia. Jeśli wystąpi błąd, wartość dojścia będzie INVALID_HANDLE_VALUE, a aplikacja może użyć funkcji GetLastError w celu uzyskania rozszerzonych informacji o błędzie.
Gdy aplikacja używa CreateFile, musi użyć parametru dwDesiredAccess, aby określić, czy zamierza odczytywać z pliku, zapisywać w pliku, odczytywać i zapisywać, czy też nie. Jest to nazywane żądaniem trybu dostępu . Aplikacja musi również użyć parametru dwCreationDisposition, aby określić, jaką akcję należy podjąć, jeśli plik już istnieje; działanie to jest znane jako dyspozycja tworzenia. Na przykład aplikacja może wywołać CreateFile z dwCreationDisposition ustawionym na CREATE_ALWAYS, aby zawsze utworzyć nowy plik, nawet jeśli plik o tej samej nazwie już istnieje (nadpisując istniejący plik). Niezależnie od tego, czy to się powiedzie, czy nie zależy od czynników, takich jak atrybuty poprzedniego pliku i ustawienia zabezpieczeń (zobacz poniższe sekcje, aby uzyskać więcej informacji).
Aplikacja używa również CreateFile, aby określić, czy chce udostępnić plik do odczytu, zapisu, obu lub nie. Jest to nazywane trybem udostępniania . Otwarty plik, który nie jest udostępniony (gdydwShareMode jest ustawiony na zero), nie może zostać ponownie otwarty ani przez aplikację, która go otworzyła, ani przez inną aplikację, dopóki nie zostanie zamknięty jego uchwyt. Jest to również nazywane wyłącznym dostępem.
Gdy proces używa CreateFile do próby otwarcia pliku, który został już otwarty w trybie udostępniania (dwShareMode ustawiony na prawidłową wartość niezerową), system porównuje żądany dostęp i tryb udostępniania do tych określonych podczas otwierania pliku. Jeśli określisz tryb dostępu lub udostępniania, który powoduje konflikt z trybami określonymi w poprzednim wywołaniu, tworzenie pliku zakończy się niepowodzeniem.
W poniższej tabeli przedstawiono prawidłowe kombinacje dwóch wywołań CreateFile przy użyciu różnych trybów dostępu i trybów udostępniania (dwDesiredAccess, dwShareMode odpowiednio). Nie ma znaczenia, w jakiej kolejności są wykonywane wywołania CreateFile. Jednak wszystkie kolejne operacje we/wy plików na każdym dojściu do pliku będą nadal ograniczone przez bieżące tryby dostępu i udostępniania skojarzone z tym konkretnym dojściem do pliku.
Pierwsze wywołanie metody CreateFile | Prawidłowe drugie wywołania CreateFile |
---|---|
GENERIC_READ, FILE_SHARE_READ |
|
GENERIC_READ, FILE_SHARE_WRITE |
|
GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE |
|
GENERIC_WRITE, FILE_SHARE_READ |
|
GENERIC_WRITE, FILE_SHARE_WRITE |
|
GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE |
|
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ |
|
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_WRITE |
|
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE |
|
Oprócz standardowych atrybutów pliku można również określić atrybuty zabezpieczeń, dołączając wskaźnik do struktury SECURITY_ATTRIBUTES jako czwarty parametr CreateFile. Jednak podstawowy system plików musi obsługiwać zabezpieczenia, aby mieć jakikolwiek wpływ (na przykład system plików NTFS obsługuje go, ale różne systemy plików FAT nie). Aby uzyskać więcej informacji na temat atrybutów zabezpieczeń, zobacz Access Control.
Aplikacja tworząca nowy plik może dostarczyć opcjonalny uchwyt do pliku szablonu, z którego CreateFile pobiera atrybuty pliku i atrybuty rozszerzone do tworzenia nowego pliku.
Scenariusze CreateFile
Istnieje kilka podstawowych scenariuszy inicjowania dostępu do pliku przy użyciu funkcji CreateFile. Są one podsumowane jako:
- Utworzenie nowego pliku, gdy plik o tej nazwie jeszcze nie istnieje.
- Utworzenie nowego pliku, nawet jeśli plik o tej samej nazwie już istnieje, wyczyszczenie jego danych i rozpoczęcie pustego.
- Otwieranie istniejącego pliku tylko wtedy, gdy jest i znajduje się w nienaruszonym stanie.
- Otwieranie istniejącego pliku tylko wtedy, gdy istnieje, obcinając go jako pusty.
- Otwarcie pliku zawsze: as-is, jeśli istnieje, lub utworzenie nowego, jeśli nie istnieje.
Te scenariusze są kontrolowane przez odpowiednie użycie parametru dwCreationDisposition. Poniżej przedstawiono podział sposobu mapowania tych scenariuszy na wartości dla tego parametru i tego, co się stanie, gdy są używane.
Podczas tworzenia lub otwierania nowego pliku, gdy plik o tej nazwie jeszcze nie istnieje (dwCreationDisposition ustawiony na CREATE_NEW, CREATE_ALWAYSlub OPEN_ALWAYS), funkcja CreateFile wykonuje następujące akcje:
- Łączy atrybuty i flagi pliku określone przez dwFlagsAndAttributes z FILE_ATTRIBUTE_ARCHIVE.
- Ustawia długość pliku na zero.
- Kopiuje atrybuty rozszerzone dostarczone przez plik szablonu do nowego pliku, jeśli określono parametr hTemplateFile (spowoduje to zastąpienie wszystkich flag FILE_ATTRIBUTE_* określonych wcześniej).
- Ustawia flagę dziedziczenia określoną przez element członkowski
bInheritHandle oraz deskryptor zabezpieczeń określony przez lpSecurityDescriptor elementu członkowskiegolpSecurityAttributes parametru ( struktury), jeśli podano.SECURITY_ATTRIBUTES
Podczas tworzenia nowego pliku, nawet jeśli plik o tej samej nazwie już istnieje (dwCreationDisposition ustawiony na CREATE_ALWAYS), funkcja CreateFile wykonuje następujące akcje:
- Sprawdza bieżące atrybuty pliku i ustawienia zabezpieczeń dotyczące dostępu do zapisu, zawodzi w przypadku odmowy.
- Łączy atrybuty i flagi pliku określone przez dwFlagsAndAttributes z FILE_ATTRIBUTE_ARCHIVE i istniejącymi atrybutami pliku.
- Ustawia długość pliku na zero (czyli wszystkie dane, które znajdowały się w pliku, nie są już dostępne i plik jest pusty).
- Kopiuje atrybuty rozszerzone dostarczone przez plik szablonu do nowego pliku, jeśli określono parametr hTemplateFile (spowoduje to zastąpienie wszystkich flag FILE_ATTRIBUTE_* określonych wcześniej).
- Ustawia flagę dziedziczenia określoną przez pole bInheritHandle parametru lpSecurityAttributes (strukturaSECURITY_ATTRIBUTES), jeśli została podana, ale ignoruje pole lpSecurityDescriptor struktury SECURITY_ATTRIBUTES.
- Jeśli w innych warunkach jest pomyślny (to znaczy, że CreateFile zwraca prawidłowy uchwyt), wywołanie GetLastError zwróci kod ERROR_ALREADY_EXISTS, mimo że w tym konkretnym przypadku użycia nie jest to w rzeczywistości błąd jako taki (jeśli zamierzasz utworzyć "nowy" (pusty) plik zamiast istniejącego).
Podczas otwierania istniejącego pliku (dwCreationDisposition ustawić wartość OPEN_EXISTING, OPEN_ALWAYSlub TRUNCATE_EXISTING), funkcja CreateFile wykonuje następujące akcje:
- Sprawdza bieżące atrybuty pliku i ustawienia zabezpieczeń dla żądanego dostępu, zakończy się niepowodzeniem, jeśli zostanie odmówiony.
- Łączy flagi plików (FILE_FLAG_*) określone przez dwFlagsAndAttributes z istniejącymi atrybutami pliku i ignoruje wszystkie atrybuty pliku (FILE_ATTRIBUTE_*) określone przez dwFlagsAndAttributes.
- Ustawia długość pliku na zero tylko wtedy, gdy dwCreationDisposition jest ustawiona na TRUNCATE_EXISTING, w przeciwnym razie bieżąca długość pliku jest utrzymywana i plik jest otwarty as-is.
- Ignoruje parametr hTemplateFile.
- Ustawia flagę dziedziczną określoną przez członek bInheritHandle parametru lpSecurityAttributes (strukturaSECURITY_ATTRIBUTES), jeśli została podana, ale ignoruje członek lpSecurityDescriptor struktury SECURITY_ATTRIBUTES.
Atrybuty i katalogi plików
Atrybuty pliku są częścią metadanych skojarzonych z plikiem lub katalogiem, z których każdy ma własny cel i reguły dotyczące sposobu ich ustawiania i zmieniania. Niektóre z tych atrybutów dotyczą tylko plików, a niektóre tylko do katalogów. Na przykład atrybut FILE_ATTRIBUTE_DIRECTORY ma zastosowanie tylko do katalogów: jest używany przez system plików w celu określenia, czy obiekt na dysku jest katalogiem, ale nie można go zmienić dla istniejącego obiektu systemu plików.
Niektóre atrybuty pliku można ustawić dla katalogu, ale mają znaczenie tylko dla plików utworzonych w tym katalogu, działając jako atrybuty domyślne. Na przykład FILE_ATTRIBUTE_COMPRESSED można ustawić na obiekcie katalogu, ale ponieważ sam obiekt katalogu nie zawiera żadnych rzeczywistych danych, nie jest on naprawdę skompresowany; jednak katalogi oznaczone tym atrybutem informują system plików o skompresowaniu wszystkich nowych plików dodanych do tego katalogu. Każdy atrybut pliku, który można ustawić w katalogu, a także zostanie ustawiony dla nowych plików dodanych do tego katalogu jest określany jako dziedziczony atrybut.
Funkcja CreateFile udostępnia parametr ustawiania niektórych atrybutów pliku podczas tworzenia pliku. Ogólnie rzecz biorąc, te atrybuty są najczęściej używane przez aplikację w czasie tworzenia pliku, ale nie wszystkie możliwe atrybuty pliku są dostępne do CreateFile. Niektóre atrybuty pliku wymagają użycia innych funkcji, takich jak SetFileAttributes, DeviceIoControllub DecryptFile po tym, jak plik już istnieje. W przypadku FILE_ATTRIBUTE_DIRECTORYfunkcja CreateDirectory jest wymagana w czasie tworzenia, ponieważ CreateFile nie może tworzyć katalogów. Inne atrybuty plików, które wymagają specjalnej obsługi, to FILE_ATTRIBUTE_REPARSE_POINT i FILE_ATTRIBUTE_SPARSE_FILE, które wymagają DeviceIoControl. Aby uzyskać więcej informacji, zobacz SetFileAttributes.
Jak wspomniano wcześniej, dziedziczenie atrybutów pliku występuje po utworzeniu pliku z atrybutami pliku odczytanymi z atrybutów katalogu, w których będzie znajdować się plik. W poniższej tabeli podsumowano te dziedziczone atrybuty i sposób ich powiązania z możliwościami CreateFile.
Stan atrybutu katalogu | możliwość nadpisania dziedziczenia dla CreateFile w nowych plikach |
---|---|
FILE_ATTRIBUTE_COMPRESSED ustawione. |
Brak kontroli. Użyj DeviceIoControl, aby wyczyścić |
FILE_ATTRIBUTE_COMPRESSED nie ustawiono. |
Brak kontroli. Ustaw DeviceIoControl. |
Ustawiono FILE_ATTRIBUTE_ENCRYPTED. |
Brak kontroli. Użyj DecryptFile. |
FILE_ATTRIBUTE_ENCRYPTED nie jest ustawione. |
Można ustawić przy użyciu CreateFile. |
ustaw FILE_ATTRIBUTE_NOT_CONTENT_INDEXED. |
Brak kontroli. Aby wyczyścić, użyj SetFileAttributes |
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED nie ustawiono. |
Brak kontroli. Użyj SetFileAttributes, aby ustawić. |