CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Problem z FileSeek i FileOpen
Strona 1 z 1

Problem z FileSeek i FileOpen

Nowy postNapisane: niedziela, 5 maja 2019, 09:12
przez lukagrom
Stworzyłem sobie prostą klasę (wykorzystującą mechanizmy - FileOpen, FileSeek), która służy do zwracania zawartości tekstowej teksu z otwieranego pliku (nazwa pliku w konstruktorze klasy).
KOD cpp:     UKRYJ  
class read_File
{
        private:
        int size;
        int  handle;
        wchar_t *buf;
        UnicodeString name_File;
        UnicodeString result;
        public:
        read_File(UnicodeString my_File)
        {
                name_File=my_File;
                handle=FileOpen(name_File.w_str(), fmOpenRead);
                size=FileSeek(handle,0,2);

        }
        UnicodeString Write()
        {       if(size==-1)
                 result="Error! Can't open file - "+name_File;
                else
                {
                 buf=new wchar_t(size+1);
                 FileSeek(handle,0,0);
                 FileRead(handle,buf,size);
                 FileClose(handle);
                 result=buf;
                 delete buf;
                 }


                 return result;
        }
};
 


Klasa dołączona do projektu, kompiluje się poprawnie. Wywołuję ją przykładowo:
KOD cpp:     UKRYJ  
read_File open_F(L"C:\csup.txt");
 UnicodeString file_text=open_F.Write();
 ListBox1->Items->Add(file_text);
 

Również kompilacja jest jak najbardziej poprawna. Problemem jest (chyba) użyta funkcja FileSeek, który mojej zmiennej size, każdorazowo (niezależnie jaką nazwę pliku (i jak) wpiszę w konstruktorze), zawsze nadaje jej wartość - -1 i tym samym funkcja tekstowa Write() nie zwraca zawartości otwieranego pliku, a komunikat o błędzie, zdeterminowany wartością size. Ktoś się domyśla dlaczego tak się dzieje? Spróbuje to jeszcze zrobić na starszym kompilatorze, z użyciem : char*, AnsiString i .c_str().

Re: Problem z FileSeek i FileOpen

Nowy postNapisane: niedziela, 5 maja 2019, 09:35
przez lukagrom
A jednak stara konwersja zdaje egzamin:
KOD cpp:     UKRYJ  
class read_File
{
        private:
        int size;
        int  handle;
        char *buf;
        AnsiString name_File;
        AnsiString result;
        public:
        read_File(AnsiString my_File)
        {
                name_File=my_File;
                handle=FileOpen(name_File.c_str(), fmOpenRead);
                size=FileSeek(handle,0,2);

        }
        AnsiString Write()
        {       if(size==-1)
                 result="Error! Can't open file - "+name_File;
                else
                {
                 buf=new char(size+1);
                 FileSeek(handle,0,0);
                 FileRead(handle,buf,size);
                 FileClose(handle);
                 result=buf;
                 delete buf;
                 }


                 return result;
        }
};
 

Widocznie FileOpen, prawidłowo współpracuje z AnsiString, niż UnicodeString.
KOD cpp:     UKRYJ  
 read_File open_F("readme.txt");
 AnsiString file_text=open_F.Write();
 ListBox1->Items->Add(file_text);
 

Działa poprawnie. A tak w ogóle dlaczego porzucono w nowych kompilatorach uniwersalny char, na rzecz wchar_t?

Re: Problem z FileSeek i FileOpen

Nowy postNapisane: niedziela, 5 maja 2019, 12:04
przez polymorphism
Dlaczego wskaźnik read_File::buf jest polem klasy, skoro używasz go jak zwykłą zmienną lokalną? Dlaczego ręczne zarządzanie pamięcią, a nie std::vector (albo nawet std::unique_ptr<[]>)?

Nie
buf=new char(size+1);
...
delete buf;

tylko
KOD cpp:     UKRYJ  
buf = new char[size + 1]
buf[size] = '\0';
...
delete[] buf;


Nie lepiej zrobić funkcję, która zwraca zawartość pliku, zamiast tej klasy, której zastosowanie nie daje Ci żadnej korzyści?

A tak w ogóle dlaczego porzucono w nowych kompilatorach uniwersalny char, na rzecz wchar_t?

Dlatego, że w XXI wieku, w dobie świata zglobalizowanego, a co za tym idzie wielojęzycznych aplikacji, nikt nie będzie się bawił w niewygodne strony kodowe.

Re: Problem z FileSeek i FileOpen

Nowy postNapisane: niedziela, 5 maja 2019, 13:09
przez lukagrom
Naturalnie poprawiłem (koszmarny) błąd nawiasowy (cud, że kompilator nie zaprotestował), oba rozwiązania działają poprawnie. Przy czym w wersji nowszej kompilatora z użyciem UnicodeString wartość tekstowa jest zwracana jako znaki czcionki azjatyckiej, co chyba zależy od lokalnych ustawień Windowsa, bądz środowiska kompilatora. Rzeczywiście zwykła funkcja była by w tym przypadku poręczniejsza.
Na moje skromne potrzeby i archaiczne podejście do "użytkowania" char i wchar_t używam sobie naprzemiennie, przy czym zdarza mi się popodglądać jakiś przykład unixowe-go C, a tam naturalnie króluje dinozaur - char. Przynajmniej alokuje się i zwalnia pamięć tak samo, co cieszy bo często wykorzystuję wielowymiarowe tablice.
KOD cpp:     UKRYJ  
wchar_t **tab_Wchar;
 char  **tab_Char;
 int i,size_tab;
 size_tab=10;
 tab_Char=new char *[size_tab];
 tab_Wchar=new wchar_t *[size_tab];
 for(i=0;i<10;i++)
 {
         tab_Char[i]=new char[size_tab];
         tab_Wchar[i]=new wchar_t[size_tab];
 }

 for(i=0;i<10;i++)
 {
         delete [] tab_Char[i];
         delete [] tab_Wchar[i];
 }
 delete [] tab_Wchar;
 delete [] tab_Char;
 

Re: Problem z FileSeek i FileOpen

Nowy postNapisane: niedziela, 5 maja 2019, 13:54
przez polymorphism
cud, że kompilator nie zaprotestował

Nie zaprotestował, bo ten kod składniowo jest poprawny, tylko nie znaczy on tego, co miałeś na myśli - przydzielasz jednego chara i przypisujesz mu wartość size + 1. Zatem tam jest fatalny błąd, który nie wylazł, bo miałeś szczęście :) Między innymi dlatego w C++ w miarę możliwości odchodzi się od ręcznego zarządzania pamięcią na rzecz inteligentnych wskaźników, klasy std::vector czy std::string. Używanie new i delete we współczesnym C++ to nie jest dobra praktyka (poza wyjątkami oczywiście).

a tam naturalnie króluje dinozaur - char.

Typ char nie jest dinozaurem, tylko w Uniksach/Linuksach natywnym kodowaniem, jeśli mowa o unikodzie, jest UTF-8, a on jest częściowo zgodny z ASCII. Windows używa znaków szerokich, czyli wchar_t (kodowanie USC-2/UTF-16).