Turbo C++ i WWW

problemy z tworzeniem programów do obsługi sieci, internetu, e-mail itp..

Re: Turbo C++ i WWW

Nowy postprzez Witold » sobota, 3 października 2009, 12:35

Cyfrowy Baron napisał(a): Zmienna typu String nie jest w stanie przechować znaków UNICODE, więc po przepisaniu pliku do zmiennej typu String pojawią się krzaczki i żadna konwersja z UTF8 na Ansi tutaj raczej nie pomoże, gdyż zmienna String nie pomieści znaków z zakresu UTF8.


Chyba namieszłeś. ZTCW, jakim typem jest String , wskazuje odpowiedni typedef w BC < BC2009 to typedef AnsiString String, w BC >= BC2009, typedef UnicodeString String.

Hmm, w BCB6 jest typedef AnsiString UTF8String;.

http://4programmers.net/Delphi/AnsiString napisał(a):Typ AnsiString obsługuje kodowanie 8bitowe (ANSI) oraz MBCS (Multibyte Character Set).
Ostatnio edytowano sobota, 3 października 2009, 12:42 przez Cyfrowy Baron, łącznie edytowano 1 raz
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: Turbo C++ i WWW

Nowy postprzez Cyfrowy Baron » sobota, 3 października 2009, 12:38

wskazuje odpowiedni typedef w BC < BC2009 to typedef AnsiString String, w BC >= BC2009, typedef UnicodeString String.

W C++ 2009 TAK, ale ja korzystam z C++ 2007 i tutaj już tak nie jest.

Tak wyświetlane są znaki UTF-8 w Memo w środowisku C++ Builder 2009.
memo_utf8.png


Pokaż jak wyświetlić w Memo znaki kodowane w UTF-8, ale nie w Memo z C++ Builder 9, lecz we wcześniejszych wersjach, oraz jak przepisać z zmiennej typu AnsiString (Memo->Text = AnsiString) do Memo, w taki sposób by wyświetlić znaki UTF-8



Wrócę jeszcze na chwilę do funkcji InternetReadFile. Rozwiązanie problemu znajdowało się cały czas w poradzie: ► patrz serwis: Cyfrowy Baron dział: porady -> sieć - internet -> Wyciąganie adresów URL ze stron internetowych.

Kod: Zaznacz cały
#include "wininet.h"


