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

Problem z FileSeek i FileOpen

dział ogólny

Problem z FileSeek i FileOpen

Nowy postprzez lukagrom » niedziela, 5 maja 2019, 09:12

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().
Avatar użytkownika
lukagrom
Homos antropiczny
Homos antropiczny
 
Posty: 79
Dołączył(a): wtorek, 1 stycznia 2013, 14:54
Podziękował : 7
Otrzymał podziękowań: 4
System operacyjny: Windows Vista
Kompilator: C++ Builder 10.1 Starter
Gadu Gadu: 0
    Windows VistaChrome

Re: Problem z FileSeek i FileOpen

Nowy postprzez lukagrom » niedziela, 5 maja 2019, 09:35

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?
Avatar użytkownika
lukagrom
Homos antropiczny
Homos antropiczny
 
Posty: 79
Dołączył(a): wtorek, 1 stycznia 2013, 14:54
Podziękował : 7
Otrzymał podziękowań: 4
System operacyjny: Windows Vista
Kompilator: C++ Builder 10.1 Starter
Gadu Gadu: 0
    Windows VistaChrome

Re: Problem z FileSeek i FileOpen

Nowy postprzez polymorphism » niedziela, 5 maja 2019, 12:04

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.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2187
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 204
System operacyjny: Windows 7 Pro
Windows 8.1
Linux Mint 19
Kompilator: Visual Studio 2015 Community
CodeLite (MinGW)
MSYS2 (MinGW, clang)
g++
Gadu Gadu: 0
    Windows 7Firefox

Re: Problem z FileSeek i FileOpen

Nowy postprzez lukagrom » niedziela, 5 maja 2019, 13:09

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;
 
Avatar użytkownika
lukagrom
Homos antropiczny
Homos antropiczny
 
Posty: 79
Dołączył(a): wtorek, 1 stycznia 2013, 14:54
Podziękował : 7
Otrzymał podziękowań: 4
System operacyjny: Windows Vista
Kompilator: C++ Builder 10.1 Starter
Gadu Gadu: 0
    Windows VistaChrome

Re: Problem z FileSeek i FileOpen

Nowy postprzez polymorphism » niedziela, 5 maja 2019, 13:54

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).
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2187
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 204
System operacyjny: Windows 7 Pro
Windows 8.1
Linux Mint 19
Kompilator: Visual Studio 2015 Community
CodeLite (MinGW)
MSYS2 (MinGW, clang)
g++
Gadu Gadu: 0
    UbuntuFirefox


Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 6 gości

cron