860 likes | 1.04k Views
Chapters 2-3. Input/Output With File and Directory Processing. OBJECTIVES (1 of 2). Upon completion of this Chapter you will be able to: Describe the Windows file systems Perform sequential file processing Perform console I/O and direct access file I/O Report and analyze system call errors
E N D
Chapters 2-3 Input/Output With File and Directory Processing
OBJECTIVES (1 of 2) • Upon completion of this Chapter you will be able to: • Describe the Windows file systems • Perform sequential file processing • Perform console I/O and direct access file I/O • Report and analyze system call errors • Describe and use Unicode characters and strings and write generic applications (both Unicode and ASCII characters) • Use Windows mandatory file locking to protect files from concurrent modification by several processes • Perform file and directory management
OBJECTIVES (2 of 2) • You will also be prepared for later Chapters • Memory-mapped files • Process management • Interprocess communication • Threads • Synchronization • Asynchronous I/O
AGENDA • Part I File Systems and Sequential I/O • Part II Unicode and Generic Characters • Part III Console I/O • Part IV Lab 2–A • Part V Direct File Access • Part VI File Locking • Part VII File and Directory Management Lab 3–B
Part I File Systems and Sequential I/O
BASIC I/O • Basic Windows API file processing functions: • CreateFile • ReadFile • WriteFile • CloseHandle • We used these, in a very simple program, in Chapter 1
THE FILE SYSTEMS • Windows File Systems • (Virtual) File Allocation Table File System (FAT, VFAT) • The only disk file system for floppies and Windows 9x • NTFS File System (NTFS) • Very large (“huge”) files, secure, robust • Supported on Windows NT (all versions) • CD-ROM File System (CDFS) • Custom file systems • Developed by software vendors
Windows FILE NAMING (1 of 2) • Hierarchical • Full pathname can start with a drive name • A:, C:, … • Or with a “share” name • \\servername\sharename • Pathname separator is a backslash — \ • You can also use / in C
Windows FILE NAMING (2 of 2) • Directory and file names cannot use ASCII 1–31 • Or any of < > : " | • But you can have blanks in file names • Case insensitive but case retaining • File, directory names up to 255 characters long • 250 in Windows 9x • A period . separates a file’s name from its extension • The period is in the name; there can be more than one • . and .. indicate the current directory and its parent
CREATING AND OPENING FILES • HANDLE CreateFile (LPCTSTR lpName, • DWORD dwAccess, DWORD dwShareMode, • LPSECURITY_ATTRIBUTES lpsa, DWORD dwCreate, • DWORD dwAttrsAndFlags, HANDLE hTemplateFile) • Return: A HANDLE to an open file object • INVALID_HANDLE_VALUE in case of failure • LPCTSTR will be described in Part II
CREATING AND OPENING FILES (2 OF 6) • Parameters • lpName • Pointer to the string naming the file • Length normally limited to 260 • \\?\ is an escape prefix allowing long NT path names • dwAccess • Access using GENERIC_READ or GENERIC_WRITE • Note: Flags can be combined with |
CREATING AND OPENING (3 OF 6) • dwShareMode • 0 — Cannot be shared; not even this process can open another handle • FILE_SHARE_READ — Other processes can read concurrently • FILE_SHARE_WRITE — Other processes can write concurrently • lpsa points to a SECURITY_ATTRIBUTES structure • NULL for now
CREATING AND OPENING (4 OF 6) • dwCreate — Create a file, overwrite one, etc. • CREATE_NEW — Fails if the file exists • CREATE_ALWAYS — An existing file will be overwritten • OPEN_EXISTING — Fail if the file does not exist • OPEN_ALWAYS — Open the file or create it if it doesn’t exist • TRUNCATE_EXISTING — File length will be set to zero • Note: There is no “open to append” mode • You will need to position to the end of file
CREATING AND OPENING (5 OF 6) • dwAttrsAndFlags — 16 flags and attributes including: • FILE_ATTRIBUTE_NORMAL — No other attributes are set • FILE_ATTRIBUTE_READONLY — Cannot write or delete • FILE_FLAG_OVERLAPPED • FILE_FLAG_SEQUENTIAL_SCAN and FILE_FLAG_RANDOM_ACCESS provide performance hints • Attributes are properties of the files themselves • Flags are associated with a specific HANDLE • Different HANDLEs to the same file can have different flags • Example: One HANDLE is “overlapped,” another not • Or, one has FILE_FLAG_SEQUENTIAL_SCAN and another FILE_FLAG_RANDOM_ACCESS
CREATING AND OPENING (6 OF 6) • File processing flags include: • FILE_FLAG_WRITE_THROUGH • FILE_FLAG_NO_BUFFERING • FILE_FLAG_DELETE_ON_CLOSE • hTemplateFile — Handle of an open GENERIC_READ file • Use the same attributes for the new file
READING FILES (1 OF 2) • BOOL ReadFile (HANDLE hFile, LPVOID lpBuffer, • DWORD nNumberOfBytesToRead, • LPDWORD lpNumberOfBytesRead, • LPOVERLAPPED lpOverlapped) • Return: TRUE if the read succeeds • Even if no bytes were read due to an attempt to read past the end of file • FALSE indicates an invalid handle, a handle without GENERIC_READ access, etc.
READING FILES (2 OF 2) • Parameters • hFile — File handle with GENERIC_READ access • lpBuffer — Memory buffer to receive the input data • nNumberOfBytesToRead • Number of bytes you expect to read • *lpNumberOfBytesRead • Actual number of bytes transferred • Zero indicates end of file • lpOverlapped • Points to OVERLAPPED structure (NULL for now)
WRITING FILES • BOOL WriteFile ( • HANDLE hFile, CONST VOID *lpBuffer, • DWORD nNumberOfBytesToWrite, • LPDWORD lpNumberOfBytesWritten, • LPOVERLAPPED lpOverlapped) • Return: TRUE if the function succeeds; FALSE otherwise
CLOSING FILES • BOOL CloseHandle (HANDLE hObject) • Return: TRUE if the function succeeds; FALSE otherwise • This function is general purpose and will be used to close handles to many different object types
COPYING FILES • BOOL CopyFile (LPCTSTR lpExistingFile, • LPCTSTR lpNewFile, BOOL fFailIfExists) • If a file with the new name already exists, it will be replaced only if fFailIfExists is FALSE • This is a “convenience function” and also provides performance
Part II Unicode and Generic Characters
UNICODE & GENERIC CHARACTERS • Windows NT supports 16-bit characters • WCHAR or wchar_t • To assure maximum flexibility and source portability, define all characters and strings using “generic” type TCHAR • Calculate lengths using sizeof(TCHAR) • Include #define UNICODE (to get WCHAR) in all source modules (or #undef UNICODE to get CHAR) • Be consistent • Define UNICODE before #include <windows.h> • Also define _UNICODE consistently for the generic C library
GENERIC CHARACTERS (2 of 3) • Use the “generic” C library for all string functions • _tprintf in place of printf • _stprintf in place of sprintf • _tcslen in place of strlen • _itot in place of itoa • And MANY more • See the on line help and the lab programs • Generic versions of some functions are not provided • e.g. memchr - Replacements are in the lab solutions
GENERIC CHARACTERS (3 of 3) • Constant strings in one of three forms (first 2 are ANSI C) • The last is a macro "This string uses 8-bit characters" L"This string uses 16-bit characters" _T ("This string uses generic characters") • Expands to “T…” if UNICODE is not defined; L”T…” if it is TEXT macro is the same as _T LPTSTR expands to either char * or wchar_t *
THE GENERIC C LIBRARY • Define _UNICODE consistently with UNICODE • This makes available a wide class of string processing and I/O functions _fgettc, _itot, _ttoi, _totupper, _totlower • And many more — nearly the complete library • Also, locale-specific functions (seven in all): lstrlen, lstrcmp, lstrcpy, lstrcat, … • Be sure to #include <tchar.h> after <windows.h> • Note: Any _ keyword or function is specific to Microsoft Visual C++ and the Microsoft compiler
GENERIC CHARACTERS AND THE MAIN PROGRAM • Windows main is for ASCII; wmain is for Unicode • In place of int main (argc, char * argv[]) • or int main (argc, w_char * argv[]) • Use #include <tchar.h> • /* this is after <windows.h> */ • ... int _tmain (int argc, LPTSTR argv[]) • The _tmain macro then expands to main or wmain • Depending on definition of _UNICODE • This assures correct operation in all circumstances and combinations
Part III Standard Devices and Console I/O
STANDARD DEVICESAND CONSOLE I/O (1 of 7) • HANDLE GetStdHandle (DWORD dwDevice) • Return: A valid handle or INVALID_HANDLE_VALUE for failure • BOOL SetStdHandle (DWORD IDStdHandle, • HANDLE hHandle) • Return: TRUE or FALSE indicating success or failure
STANDARD DEVICESAND CONSOLE I/O (2 of 7) • dwDevice and IDStdHandle • Must have one of these values: • STD_INPUT_HANDLE • STD_OUTPUT_HANDLE • STD_ERROR_HANDLE
STANDARD DEVICESAND CONSOLE I/O (3 of 7) • hHandle • Specifies an open file that is to be the standard device • Two reserved pathnames for console input (the keyboard): • "CONIN$" • and output (the display): • "CONOUT"
STANDARD DEVICESAND CONSOLE I/O (4 of 7) • BOOL SetConsoleMode (HANDLE hConsole, • DWORD fdevMode) • Return: TRUE if and only if the function succeeds • hConsole • Must have GENERIC_WRITE access
STANDARD DEVICESAND CONSOLE I/O (5 of 7) • fDevMode — How characters are processed • ENABLE_WINDOW_INPUT • ENABLE_LINE_INPUT • ENABLE_ECHO_INPUT • ENABLE_PROCESSED_INPUT • ENABLE_PROCESSED_OUTPUT • ENABLE_WRAP_AT_EOL_OUTPUT
STANDARD DEVICESAND CONSOLE I/O (6 of 7) • BOOL ReadConsole (HANDLE hConsoleInput, • LPVOID lpvBuffer, DWORD cchToRead, • LPDWORD lpcchRead, LPVOID lpvReserved) • Return: TRUE if and only if the read succeeds
STANDARD DEVICESAND CONSOLE I/O (7 of 7) • BOOL WriteConsole • Same as ReadConsole • BOOL FreeConsole (VOID) • BOOL AllocConsole (VOID)
EXAMPLE: PrintStrings (1 of 3) • #include "envirmnt.h" /* UNICODE is defined here */ • #include <windows.h> • BOOL PrintStrings (HANDLE hOut, ...) • /* Write the messages to the output handle (hOut) • Use WriteConsole (to handle Unicode & console • processing) first, as the output will normally • be the console. If that fails, use WriteFile. • hOut: Handle for output file. • ... : Variable argument list containing TCHAR • strings. The list must be terminated with NULL. */
PrintStrings (2 of 3) • { • DWORD MsgLen, Count; • BOOL Success = TRUE; • LPCTSTR pMsg; • va_list pMsgList; /* Current message string */ • va_start (pMsgList, hOut); • /* Start processing msgs */ • while (((pMsg = va_arg (pMsgList, LPCTSTR)) != NULL) • && Success) • { • MsgLen = _tcslen (pMsg); • (CONTINUED)
PrintStrings (3 of 3) • /* WriteConsole fails if the handle is associated • with a file rather than with a console */ • if ( !WriteConsole (hOut, pMsg, • MsgLen, &Count, NULL) && • !WriteFile (hOut, pMsg, • MsgLen * sizeof (TCHAR), &Count, NULL)) • return FALSE; • } /* End of while loop - process next message */ • va_end (pMsgList); • return TRUE; • }
EXAMPLE: ReportError (1 of 4) • OBJECTIVE: • Turn system call errors into meaningful text strings • And print the text • Terminate the program if the error is fatal • Similar to perror(), but it works in the multithreaded Windows environment.
EXAMPLE: ReportError (2 of 4) • #include "envirmnt.h" • #include <windows.h> • #include "support.h" • VOID ReportError (LPCTSTR UserMessage, • DWORD ExitCode, BOOL PrintErrorMsg) • /* General-purpose function to report system errors. • Obtain the error number and turn it into the • system error message. Display this information • and the user specified message to the standard • error device. • UserMessage: Message to be displayed to • standard error device. */
ReportError (3 of 4) • ExitCode: 0 - Return • > 0 - ExitProcess with this code • PrintErrorMessage: Display the last system error • message if this flag is set. */ • { • DWORD eMsgLen, ErrNum = GetLastError (); • LPVOID lpvSysMsg; • HANDLE hStdErr = GetStdHandle (STD_ERROR_HANDLE); • PrintMsg (hStdErr, UserMessage); • if (PrintErrorMsg) {
ReportError (4 of 4) • eMsgLen = FormatMessage ( • FORMAT_MESSAGE_ALLOCATE_BUFFER | • FORMAT_MESSAGE_FROM_SYSTEM, • NULL, ErrNum, • MAKELANGID (LANG_DFLT, SUBLANG_DFLT), • &lpvSysMsg, 0, NULL); • PrintStrings (hStdErr, TEXT ("\n"), • lpvSysMsg, TEXT ("\n"), NULL); • HeapFree (GetProcessHeap (), 0, lpvSysMsg); • } • if (ExitCode > 0) • ExitProcess (ExitCode); • else • return; • }
LAB 2–A (Option 1) • Modify the copy program in Chapter 1 to create the program cpCF which will: • Take the input and output files from the command line • Use the generic macro_tmain • Report all system errors using ReportError () • Use the CopyFile function • Prompt the user to see if an existing file should be overwritten.
LAB 2–A (Option 2) • Create a program, atou, which behaves just like cpexcept that the input file is assumed to be in ASCII and the output file will be the Unicode equivalent (and twice as long as the original). Include the asc2un.c source file in your project. • We will build several variations of this program during the course to illustrate different file processing techniques.
LAB 2–A (Option 3) • Create a program, cat, that takes multiple file names from the command line and copies them, in order, to standard output. If there are no file names on the command line, use standard input. • This program will be required with several future labs. • Addtional Note: You will find it convenient to put your working programs (.EXE files) in a common directory, such as RUN (Provided with the solutions).
Part V Direct File Access
FILE POINTERS (1 of 4) • DWORD SetFilePointer (HANDLE hFile, • LONG lDistanceToMove, • PLONG lpDistanceToMoveHigh, • DWORD dwMoveMethod) • Return: The low-order DWORD (unsigned) of the new file pointer. The high-order portion of the new file pointer goes to the DWORD indicated by lpDistanceToMoveHigh (if non-NULL). In case of error, the return value is OxFFFFFFFF. • Note: The file pointer is associated with the HANDLE, not the file. The pointer advances with each read and write.
FILE POINTERS (2 of 4) • Note: NTFS is a 64-bit file system, so file pointers are 64 bits long. The file pointer is specified with two 32-bit parts. • Large files are increasingly important in many applications • But many users will only require “short” (< 4GB) files • SetFilePointer Parameters • hFile — Handle of an open file with read and/or write access • lDistanceToMove — LONG signed distance to move or unsigned file position
FILE POINTERS (3 of 4) • *lpDistanceToMoveHigh • High-order portion of the move distance • Can be NULL for “small” files • dwMoveMethod — Specifies one of these modes: • FILE_BEGIN — Position from the start of file • FILE_CURRENT — Move pointer forward or backward • FILE_END — Position backward from end of file • SetEndOfFile () function resizes the file based on the current file pointer
FILE POINTERS (4 of 4) • Use the LARGE_INTEGER data type (union) for 64-bit file positions • Example coming up • Members: • LONGLONG Quadpart Do the 64-bit arithmetic here • DWORD LowPart • LONG HighPart
Alternative Direct File Access Using the Overlapped Structure (1 of 2) • Example: Use the Offset fields in the overlapped structure • Offset Low order 32 bits • OffsetHigh High order 32 bits • hEvent Must be NULL. This field is used with asynchronous I/O • Two reserved fields Do not use!! • The example shows how to update a record in a file