Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

dział ogólny

Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez mko000 » wtorek, 5 stycznia 2010, 17:32

Witam. Otóż znalazłem problem w powyższej poradzie. Oto kod:
Kod: Zaznacz cały
// Plik źródłowy np. Unit1.cpp.
//--------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int iFileHandle;
int iFileLength;
int iBytesRead;
int iBytesWrite = 0;
char *pszBuffer;

if(OpenDialog1->Execute())
{
  try
  {
   iFileHandle = FileOpen(OpenDialog1->FileName, fmOpenRead);
   iFileLength = FileSeek(iFileHandle, 0, 2);
   FileSeek(iFileHandle, 0, 0);
   pszBuffer = new char[iFileLength+1];
   iBytesRead = FileRead(iFileHandle, pszBuffer, iFileLength);
   FileClose(iFileHandle);

   while(iBytesWrite < iBytesRead)
   {
    if(pszBuffer[iBytesWrite] == 0)
    pszBuffer[iBytesWrite] = ' ';
    iBytesWrite++;
   }

   Memo1->Lines->SetText(pszBuffer);
   delete [] pszBuffer;
  }
  catch(...)
  {
   Application->MessageBox("Can't perform one of the following file operations: Open, Seek, Read, Close.", "File Error", IDOK);
  }
}
}
//--------------------------------

Na formie mam tylko memo1 i opendialog1

a błąd dotyczy tej linijki
Memo1->Lines->SetText(pszBuffer);

[BCC32 Error] Unit3.cpp(43): E2034 Cannot convert 'char *' to 'wchar_t *'
[BCC32 Error] Unit3.cpp(43): E2342 Type mismatch in parameter 'Text' (wanted 'wchar_t *', got 'char *')

jak zamienic ta zmienna ?
Avatar użytkownika
mko000
Homos antropiczny
Homos antropiczny
 
Posty: 74
Dołączył(a): sobota, 19 grudnia 2009, 00:30
Podziękował : 35
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP2
Kompilator: C++ Builder 2010
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez Witold » wtorek, 5 stycznia 2010, 18:56

spróbuj: Memo1->Text = pszBuffer;
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
Podziękował : 1
Otrzymał podziękowań: 14
Kompilator: bcb6, Turbo C++ Explorer
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez Cyfrowy Baron » wtorek, 5 stycznia 2010, 19:01

Porada była pisana dla środowiska C++Builder do wersji 2007. Problem polega na tym, że w nowszych wersjach C++Builder od 2009 domyślnie pracuje na zmiennych typu UnicodeString. Musisz zmienić typ char na wchar_t, czyli tutaj:

Kod: Zaznacz cały
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int iFileHandle;
int iFileLength;
int iBytesRead;
int iBytesWrite = 0;
wchar_t *pszBuffer;

if(OpenDialog1->Execute())
{
  try
  {
   iFileHandle = FileOpen(OpenDialog1->FileName, fmOpenRead);
   iFileLength = FileSeek(iFileHandle, 0, 2);
   FileSeek(iFileHandle, 0, 0);
   pszBuffer = new wchar_t[iFileLength+1];
   iBytesRead = FileRead(iFileHandle, pszBuffer, iFileLength);
   FileClose(iFileHandle);

   while(iBytesWrite < iBytesRead)
   {
     if(pszBuffer[iBytesWrite] == 0)
     pszBuffer[iBytesWrite] = ' ';
     iBytesWrite++;
   }

   Memo1->Lines->SetText(pszBuffer);
   delete [] pszBuffer;
   }
   catch(...)
   {
     Application->MessageBox(L"Can't perform one of the following file operations: Open, Seek, Read, Close.", L"File Error", IDOK);
   }
}
}

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
mko000
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4731
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 445
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez Witold » wtorek, 5 stycznia 2010, 21:24

Cyfrowy Baron napisał(a):...
Musisz zmienić typ char na wchar_t, czyli tutaj:
...


Zdaje mi się że to co napisałeś zmieni interpretacje znaków char->wchar_t (pliki binarne nie są chyba zapisywane w unicode) i dodasz trochę danych od siebie (albo nie)?

Z ciekawości, czemu służyła ta zmiana kolejności postów ?

Zdaje mi się też że Kinio zapomniał pszBuffer[iFileLength] = 0; a FileOpen, FileSeek, FileRead, FileClose nie rzucają wyjątków.
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
Podziękował : 1
Otrzymał podziękowań: 14
Kompilator: bcb6, Turbo C++ Explorer
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez Cyfrowy Baron » wtorek, 5 stycznia 2010, 21:47

Co proponujesz zamiast wchar_t?

Przesunąłem wątek, gdyż twoja odpowiedź nie rozwiązywała problemu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4731
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 445
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez Witold » wtorek, 5 stycznia 2010, 23:52

