Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Microsoft visual C++ и MFC

© Александр Фролов, Григорий Фролов
Том 24, М.: Диалог-МИФИ, 1993.

[Назад] [Содеожание] [Дальше]

Файловая система - класс CStdioFile

Если вы привыкли пользоваться функциями потокового ввода/вывода из стандартной библиотеки трансляторов Си и Си++, обратите внимание на класс CStdioFile XE "CStdioFile" , наследованный от базового класса CFile. Этот класс позволяет выполнять буферизованный ввод/вывод в текстовом и двоичном режиме.

CStdioFile <- CFile <- CObject

В текстовом режиме выполняется специальная обработка символов возврата каретки и перевода строки. Когда в файл, открытый в текстовом режиме, записывается символ перевода строки \n (код 0x0A), он преобразуется в два символа - символ перевода строки (код 0x0A) и символ возврата каретки (код 0x0D). И наоборот, когда из файла считывается пара символов перевода строки и возврата каретки, они преобразуются в один символ перевода строки.

Для объектов класса CStdioFile можно вызывать все методы его базового класса CFile, кроме методов Duplicate, LockRange и UnlockRange. Напомним, что класс CMemFile, также наследованный от базового класса CFile, тоже работает с этими методами.

В класс CStdioFile входит элемент данных m_pStream, который содержит указатель на открытый файл. Если объект CStdioFile создан, но файл либо еще не открыт, либо закрыт, тогда m_pStream содержит константу NULL.

Класс CStdioFile имеет три различных конструктора. Первый конструктор класса CStdioFile не имеет параметров:

CStdioFile();

Этот конструктор только создает объект класса, но не открывает никаких файлов. Чтобы открыть файл, надо вызвать метод Open базового класса CFile.

Второй конструктор класса CStdioFile можно вызывать, если файл уже открыт и вам надо создать новый объект класса и связать с ним открытый файл:

CStdioFile(FILE* pOpenStream);

Этот конструктор можно использовать, если файл был открыт стандартной функцией fopen.

Параметр pOpenStream должен содержать указатель на файл, полученный вызовом стандартной функции fopen.

Третий, последний конструктор можно использовать, если надо создать объект класса CStdioFile, открыть новый файл и связать его с только что созданным объектом:


CStdioFile(LPCTSTR lpszFileName, UINT nOpenFlags);
	throw(CFileException);

Если указанный файл не может быть открыт, вызывается исключение CFileException.

Параметр lpszFileName должен содержать указатель на строку с именем файла. Можно указать полный путь файла, а не только его имя. Параметр nOpenFlags определяет режим, в котором будет открыт файл. Возможные значения этого параметра были описаны ранее (см. Метод Open класса CFile).

Для чтения и записи в текстовый файл класс CStdioFile включает два новых метода ReadString и WriteString. Метод ReadString позволяет прочитать из файла строку символов, а метод WriteString - записать.

Метод ReadString имеет две формы. Первая используется для чтения строк из файла в буфер памяти, а вторая для чтения строк и записи их в объект класса CString.

Вот описание первой формы метода ReadString:


virtual LPTSTR ReadString(LPTSTR lpsz, UINT nMax);
	throw(CFileException);

Из открытого файла считывается текстовая строка и записывается в буфер lpsz. Считается, что строка файла оканчивается символами перевода строки и возврата каретки. В конец строки, записанной в буфер lpsz, заносится символ двоичного нуля (\0).

Максимальное количество считываемых символов определяется параметром nMax. Если в строке файла больше, чем nMax - 1 байт, то остальные символы не будут прочитаны. Метод ReadString возвращает указатель на прочитанную строку или NULL, если достигнут конец файла.

Вторая форма метода ReadString не намного отличается от первой. Вместо двух параметров lpsz и nMax указывается один параметр rString, указывающий на объект класса CString, в который будет записана строка, прочитанная из файла:


BOOL ReadString(CString& rString);
	throw(CFileException);