#pragma comment(lib, "wininet.lib")
AnsiString ReadFile(AnsiString Url)
{
AnsiString result = "";
HINTERNET hSession = NULL;
hSession = InternetOpen("ReadFile", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if(hSession)
{
  HINTERNET hService = NULL;
  hService = InternetOpenUrl(hSession, Url.c_str(), NULL, 0, 0, 0 );
  if(hService)
  {
   while(1)
   {
    char lpBuffer[1024 + 1];
    DWORD dwBytesRead;
    InternetReadFile(hService, lpBuffer, 1024, &dwBytesRead);
    if(dwBytesRead == 0) break;
    lpBuffer[dwBytesRead] = 0;
    result += lpBuffer;
   }
  }
  InternetCloseHandle(hService);
}
InternetCloseHandle(hSession);
return result;
}
void __fastcall TForm1::Button3Click(TObject *Sender)
{
String m_strURL = "http://programowanie.cal.pl/forum/index.php";

UsuwajTagi(ReadFile(m_strURL));


String tekst = ReadFile(m_strURL); //tylko celem sprawdzenia
Memo1->Text = tekst; //tylko celem sprawdzenia

}
//---------------------------------------------------------------------------


Mechanizm jest podobny do tego, który przedstawił polymorphism.

To rozwiązanie wdaje mi się najlepsze, z dotychczas zaproponowanych, szczególnie, że jak zauważysz, znika problem "kwadracików" i możesz przekazać do funkcji UsuwajTagi od razu funkcję ReadFile z jednym tylko argumentem - adresem strony.
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Turbo C++ i WWW

Nowy postprzez Witold » sobota, 3 października 2009, 12:58

Cyfrowy Baron napisał(a):
Pokaż jak wyświetlić w Memo znaki kodowane w UTF-8, ale nie w Memo z C++ Builder 9, lecz we wcześniejszych wersjach, oraz jak przepisać z zmiennej typu AnsiString (Memo->Text = AnsiString) do Memo, w taki sposób by wyświetlić znaki UTF-8


Czemu ? Odnosiłem się do tego że rzekomo AnsiString nie może przechowywać UTF-8. Jeśli AnsiString zawierałby dane UTF-8, to funkcja
AnsiString __fastcall Utf8ToAnsi(const UTF8String S); powinna pomóc (np. dla znaków PL, oczywiście nie wszystko da się dopasować).

Cyfrowy Baron napisał(a):Tak wyświetlane są znaki UTF-8 w Memo w środowisku C++ Builder 2009.


Wszystko dobrze poustawiałeś?
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: Turbo C++ i WWW

Nowy postprzez Cyfrowy Baron » sobota, 3 października 2009, 13:07

No więc mi dokładnie o to samo chodziło. Źle się wyraziłem, chodzi o to, że zmienna AansiString nie wyświetla prawidłowo znaków UTF-8, ale wyświetla krzaczki, czyli jednak coś tam przechowuje.
Co się tyczy funkcji Utf8ToAnsi to niestety nie tłumaczy tych krzaczków na polskie znaki. Problem dałoby się rozwiązać pisząc własną funkcję podmieniającą znaki.



Wszystko dobrze poustawiałeś?


Próbowałem różnych ustawień, ale nie da rady. Co ciekawe Notatnik prawidłowo interpretuje pliki zapisane w Memo z kodowaniem UTF-8. Prawdopodobnie dopiero C++ Builder 2009 wprowadza obsługę tego kodowania do Memo.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Turbo C++ i WWW

Nowy postprzez GoldWolf » sobota, 3 października 2009, 19:29

U mnie tylko to rozwiązanie jest zadowalające:
Kod: Zaznacz cały
Memo1->Lines->LoadFromStream(oStream.get());
w innych ma kwadraciki.
Tylko dwie rzeczy są nieskończone: wszechświat oraz ludzka głupota, choć nie jestem pewien co do tej pierwszej. - Albert Einstein

Błędów nie popełnia ten, kto nic nie robi. - Theodore Roosevelt
Avatar użytkownika
GoldWolf
Homos antropiczny
Homos antropiczny
 
Posty: 116
Dołączył(a): piątek, 16 stycznia 2009, 18:42
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Siódemka Profesjonalna
Kompilator: Microsoft Visual Studio 2010
Version 10.0.30319.1
Gadu Gadu: 0
    NieznanyNieznana

Re: Turbo C++ i WWW

Nowy postprzez Cyfrowy Baron » sobota, 3 października 2009, 20:04

Rzeczywiście, u mnie też, przez pomyłkę wywoływałem inną funkcję.
Swoją drogą ciekaw jestem czemu tak się dzieje...
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Turbo C++ i WWW

Nowy postprzez GoldWolf » sobota, 3 października 2009, 20:09

Nie umiem tego zrozumieć, z jednej strony mamy metodę która wczytuje od razu ze strumienia,
Kod: Zaznacz cały
Memo1->Lines->LoadFromStream(oStream.get());
a z drugiej AnsiString result. Nie chce używać Memo1, ale jeśli będę musiał to spowoduje dodatkowe komplikacje.

PS
Swoją drogą ciekaw jestem czemu tak się dzieje...
- widzę, że czytasz w moich myślach ...


DZIĘKUJE WSZYSTKIM ZA PORADY WSZYSTKO DZIAŁA DOKŁADNIE TAK JAK CHCE, OWSZEM W MEMO SĄ KWADRACIKI, ALE W PLIKU TEKSTOWYM ICH NIEMA. Z TEGO WSZYSTKIE ZAPOMNIAŁEM CO CHCĘ UZYSKAĆ I DO CZEGO DĄŻĘ. JAK TO WSZYSTKO UPORZĄDKUJĘ TO POSTARAM SIĘ PODAĆ WSZYSTKIE WASZE ROZWIĄZANIA.
Tylko dwie rzeczy są nieskończone: wszechświat oraz ludzka głupota, choć nie jestem pewien co do tej pierwszej. - Albert Einstein

Błędów nie popełnia ten, kto nic nie robi. - Theodore Roosevelt
Avatar użytkownika
GoldWolf
Homos antropiczny
Homos antropiczny
 
Posty: 116
Dołączył(a): piątek, 16 stycznia 2009, 18:42
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Siódemka Profesjonalna
Kompilator: Microsoft Visual Studio 2010
Version 10.0.30319.1
Gadu Gadu: 0
    NieznanyNieznana

Re: Turbo C++ i WWW

Nowy postprzez Cyfrowy Baron » sobota, 3 października 2009, 23:06

Chciałem zaproponować rozwiązanie ostateczne eliminujące konieczność stosowania obiektu Memo i eliminujące "kwadraciki".
Zadanie będzie realizowane za pomocą funkcji ReadFile, która pobiera argument typu String będący adresem pobieranej strony WEB i zwraca wartość również typu String, bez "kwadracików" i mało tego funkcja dekoduje znaki UTF-8 na znaki polskie, jednak co do pozostałego kodowania stron (mam na myśli zestawy znaków ISO-, Windows-, itp), to sprawa wygląda dokładnie tak jak w przypadku otwierania plików HTML w Notatniku, trzeba by stworzyć funkcję sprawdzającą w nagłówku jakiego kodowania użyto i w zależności od tego podstawiać polskie znaki.
pliki PHP kodowane w UTF-8 jednak dekodują się bez problemu w efekcie dając polskie znaki:

Kod: Zaznacz cały
#include "wininet.h"
#include <memory>

#pragma comment(lib, "wininet.lib")
//---------------------------------------------------------------------------
String ReadFile(String Url)
{
IStream* pStream;

URLOpenBlockingStream(0, Url.c_str(), &pStream, 0, 0);

std::auto_ptr<TOleStream> oStream(new TOleStream(pStream));
std::auto_ptr<TStrings> sMemo(new TStringList());

sMemo->LoadFromStream(oStream.get());

String Result = UTF8Decode(sMemo->Text);
if(!Result.IsEmpty()) return Result;

return  sMemo->Text;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
//String sUrl = "http://cyfbar.republika.pl/index.html"; // strona kodowana w ISO-88592
String sUrl = "http://programowanie.cal.pl/forum/index.php"; // strona kodowana w Unicode UTF-8

String tekst = ReadFile(sUrl);

UsuwajTagi(ReadFile(sUrl));

Memo1->Text =  tekst; //sprawdzanie co zawiera tekst
}
//---------------------------------------------------------------------------
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Turbo C++ i WWW

Nowy postprzez Witold » niedziela, 4 października 2009, 09:54

Cyfrowy Baron napisał(a):Co się tyczy funkcji Utf8ToAnsito niestety nie tłumaczy tych krzaczków na polskie znaki.


Potem użyłeś UTF8Decode i jak rozumiem już tłumaczyła.

Funkcja Utf8ToAnsi w BCB6 wywołuje Utf8Decode:

System.pas, linia 17681 napisał(a):function Utf8ToAnsi(const S: UTF8String): string;
begin
Result :=Utf8Decode(S); <---------------------------------
end;


????
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: Turbo C++ i WWW

Nowy postprzez Cyfrowy Baron » niedziela, 4 października 2009, 10:46

W C++ Builder 2007 użycie funkcji Utf8ToAnsi nie daje żadnych efektów, nic się nie zmienia, ale jeżeli przekaże się do funkcji tekst nie zawierający kodowania UTF-8 to nic nie zwraca, dlatego w funkcji ReadFile umieściłem warunek:

Kod: Zaznacz cały
String Result = UTF8Decode(sMemo->Text);
if(!Result.IsEmpty()) return Result;

return  sMemo->Text;


Jeżeli tekst zawiera kodowanie UTF-8 to funkcja zwraca zdekodowany tekst, w przeciwnym razie zwraca tekst bez zmian.



Wrócę jeszcze do tych kwadracików, które nie pojawiają się gdy plik jest przepisywany do obiektu typu TString bezpośrednio ze strumienia, a pojawiają się gdy ze strumienia przepisuje się to do zmiennej typu char:

Kod: Zaznacz cały
    char lpBuffer[1024 + 1];
    DWORD dwBytesRead;
    InternetReadFile(hService, lpBuffer, 1024, &dwBytesRead);


Zakładam, że wina leży właśnie po zmiennej typu char, gdyż ten typ nie jest już w stanie przechować kodowania UTF-8, dlatego wstawia znak zastępczy.
Gdyby dało się zastąpić ten typ innym to funkcja zwracała by tekst prawidłowo.
Próbowałem z typem wchar_t, ale efekt był jeszcze gorszy - żadnych liter.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Turbo C++ i WWW

Nowy postprzez polymorphism » niedziela, 4 października 2009, 11:03

Zakładam, że wina leży właśnie po zmiennej typu char, gdyż ten typ nie jest już w stanie przechować kodowania UTF-8, dlatego wstawia znak zastępczy.

Nic nie wstawia. Krzaczki masz dlatego, bo dwubajtowy znak traktujesz jak dwa znaki w kodowaniu ansi.

Typ char[] jest jak najbardziej odpowiedni do przechowywania tekstu w kodowaniu utf-8.

Próbowałem z typem wchar_t, ale efekt był jeszcze gorszy - żadnych liter.

Żeby próbować z typem wchar_t, musiałbyś najpierw przekonwertować litery z kodowania utf-8 na utf-16. Zwykłe przepisanie char -> wchar_t jest błędem dla kodów powyżej wartości 127.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Turbo C++ i WWW

Nowy postprzez Cyfrowy Baron » niedziela, 4 października 2009, 13:02

Tu nie chodzi o krzaczki, gdyż akurat ten problem rozwiązuje funkcja Utf8Decode, problem stanowią kwadraciki, które są znakami końca linii. Gdy zawartość pliku jest ładowana bezpośrednio do zmiennej String, to kwadracików nie ma, gdy w pobieraniu danych pośredniczy zmienna typu char kwadraciki się pojawiają.

Nic nie wstawia. Krzaczki masz dlatego, bo dwubajtowy znak traktujesz jak dwa znaki w kodowaniu ansi.


Czepiasz się drobiazgów. Jest oczywiste, że zmienna nic sobie nie wstawi. Pisząc, że wstawia znak zastępczy, chodziło mi o to. że zamiast znaku końca linii widoczne są kwadraciki, zamiast pozostawić puste pole, znak spacji, czy coś podobnego.

Problem krzaczków już rozwiązałem, pozostał problem tych kwadracików, dla zmiennej char jest to chyba wartość '\0'.

Marnujesz tylko mój czas, przedkładając nic nie wnoszące uwagi ponad konkretne rozwiązania problemu. Pisząc o nic nie wnoszących uwagach mam na myśli, że do niczego nie prowadzą i problem pozostaje nierozwiązany.

Może zamiast się wymądrzać wreszcie napiszesz coś konstruktywnego.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Turbo C++ i WWW

Nowy postprzez GoldWolf » niedziela, 4 października 2009, 18:39

Powiem tak to jeszcze nie koniec problemu. Zacząłem testować sobie rozwiązania i przy tej stronie:
Kod: Zaznacz cały
Url = "http://www.bet-at-home.com/odd.aspx?action=toggleEventGroup&SportID=1&EventGroupID=222";
Wysypuje mi się w tym miejscu:
Kod: Zaznacz cały
IStream* pStream;
URLOpenBlockingStream(0, URL.c_str(), &pStream, 0, 0);
std::auto_ptr<TOleStream> oStream(new TOleStream(pStream));
Form4->Memo1->Lines->LoadFromStream(oStream.get());    // <-- BŁĄD !!!
Drugie z prezentowanych rozwiązań wczytuje część podanej strony.
Jednak po kilku niepowodzeniach druga metoda wczytała całość.

PS podany link będzie działać do ok 21, a potem to nie wiem dokładnie, ale dopiero po kilku dniach.
Tylko dwie rzeczy są nieskończone: wszechświat oraz ludzka głupota, choć nie jestem pewien co do tej pierwszej. - Albert Einstein

Błędów nie popełnia ten, kto nic nie robi. - Theodore Roosevelt
Avatar użytkownika
GoldWolf
Homos antropiczny
Homos antropiczny
 
Posty: 116
Dołączył(a): piątek, 16 stycznia 2009, 18:42
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Siódemka Profesjonalna
Kompilator: Microsoft Visual Studio 2010
Version 10.0.30319.1
Gadu Gadu: 0
    NieznanyNieznana

Re: Turbo C++ i WWW

Nowy postprzez Cyfrowy Baron » niedziela, 4 października 2009, 19:17

Jednak po kilku niepowodzeniach druga metoda wczytała całość.


Druga, czyli która?
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Turbo C++ i WWW

Nowy postprzez GoldWolf » niedziela, 4 października 2009, 19:20

Wykorzystująca wininet.
Kod: Zaznacz cały
#include "wininet.h"
#pragma comment(lib, "wininet.lib")
AnsiString ReadFile(AnsiString Url)
{
AnsiString result = "";
HINTERNET hSession = NULL;
Trochę testowałem i jest ok, przynajmniej z tymi kilkoma stronami, które brałem pod uwagę.

A pierwsze metoda ma błąd w tym miejscu dla w/w strony:
Kod: Zaznacz cały
Form4->Memo1->Lines->LoadFromStream(oStream.get());    // <-- BŁĄD !!!
Dodam tylko, że sMemo nie potrafię zastosować. Aczkolwiek błąd dotyczy strumienia.
Tylko dwie rzeczy są nieskończone: wszechświat oraz ludzka głupota, choć nie jestem pewien co do tej pierwszej. - Albert Einstein

Błędów nie popełnia ten, kto nic nie robi. - Theodore Roosevelt
Avatar użytkownika
GoldWolf
Homos antropiczny
Homos antropiczny
 
Posty: 116
Dołączył(a): piątek, 16 stycznia 2009, 18:42
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Siódemka Profesjonalna
Kompilator: Microsoft Visual Studio 2010
Version 10.0.30319.1
Gadu Gadu: 0
    NieznanyNieznana

Poprzednia stronaNastępna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Aplikacje sieciowe

Kto przegląda forum

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