Чтение и запись в файл
От: dina89  
Дата: 09.01.12 07:20
Оценка:
Надо продемонстрировать асинхронный доступ к файлу. Программа не совсем корректная в этом плане. но.
Вопрос вот в чем: при чтении файла и отображении его в edit получается абракодабра. Я так понимаю проблема в типе буфера и что-то с Ascii и Unicode кодировке. Наверное. Посмотрите, пожалуйста, в чем ошибка.

Еще проблема при очистке буфера. Выдает ошибку. Не понимаю почему.


#include "windows.h"
#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;
}
Re: Чтение и запись в файл
От: GrayWolf Россия https://kini24.ru
Дата: 09.01.12 07:50
Оценка: 3 (1)
Здравствуйте, dina89, Вы писали:

D> case WM_COMMAND:

D> switch (LOWORD(wp)) {
D> case IDCANCEL: /* посылается при закрытии диалога по [Esc]*/
D> case ID_EXIT: /* команда меню "ВЫход" */
D> DestroyWindow(hw);
D> break;

Диалоги закрываются по EndDialog().

D> case ID_OPEN: /* команда меню "Открыть" */

D> ....
D> /* открываем файл */
D> hf=CreateFile(filename,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);

Указываете FILE_FLAG_OVERLAPPED, но не указываете структуру. Тут могу ошибаться, асинхронный ни разу не использовал, правлю по памяти.

D> ....

D> len=GetFileSize(hf,NULL);
D> bufr=(PCTSTR*)malloc(len+1); /* доп. байт под символ-терминатор (0) */

Не нравится мне выделение памяти чем-то, хоть убейте. Вероятно тем, что выделяется память под набор строк, а не символов.

D> ReadFile(hf,LPWSTR(bufr),len,NULL,&olr);


Тут можно использовать одну структуру OVERLAPPED, которую вы указали при открытии файла.

D> hf=CreateFile(filename,GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL);


Аналогично похожей записи на открытие для чтения, "претензия" та же.

D> WriteFile(hf,bufw,sizeof(bufw)+1,NULL,&olw);


И вот тут расхождение: читаете вы unicode, а записываете в ansi. Для unicode-файлов требуется в начало записать два байта-сигнала: 0xFF и 0xFE.
Re: Чтение и запись в файл
От: Аноним  
Дата: 09.01.12 08:49
Оценка: 2 (1)
D>Вопрос вот в чем: при чтении файла и отображении его в edit получается абракодабра. Я так понимаю проблема в типе буфера и что-то с Ascii и Unicode кодировке. Наверное.

D>
D>     WriteFile(hf,bufw,sizeof(bufw)+1,NULL,&olw);
D>


sizeof от указателя на строку это не размер строки.
Re[2]: Чтение и запись в файл
От: dina89  
Дата: 09.01.12 12:11
Оценка:
Подскажите, пожалуйста, какого типа лучше задать буфер.
у меня: PCTSTR* bufr;
может лучше другой тип? я пробовала CHAR — возникают проблемы...
Re[2]: Чтение и запись в файл
От: dina89  
Дата: 09.01.12 12:20
Оценка:
Здравствуйте, Аноним, Вы писали:


D>>Вопрос вот в чем: при чтении файла и отображении его в edit получается абракодабра. Я так понимаю проблема в типе буфера и что-то с Ascii и Unicode кодировке. Наверное.


D>>
D>>     WriteFile(hf,bufw,sizeof(bufw)+1,NULL,&olw);
D>>


А>sizeof от указателя на строку это не размер строки.


Подскажите, как определить размер буфера? Т.е. фактически размер файла.
И еще правильно ли я считываю файл? Мне надо прочитать весь файл до конца и я его сразу пытаюсь запихнуть в буфер. Может надо как-то по частям в цикле считывать? (только я не знаю как)
Re[2]: Чтение и запись в файл
От: dina89  
Дата: 09.01.12 12:27
Оценка:
Здравствуйте, GrayWolf, Вы писали:

D>> ....

D>> len=GetFileSize(hf,NULL);
D>> bufr=(PCTSTR*)malloc(len+1); /* доп. байт под символ-терминатор (0) */

GW>Не нравится мне выделение памяти чем-то, хоть убейте. Вероятно тем, что выделяется память под набор строк, а не символов.


Мне этот момент тоже не нравится. Но не знаю как правильно сделать. Никак не могу одолеть WinAPI. Может надо буфер сделать символьным (CHAR) и bufr=(CHAR)malloc(len+1);
Только при создании символьного буфера надо указать заранее размер, который я не знаю, пока файл не открыт.


D>> WriteFile(hf,bufw,sizeof(bufw)+1,NULL,&olw);


GW>И вот тут расхождение: читаете вы unicode, а записываете в ansi. Для unicode-файлов требуется в начало записать два байта-сигнала: 0xFF и 0xFE.


Как это делается? так:

WriteFile(hf,'0xFF',1 ,NULL,&olw);
WriteFile(hf,'0xFE',1 ,NULL,&olw);
WriteFile(hf,bufw,sizeof(bufw)+1,NULL,&olw);
Re[3]: Чтение и запись в файл
От: Аноним  
Дата: 09.01.12 15:08
Оценка:
D>Еще проблема при очистке буфера. Выдает ошибку. Не понимаю почему
WM_GETTEXTLENGTH возвращает размер в символах (GetDlgItemText, кстати, тоже работает с символами). А malloc выделяет байтами — отсюда переполнение буфера

D>Подскажите, как определить размер буфера? Т.е. фактически размер файла.

Умножить количество символов на размер одного символа
Для формирования корректного txt-файла нужно записать в начало файла префикс (как указано в параллельной ветке)


D>И еще правильно ли я считываю файл? Мне надо прочитать весь файл до конца и я его сразу пытаюсь запихнуть в буфер. Может надо как-то по частям в цикле считывать? (только я не знаю как)

Это решать разрабочику: можно весь, можно частями.

P.S. Лабораторную работу тут за вас никто писать не будет
тие
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.