Еще одно отличие второй формы метода ReadString заключается в типе возвращаемого им значения. Если достигнут конец файла, то вторая форма метода ReadString возвращает константу FALSE.

Для записи в файл текстовой строки предназначен метод WriteString:


virtual void WriteString(LPCTSTR lpsz);
	throw(CFileException);

В качестве параметра lpsz этого метода надо указать адрес буфера с текстовой строкой, закрытой символом \0. Символ \0 не записывается в файл. Если в текстовой строке lpsz есть символы перевода строки, они записываются как пара символов возврата каретки и перевода строки.

Метод WriteString может вызвать исключение, если во время записи в файл произойдет ошибка, например переполнение диска.

Приложение TestFile

Теперь мы представим вам приложение, которое использует класс CStdioFile для записи в файл информации о файловой системе компьютера. Для определения характеристик файловой системы мы воспользовались функцией GetVolumeInformation из программного интерфейса Win32.

Эта функция позволяет определить различные характеристики файловой системы, установленной на данном томе. Ниже представлен прототип функции GetVolumeInformation:


BOOL GetVolumeInformation(
	LPCTSTR	lpRootPathName, 
	LPTSTR	lpVolumeNameBuffer, 
	DWORD  	nVolumeNameSize, 
	LPDWORD	lpVolumeSerialNumber, 
	LPDWORD	lpMaximumComponentLength,
	LPDWORD	lpFileSystemFlags, 
	LPTSTR	lpFileSystemNameBuffer, 
	DWORD 	nFileSystemNameSize 
);	

Первый параметр lpRootPathName перед вызовом функции должен указывать на строку, содержащую путь корневого каталога тома, информацию о котором надо получить. Если вы присвоите lpRootPathName значение NULL, по умолчанию будет выбран корневой каталог текущего тома.

Параметр lpVolumeNameBuffer должен содержать указатель на буфер, в который будет записано имя тома. Длина буфера определяется параметром nVolumeNameSize. Если вас не интересует имя тома, вы можете указать для параметра lpVolumeNameBuffer значение NULL. В этом случае значение nVolumeNameSize не используется.

Параметр lpVolumeSerialNumber должен содержать адрес переменной типа DWORD, в которую будет записан серийный номер тома. Если вас не интересует серийный номер, вы можете указать для параметра значение NULL.

Параметр lpMaximumComponentLength должен содержать адрес переменной, в которую будет записана максимальная длина файла, для данной файловой системы. Для операционной системы Windows 95 эта переменная будет содержать значение 255, несмотря на то, что тип файловой системы остался FAT.

Параметр lpFileSystemFlags указывает на переменную, которая может быть одной или комбинацией нескольких констант, перечисленных в следующей таблице.

Константа

Описание

FS_CASE_IS_PRESERVED

При записи файлов на диск сохраняется написание (заглавные и прописные символы) имени файла

FS_CASE_SENSITIVE

Файловая система различает заглавные и прописные символы в именах файлов

FS_UNICODE_STORED_ON_DISK

Файловая система обеспечивает кодировку имен файлов Unicode

FS_FILE_COMPRESSION

Обеспечивается возможность сжатия отдельных файлов, расположенных на томе. Эта константа не может быть использована вместе с другими

FS_VOL_IS_COMPRESSED

Данный том является компрессованным. Такой том может быть создан системами типа DoubleSpace. Эта константа не может быть использована вместе с другими

Параметр lpFileSystemNameBuffer содержит указатель на буфер, в который будет записан тип файловой системы. В зависимости от типа файловой системы, установленной на данном томе, это может быть FAT, NTFS или HPFS XE "HPFS" .

Размер буфера определяется параметром nFileSystemNameSize. Если вас не интересует тип файловой системы, запишите в параметр lpFileSystemNameBuffer значение NULL.