Cyfrowy Baron napisał(a):Co proponujesz zamiast wchar_t?


dalej: Memo1->Text = pszBuffer;

UnicodeString ma konstruktor: System::UnicodeString * __fastcall UnicodeString(const char * src);
http://docwiki.embarcadero.com/VCL/en/S ... nstructors

Cyfrowy Baron napisał(a):Przesunąłem wątek, gdyż twoja odpowiedź nie rozwiązywała problemu.


mko000 napisał(a):a błąd dotyczy tej linijki
Memo1->Lines->SetText(pszBuffer);

[BCC32 Error] Unit3.cpp(43): E2034 Cannot convert 'char *' to 'wchar_t *'
[BCC32 Error] Unit3.cpp(43): E2342 Type mismatch in parameter 'Text' (wanted 'wchar_t *', got 'char *')


Znaczy się po zmiane:
Kod: Zaznacz cały
  Memo1->Lines->SetText(pszBuffer);

na
Kod: Zaznacz cały
Memo1->Text = pszBuffer;

błąd „Cannot convert 'char *' to 'wchar_t *'” pojawia się dalej ? Może pojawia się jakiś inny błąd ?
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
Podziękował : 1
Otrzymał podziękowań: 14
Kompilator: bcb6, Turbo C++ Explorer
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez polymorphism » środa, 6 stycznia 2010, 12:42

Witold napisał(a):Zdaje mi się że to co napisałeś zmieni interpretacje znaków char->wchar_t (pliki binarne nie są chyba zapisywane w unicode) [...]

Dokładnie. Taka zwykła zamiana typów jest błędna, bo w unikodzie, przy kodowaniu utf-16, nie ma takiej dowolności, jeśli chodzi kody znaków, jak w kodowaniu ansi, gdzie (prawie) każda wartość 'coś' znaczy. W unikodzie to nie przejdzie, niektóre kody po prostu nie istnieją.

UnicodeString ma konstruktor: System::UnicodeString * __fastcall UnicodeString(const char * src);

Tylko żeby przekonwertować ciąg bajtów na unikod, musisz znać jego kodowanie. Mowa o danych binarnych, więc trudno mówić o konkretnym kodowaniu, a co za tym idzie o poprawnej konwersji.

Kod: Zaznacz cały
pszBuffer = new wchar_t[iFileLength+1];

iFileLength to długość pliku w bajtach, więc pszBuffer jest dwa razy większy niż powinien (druga połowa bufora będzie zawierać przypadkowe wartości). Na jeden znak przypadają 2 bajty.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2263
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 210
System operacyjny: Windows 8.1
Windows 10
Linux Mint 19
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez Cyfrowy Baron » środa, 6 stycznia 2010, 12:57

Kod: Zaznacz cały
Memo1->Text = pszBuffer;


To rzeczywiście działa, są jednak dwa ale, wczytanie pliku o rozmiarze 2 MB trwa około minuty, wczytana dane binarne są nieprawidłowo, zawierają mnóstwo pustych spacji.

Text = UnicodeString;
SetText(wchar_t *);

To mnie trochę zmyliło, sądziłem, że SetText(UnicodeString), a konwersja dokonuje się niejawnie.

Pytanie jak dokonać konwersji char na wchar_t.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4731
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 445
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez polymorphism » środa, 6 stycznia 2010, 15:09

wczytana dane binarne są nieprawidłowo, zawierają mnóstwo pustych spacji.

Bo dane binarne to nie zawsze są tekstem. Takich danych nie podaje w ten sposób kontrolkom stricte tekstowym.

Pytanie jak dokonać konwersji char na wchar_t.


KOD cpp:     UKRYJ  
locale loc(".1250");// <--- przykładowe kodowanie

const ctype<wchar_t> &ct = use_facet<ctype<wchar_t> >(loc);

/* dla każdego bajta */
...
char chr = /* whatever */
wchar_t wc = ct.widen(chr);
bool ok = ct.is(ctype<wchar_t>::alpha | ctype<wchar_t>::digit | ctype<wchar_t>::punct,wc);
if(!ok) wc = 0x2588; // jeśli kod nie jest literą, cyfrą lub znakiem interpunkcyjnym, to wtedy zmiana na █
 
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2263
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 210
System operacyjny: Windows 8.1
Windows 10
Linux Mint 19
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez Cyfrowy Baron » środa, 6 stycznia 2010, 15:22

Bo dane binarne to nie zawsze są tekstem. Takich danych nie podaje w ten sposób kontrolkom stricte tekstowym.


Nie o to mi chodziło. Ten sam kod użyty w C++Builder 2007 w miejscu spacji wstawia kwadraciki i działa szybciej, plik jest wczytywany niemal natychmiast.

Co do szybkości działania, to sądziłem, że opóźnienie wywołuje pętla, ale tak nie jest, co można sprawdzić za pomocą tego kodu:

Kod: Zaznacz cały
int iFileHandle;
int iFileLength;
int iBytesRead;
int iBytesWrite = 0;
char *pszBuffer;
AnsiString dane;

if(OpenDialog1->Execute())
{
  try
  {
   iFileHandle = FileOpen(OpenDialog1->FileName, fmOpenRead);
   iFileLength = FileSeek(iFileHandle, 0, 2);
   FileSeek(iFileHandle, 0, 0);
   pszBuffer = new char[iFileLength+1];
   iBytesRead = FileRead(iFileHandle, pszBuffer, iFileLength);
   FileClose(iFileHandle);

   while(iBytesWrite < iBytesRead)
   {
     if(pszBuffer[iBytesWrite] == 0)
     pszBuffer[iBytesWrite] = ' ';
     iBytesWrite++;
   }
   dane = pszBuffer;
   delete [] pszBuffer;
   }
   catch(...)
   {
     Application->MessageBox(L"Can't perform one of the following file operations: Open, Seek, Read, Close.", L"File Error", MB_OK);
   }
}
  ShowMessage("Przepisywanie");
Memo1->Text = dane;


Opóźnienie powstaje przy przepisywanie danych do obiektu Memo. Jak więc sądzę problemem jest przekonwertowanie danych na UnicodeString.

Jak widać użyłem zmiennej typu AnsiString do przechowania zawartości bufora, to oczywiście nic nie daje, gdyż opóźnienie nadal występuje.
Kolejne pytanie jak szybko przepisać wartość AnsiString do UnicodeString bez opóźnienia?
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4731
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 445
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez polymorphism » środa, 6 stycznia 2010, 15:44

Kod który podałem, po drobnych zmianach, z użyciem wstringa, 2MB bufor konwertuje mi w ~0.6 sekundy (2x2.5GHz), a 10MB w ~2.8 sekundy. Więc sama konwersja nie powinna być problemem.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2263
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 210
System operacyjny: Windows 8.1
Windows 10
Linux Mint 19
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez Witold » środa, 6 stycznia 2010, 18:20

polymorphism napisał(a):
UnicodeString ma konstruktor: System::UnicodeString * __fastcall UnicodeString(const char * src);

Tylko żeby przekonwertować ciąg bajtów na unikod, musisz znać jego kodowanie. Mowa o danych binarnych, więc trudno mówić o konkretnym kodowaniu, a co za tym idzie o poprawnej konwersji.


Pomysł takiego przerzucenia danych z pliku do TMemo nie jest mój, próbowałem tylko wyeliminować wymieniony błąd. Zdaje mi się że znaki w TMemo wg tego sposobu (+poprawka) będą takie same dla środowiska z AnsiString i UnicodeString (wszystko wg kodowania systemowego). Twoje rozwiązanie z analizą znaków jest MSZ lepsze.

Cyfrowy Baron napisał(a):Kolejne pytanie jak szybko przepisać wartość AnsiString do UnicodeString bez opóźnienia?


Trzeba by mieć pewność, że to jest problemem. Może chodzi o WordWrap.
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
Podziękował : 1
Otrzymał podziękowań: 14
Kompilator: bcb6, Turbo C++ Explorer
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez Cyfrowy Baron » czwartek, 7 stycznia 2010, 12:02

Witold trochę mi namieszał.
kinio nie bez powodu użył funkcji SetText(char *) gdyż ta funkcja pobiera wartości typu char, podczas gdy Memo->Text pobiera wartości typu AnsiString (do wersji BCB 2007)
Dlatego też, jeżeli chcemy mieć prawidłowo wyświetlane znaki to należy używać funkcji SetText.

Żadne z rozwiązań, które testowałem nie daj zadowalających rezultatów. Kod po prostu działa za długo. Co do kodu polymorphis to otrzymuję kilka błędów i nie mogę go przetestować.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4731
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 445
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez polymorphism » czwartek, 7 stycznia 2010, 12:21

Jakich błędów?
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2263
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 210
System operacyjny: Windows 8.1
Windows 10
Linux Mint 19
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postprzez Cyfrowy Baron » czwartek, 7 stycznia 2010, 12:39

Jest problem z tą linią:

Kod: Zaznacz cały
wchar_t wc = ct.widen(chr);



[BCC32 Error] Unit1.cpp(149): E2285 Could not find a match for 'ctype<wchar_t>::widen(char *)'



Potem gdy próbuję przepisać zawartość zmiennej wc do Memo poprzez funkcję SetText otrzymuję komunikat:


[BCC32 Error] Unit1.cpp(153): E2342 Type mismatch in parameter 'Text' (wanted 'wchar_t *', got 'wchar_t')



a tak wogóle to nie bardzo rozumiem ten twój kod.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4731
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 445
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

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