Работа с файлами.
Знаю, что прошу очень многого, но помогите, пожалуйста, чайнику.
Я совсем не знаю winAPI, а надо за 2 недели написать программу демонстрирующую работу с файлами в асинхронном режиме. Срада разработки VS 2008. Язык C++.
Я точно не успею разобраться со всем. :facepalm: Помогите!
Большое спасибо.
В интернете искала. Ничего доступного не нашла.
Еще проблема при очистке буфера. Выдает ошибку. Не понимаю почему.
#include "stdafx.h"
#include "resource.h"
HINSTANCE hThisInstance;
TCHAR filename[MAX_PATH]; /*буфер имени файла*/
LRESULT CALLBACK MainProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,int) {
hThisInstance=hInst;
DialogBox(hInst, MAKEINTRESOURCE(MnWnd),NULL,(DLGPROC)MainProc);
}
/* диалоговая процедура */
LRESULT CALLBACK MainProc(HWND hw,UINT msg,WPARAM wp,LPARAM lp)
{
static DWORD OldIcon=0; /* id старой иконки диалога */
static OPENFILENAME of;
OVERLAPPED olr;
OVERLAPPED olw;
PCTSTR* bufr;
PCTSTR* bufw;
HANDLE hf;
DWORD len,len1;
switch (msg) {
case WM_INITDIALOG: /* меняем иконку диалога */
OldIcon=SetClassLong(hw,GCL_HICON,(long)LoadIcon(hThisInstance,MAKEINTRESOURCE(MyIcon)));
return TRUE;
case WM_COMMAND:
switch (LOWORD(wp)) {
case IDCANCEL: /* посылается при закрытии диалога по [Esc]*/
case ID_EXIT: /* команда меню "ВЫход" */
DestroyWindow(hw);
break;
case ID_OPEN: /* команда меню "Открыть" */
of.lStructSize=OPENFILENAME_SIZE_VERSION_400A;
of.hwndOwner=hw;
of.lpstrFilter=_T("Text Files (*.TXT)\0*.txt\0");
of.lpstrCustomFilter=NULL;
of.nMaxCustFilter=0;
of.nFilterIndex=1;
of.lpstrFile=filename;
of.nMaxFile=MAX_PATH;
of.lpstrFileTitle=NULL;
of.nMaxFileTitle=0;
of.lpstrInitialDir=NULL;
of.Flags=OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
if (!GetOpenFileName(&of)) break;
SetDlgItemText(hw,ID_STATUS,filename);
/* открываем файл */
hf=CreateFile(filename,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
if (hf==INVALID_HANDLE_VALUE) {
MessageBox(hw,_T("Ошибка открытия"),_T("Error"),MB_ICONHAND|MB_OK);
break;
}
len=GetFileSize(hf,NULL);
bufr=(PCTSTR*)malloc(len+1); /* доп. байт под символ-терминатор (0) */
if (!bufr) {
MessageBox(hw,_T("Ошибка выделения памяти"),_T("Error"),MB_ICONHAND|MB_OK);
break;
}
olr.Offset=0;
olr.OffsetHigh=0;
olr.hEvent=0;
ReadFile(hf,LPWSTR(bufr),len,NULL,&olr);
//bufr[len+1]='\0';
CloseHandle(hf);
SetDlgItemText(hw,ID_EDIT,LPWSTR(bufr));
free(bufr);
break;
case ID_SAVEAS: /* команда меню "Сохранить как" */
of.lStructSize=OPENFILENAME_SIZE_VERSION_400A;
of.hwndOwner=hw;
of.lpstrFilter=_T("Text Files (*.TXT)\0*.txt\0");
of.lpstrCustomFilter=NULL;
of.nMaxCustFilter=0;
of.nFilterIndex=1;
of.lpstrFile=filename;
of.nMaxFile=MAX_PATH;
of.lpstrFileTitle=NULL;
of.nMaxFileTitle=0;
of.lpstrDefExt = _T("txt") ;
of.lpstrInitialDir=NULL;
of.Flags=OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY;
if (!GetSaveFileName(&of)) break;
case ID_SAVE: /* команда меню "Сохранить" */
if (lstrlen(filename)==0) {
/* для нового файла - вызываем диалог "Сохранить как" */
PostMessage(hw,WM_COMMAND,ID_SAVEAS,lp);
break;
}
SetDlgItemText(hw,ID_STATUS,filename);
/* сохраняем файл */
hf=CreateFile(filename,GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL);
if (hf==INVALID_HANDLE_VALUE) {
MessageBox(hw,_T("Ошибка сохранения"),_T("Error"),MB_ICONHAND|MB_OK);
break;
}
len=SendDlgItemMessage(hw,ID_EDIT,WM_GETTEXTLENGTH,0,0);
bufw=(PCTSTR*)malloc(len+1); /* доп. байт под символ-терминатор (0) */
GetDlgItemText(hw,ID_EDIT,LPWSTR(bufw),len+1);
if (!bufw) {
MessageBox(hw,_T("Ошибка выделения памяти"),_T("Error"),MB_ICONHAND|MB_OK);
break;
}
bufw[len+1]='\0';
olw.Offset=0;
olw.OffsetHigh=0;
olw.hEvent=0;
WriteFile(hf,bufw,sizeof(bufw)+1,NULL,&olw);
CloseHandle(hf);
//free(bufw);
break;
case ID_about : /* команда меню "About" */
MessageBox(hw,_T("Асинхронный доступ к файлам"),_T("О программе..."),MB_OK|MB_ICONINFORMATION);
break;
}
return TRUE;
case WM_DESTROY: /* при закрытии окна восстанавливаем старую иконку */
SetClassLong(hw,GCL_HICON,(long)OldIcon);
PostQuitMessage(0);
return TRUE;
}
return FALSE;
}
Подскажите, а как узнать размер файла в байтах? и возможно ли сразу "запихнуть" весь файл в буфер (как это пытаюсь сделать я) или это тоже бывает причиной ошибки?
еще. почему могут вызываться ошибки в строке free(bufw). вроде бы так нада же уничтожать буфер?
Подскажите, а как узнать размер файла в байтах?
Используйте MSDN GetFileSizeEx
и возможно ли сразу "запихнуть" весь файл в буфер (как это пытаюсь сделать я) или это тоже бывает причиной ошибки?
При небольших размерах файла возможно и приемлемо.
еще. почему могут вызываться ошибки в строке free(bufw). вроде бы так нада же уничтожать буфер?
Уничтожать надо. Скорее всего портится куча, но без конкретики сказать невозможно.
2. По поводу памяти: если вы выделяете память для массива длиной (len + 1) символов (нужно именно символов, а не байт как у вас), то максимальный доступный индекс массива будет len, но не len + 1.
bufw в данном случае является указателем, sizeof(bufw) даст вам размер указателя (4 байта, по-моему). Зачем вообще это нужно, если размер буфера определен у вас как len + 1?
Тип PCTSTR сам по себе уже является указателем на строку. Вы здесь выделяете память для массива строк.
Если я правильно понял, "файлом" в данном случае вы называете содержимое ID_EDIT, размер которого вы узнаете в символах, а хотите в байтах? Если да, то можно просто умножить len на sizeof(TCHAR). Не забудьте, что в len не входит 0-терминатор, а его размер тоже составляет sizeof(TCHAR). В общем, должно быть так:
LRESULT strLen = SendDlgItemMessage(hw, ID_EDIT, WM_GETTEXTLENGTH, 0, 0);
strBuf = (LPTSTR)malloc(sizeof(TCHAR) * (strLen + 1));
GetDlgItemText(hw, ID_EDIT, strBuf, strLen + 1);
strBuf[strLen] = TEXT('\0');
size_t bufLen;
StringCbLength(strBuf, STRSAFE_MAX_CCH, &bufLen);
WriteFile(hf, (PBYTE)strBuf, bufLen, NULL, &olw);
free(strBuf);
P.S. Для использования безопасных строковых функций подключите хэдер <strsafe.h>
Буду разбираться.