Если функция GetVolumeInformation завершилась без ошибок, она возвращает значение TRUE. В противном случае возвращается значение FALSE, а для получения дополнительной информации вы можете вызвать функцию GetLastError.

В листинге 3.1 представлен исходный текст приложения TestFile. В этом приложении используются всего несколько классов библиотеки классов MFC. Для организации самого приложения мы наследовали от базового класса CWinApp XE "CWinApp" главный класс приложения CMFStartApp. Класс CWinApp был описан нами ранее в разделе “Приложение MFStart”.

В классе CMFStartApp определены два метода: InitInstance и FileSystemInfo. Метод InitInstance является переопределением виртуального метода InitInstance базового класса CWinApp. Этот метод вызывается каждый раз при запуске приложения. Мы используем метод InitInstance для того, чтобы вызвать метод FileSystemInfo и сразу завершить работу приложения.

Метод FileSystemInfo получает данные о файловой системе текущего тома и записывает их в файл fsystem.dat в текущем каталоге. Для получения информации о файловой системе используется функция GetVolumeInformation, описанная выше.

Данные, полученные функцией FileSystemInfo, временно заносятся в строку strTmpOut класса CString. При этом используется метод Format, чтобы получить форматированную запись, содержащую дополнительное текстовое описание.

Для записи в файл мы создали объект класса CStdioFile. В конструкторе мы сразу указали имя файла, который надо создать и открыть. Все операции с файлом, включая его создание, выполняются в блоке try. В случае возникновении ошибки во время создания или других операций с файлом вызывается исключение, которое будет обработано блоком catch.

Мы специально создаем файл и открываем его, используя конструктор класса CStdioFile, а не метод Open. Метод Open в случае возникновения ошибки возвращает соответствующее значение, но не вызывает исключение. Поэтому надо было бы специально проверять значение возвращаемое методом Open.

Для записи в файл мы вызываем метод WriteString, передавая ему в качестве параметра строку strTmpOut, которая содержит данные подготовленные для записи. Каждый вызов метода WriteString записывает в файл одну строку, так как в конце strTmpOut мы всегда записываем символ перевода строки.

Чтобы закрыть файл, мы используем метод Close базового класса CFile. В случае успешного завершения на экране отображается сообщение с именем файла fsystem.dat и управление возвращается методу InitInstance.

Если при работе с файлом возникла ошибка, управление передается блоку catch. В нем отображается сообщение об ошибке, а затем управление сразу возвращается методу InitInstance. Невыполненная часть блока try игнорируется.

Листинг 3.1. Файл TestFile.cpp


// Включаемый файл для MFC
#include 

//===================================================== 
// Главный класс приложения CMFStartApp
//===================================================== 
class CMFStartApp : public CWinApp
{
public:
	virtual BOOL	InitInstance();
	void					FileSystemInfo();
};
 
// Создаем объект приложение класса CMFStartApp
CMFStartApp MFStartApp;
 
//===================================================== 
// Переопределяем виртуальный метод InitInstance
// класса CWinApp
//===================================================== 
BOOL CMFStartApp::InitInstance()
{
	// Определяем характеристики файловой системы
	FileSystemInfo();	

	// Завершаем приложение
	return FALSE;
}

//===================================================== 
// Метод FileSystemInfo главного класса приложения
// Определяет характеристики текущего тома и записывает 
// их в файл 
//===================================================== 
void CMFStartApp::FileSystemInfo() 
{

	// Метка тома
	CString	VolumeNameBuffer;

	// Максимальная длина метки тома
	DWORD	nVolumeNameSize = 100;	

	// Серийный номер тома
	DWORD	VolumeSerialNumber;

	// Максимальная длина имени файла
	DWORD	MaximumComponentLength;

	// Характеристики файловой системы
	DWORD	FileSystemFlags;

	// Тип файловой системы
	CString	FileSystemNameBuffer;

	// Максимальная длина строки типа файловой системы
	DWORD	nFileSystemNameSize = 100;

	// Получаем данные о файловой системе и текущем устройстве
	GetVolumeInformation(
		NULL, 
		VolumeNameBuffer.GetBuffer(nVolumeNameSize), 
		nVolumeNameSize, 
		&VolumeSerialNumber,
		&MaximumComponentLength, &FileSystemFlags,
		FileSystemNameBuffer.GetBuffer(nFileSystemNameSize),
		nFileSystemNameSize );

	// Снимаем блокировку буферов 
	VolumeNameBuffer.ReleaseBuffer();
	FileSystemNameBuffer.ReleaseBuffer();

	// Обрабатываем ошибочные ситуации, которые могут 
	// возникнуть при работе с файлами
	try
	{
		// Создаем файл fsystem.dat и открываем его для записи
		CStdioFile file("fsystem.dat", 
			CFile::modeCreate | 
			CFile::modeWrite | 
			CFile::typeText);

		// Временная строка, используемая для записи в файл
		CString	strTmpOut;

		// Увеличиваем размер буфера до 512 байт
		strTmpOut.GetBuffer(512);

		// Записываем в файл метку тома
		strTmpOut.Format("Метка тома: %s \n", VolumeNameBuffer);
		file.WriteString(strTmpOut);

		// Записываем в файл серийный номер
		strTmpOut.Format("Серийный номер: %X \n", 
			VolumeSerialNumber);

		file.WriteString(strTmpOut);

		// Записываем в файл тип файловой системы
		strTmpOut.Format("Тип файловой системы: %s \n", 
			FileSystemNameBuffer);

		file.WriteString(strTmpOut);
	
		// Записываем в файл максимальную длину имени файла
		strTmpOut.Format("Максимальная длина имени файла: %d \n", 
			MaximumComponentLength);

		file.WriteString(strTmpOut);
		
		// Записываем в файл свойства файловой системы
		strTmpOut = "Свойства файловой системы \n";

		if(FileSystemFlags & FS_CASE_IS_PRESERVED)
			strTmpOut += "   FS_CASE_IS_PRESERVED\n";

		if(FileSystemFlags & FS_CASE_SENSITIVE)
			strTmpOut += "   FS_CASE_SENSITIVE\n";
	
		if(FileSystemFlags & FS_UNICODE_STORED_ON_DISK)
			strTmpOut += "   FS_UNICODE_STORED_ON_DISK\n";
	
		if(FileSystemFlags & FS_PERSISTENT_ACLS)
			strTmpOut += "   FS_PERSISTENT_ACLS\n";
	
		if(FileSystemFlags & FS_FILE_COMPRESSION)
			strTmpOut += "   FS_FILE_COMPRESSION\n";

		if(FileSystemFlags & FS_VOL_IS_COMPRESSED)
			strTmpOut += "   FS_VOL_IS_COMPRESSED\n";

		file.WriteString(strTmpOut);	
	
		// Закрываем файл
		file.Close();
		// Отображаем сообщение об успешном завершении приложения
		MessageBox(NULL, "File fsystem.dat", "Message", MB_OK);
	}

	// Обработчик исключения. Вызывается при ошибках 
	// работы с файлами
	catch(...)
	{
		// Отображаем сообщение о возникшей ошибке 
		MessageBox(NULL, "File I/O Error", "Error", MB_OK);
	}

	return;
}

Файл fsystem.dat, созданный приложением, можно просмотреть в любом текстовом редакторе, например Notepad или WordPad. В листинге 3.2 приведен пример файла, полученного при помощи приложения TestFile на нашем компьютере, на котором установлена операционная система Windows 95.

Листинг 3.2. Файл fsystem.dat


Метка тома:  LIBRARY
Серийный номер: 1D794E8D 
Тип файловой системы: FAT 
Максимальная длина имени файла: 255 
Свойства файловой системы 
   FS_CASE_IS_PRESERVED
   FS_UNICODE_STORED_ON_DISK
[Назад] [Содеожание] [Дальше]