[cURL] Zmiana kodowania na unicode

0

Witam.
W jaki sposób zmienić typ tablicy zawierającej kod HTML pobranej ze strony za pomocą biblioteki cURL z char na wchar_t??
Parametr CURLOPT_WRITEFUNCTION zwraca mi prototyp do funkcji ze zwkaźnikiem do tablicy typu char tak więc zwyczajna konwersja typów nie wchodzi w grę bo ilość bitów sie nie zgadza :(

Czy jest jakaś biblioteka lub jakieś dobre rozwiązanie które w łatwy sposób przekonwertuje tą tablicę z typu char na wchar_t w taki sposób żeby wszystkie polskie znaki były poprawnie wyświetlane??

A może jest jakiś parametr do funkcji curl_easy_setopt()?? Niby przeczytałem całą ale nie znalazłem nic takiego :(

Bardzo proszę o pomoc...

0

o curl nic nie wiem, pod windowsem używam:

wchar_t* ascii2wide(const char* text) {
	int size = MultiByteToWideChar(GetACP(), 0, text, -1, 0,0);
	wchar_t* wbuffer = new wchar_t[size+1];

	MultiByteToWideChar(GetACP(), 0, text, -1, wbuffer, size+1);
	return wbuffer;
	}

i później z górki:

wchar_t* wtext = ascii2wide("hello world");
// ...
delete []wtext;
0

A pod linuxem to też zadziała?? ponieważ piszę program który ma sie dobrze skompilowac zarówno pod win jak i linux/unix... Ale aktualnie nie moge sam sprawdzić bo mi sie zasilacz od drugiego kompa sfurał ;/

EDIT:
No i niestety nie działa ta funkcja nawert pod windowsem :(

wchar_t* ascii2wide(const char* text) {
    int size = MultiByteToWideChar(GetACP(), 0, text, -1, 0,0);
    wchar_t* wbuffer = new wchar_t[size+1];

    MultiByteToWideChar(GetACP(), 0, text, -1, wbuffer, size+1);
    return wbuffer;
}

size_t WriteWebSite(void * data_start, size_t size, size_t dlugosc, void * stream)
{
    wchar_t * stream2 = ascii2wide(reinterpret_cast<char *>(data_start));
    
    for(size_t i=0; i<dlugosc; i++)
    {
         cout << *stream2++;
    }
}

Wyświetla mi tylko liczby tak jak bym dokonał konwersji przez reinterpret_cast<wchar_t *>()

0

hola wędrowcze, przecież nie możesz na cout pisać w unicode :) wcout albo wprintf użyj, jeśli wcout nie masz (libstdc++ ma z nim chyba problemy...)

konwersje w linuxie, nie moja broszka, ale libc niby jakieś funkcje ma...
chociaż pewniej bym się czuł jakiegoś libiconv używając.

0

a jakiś malutki przykładzik jak użyć libiconv a dokłądnie fnkcji iconv() z tej biblioteki?? Bo próbuje cały czas ale ciągle system mi zamyka proces bo coś spowodowało błąd...
Czytam ten manual na tej stronie ale też dużo z niego nie wiem :/

0

Tak kombinuje z tym kodowaniem od wczoraj... ściagnąłem iconva i przekonwertowałem niby jakiś string... Niestety wynik wyśeitlania był taki nie bardzo :P

Sprawdziłem więc rozmiary poszczególnych typów znakowych operatorem sizeof()
char: 4 bajty
wchar_t: 4bajty
std: 4bajty

No i pojawił się problem ponieważ utf-8 używa chyba przecież 8 bajtów...
Jak więc korzystać z tego utf-8?? :(
Szukam jakiś rozwiązań w google i nic nie mogę znaleźć a do tego wcout i wprintf nie istnieje w bibliotekach mojego kompilatora (DEV C++ najnowszy).

0

lol char 4B to niezgodne ze standardem C++, chyba coś źle sprawdzałeś...

a po co ci unikod w konsoli? To bezcelowe, bo standardowa czcionka konsoli w Windows nie ma polskich znaków, więc jak byś nie kombinował nie uzyskasz nic, jedynie możesz spróbować podmienić czcionkę...

UNICODE czy zwykły ASCII ze zmianami stron kodowych nic nie pomoże...

0

To ma być aplikacja uruchamiana jako proces w tle na serwerze. A UTF-8 jest mi potrzebne ponieważ z takiego kodowania korzysta baza MySQL z której ten program będzie korzystał.

size_t WriteWebSite(void * data_start, size_t size, size_t dlugosc, void * stream)
{
    const char * s = reinterpret_cast<const char *>(data_start);
    char * result = NULL;
    size_t dlugosc_r = 0;
    
    iconv_t ihandle = iconv_open("UTF-8", "");
    iconv(ihandle, &s, &dlugosc, &result, &dlugosc_r);
    iconv_close(ihandle);
}

No i tuż po skompilowaniu i właczeniu się konsoli wywala mi błąd, a zmienne result i dlugosc_r są puste :/
Jak korzystać z tego libiconva?? :(

0

No i pojawił się problem ponieważ utf-8 używa chyba przecież 8 bajtów...

Jak już to bitów :> W UTF-8 znak może zajmować maksymalnie 4 bajty, a minimalnie - 1 bajt.

No i tuż po skompilowaniu i właczeniu się konsoli wywala mi błąd,

A czy przypadkiem result nie musi wskazywać na jakiś bufor, do którego będzie wpisany efekt pracy funkcji?

0
0x666 napisał(a)

A czy przypadkiem result nie musi wskazywać na jakiś bufor, do którego będzie wpisany efekt pracy funkcji?

Tzn.? iconv spodziewa się w funkcji typu char * więc też taki utworzyłem.
Błąd wywala mi tylko (i zawiesza program) gdy chcę wypisać result albo dlugosc_r

0

No ale jak chcesz wypisać result jeżeli na nic nie wskazuje? W tym opisie nie widzę, żeby była mowa o tym, że funkcja tworzy bufor i przypisuje go do wskaźnika outbuf. To że dajesz tam wskaźnik na wskaźnik wynika z faktu, że:

The iconv function converts one multibyte character at a time, and for each character conversion it increments *inbuf [...] by the number of converted input bytes, it increments *outbuf [...] by the number of converted output bytes.

Wniosek z tego taki, że musisz zapewnić bufor wyjściowy i że wskaźniki, które podasz będą przesunięte o N przeparsowanych bajtów, więc uwaga na to. Inna ważna sprawa, która jest w cytacie to to, że funkcja ta konwertuje pojedyncze znaki, a nie całe ciągi. W katalogu extras masz funkcję konwertującą całe ciągi znaków.

0

No ok... chyba teraz zrozumiałem...
Dałem tej funkcji do przekonwertowania wskaźnik na jakąś literę polską ("ś" albo "ż") i za każdym razem otrzymuję cały czas taki sam wynik "(+||" (albo "x?:-) x" w przypadku z tym drugim kodem źródłowym który podałem poniżej) - po przesunięciu tego wskaźnika o 1 wielkość zmiennej char i wypisaniu też znajduje się to samo...

zmienna dlugosc_r dalej zawiera 0...

Próbowałem tak:

    const char * s = "ś";
    char * result = new char; //TO JEST ZMIENIONE
    size_t dlugosc_r = 0;
    size_t dlugosc = sizeof(s);

    iconv_t ihandle = iconv_open("UTF-8", "char");
    iconv(ihandle, &s, &dlugosc, &result, &dlugosc_r);
    iconv_close(ihandle);

a później jeszcze tak:

    const char * s = "ś";
    char * * result = new char*; //TO JEST ZMIENIONE
    size_t dlugosc_r = 0;
    size_t dlugosc = sizeof(s);

    iconv_t ihandle = iconv_open("UTF-8", "char");
    iconv(ihandle, &s, &dlugosc, result, &dlugosc_r);
    iconv_close(ihandle);

Wieczorem spróbuję jeszcze z tym iconv_string() może to coś da... tylko pytanie.

Jak sprawdzić bieŻące kodowanie i jak ustawić żeby funkcja fwrite() zapisywała w UTF-8 a nie w ANSI.

0
const char * s = "ś"; //<--- to będzie w takim kodowaniu w jakim pracuje IDE

size_t dlugosc = sizeof(s);

Podstawy się kłaniają. s jest wskaźnikiem, a ten ma rozmiar 4 bajtów.

char * result = new char; //TO JEST ZMIENIONE

Dlaczego new, a nie zwykła tablica statyczna? Dlaczego 1 bajt, jeżeli 'ś' będzie miała 2 bajty w utf-8? Zwalniasz w ogóle gdzieś tą pamięć?

A do tego:

size_t dlugosc_r = 0;

znowu cytat:

The iconv function converts one multibyte character at a time, and for each character conversion it [...] decrements *inbytesleft by the number of converted input bytes, it [...] decrements *outbytesleft by the number of converted output bytes.

Wniosek: dlugosc_r nie może być równe 0, musi zawierać rozmiar bufora. Wartość ta jest zmniejszana przez funkcję, a nie zwiększana.

jak ustawić żeby funkcja fwrite() zapisywała w UTF-8 a nie w ANSI.

fwrite służy do zapisywania binarnego, wiec dla niej nie ma znaczenia kodowanie znaków, to tylko ciąg bajtów.

0
0x666 napisał(a)
const char * s = "ś"; //<--- to będzie w takim kodowaniu w jakim pracuje IDE

Jak zatem sprawdzić kodowanie domyślne w DEVie?? W czymś to jest zapisane??

0

Jeśli nic nie napstrykałeś, prawdopodobnie będzie takie jak kodowanie systemowe - w polskiej wersji językowej windowsa jest to (domyślnie) CP1250.

0

w Dev C++ jeśli chcesz mieć UNICODE domyślnie, na początku każdego *.cpp definiujesz(przed includami)
#define UNICODE
i masz domyślnie unikod
oczywiście żeby używać unikodu musisz używać nie char(bo ta ma cały czas 1 bajt niezależnie od tego czego używasz), a t_wchar(czy wchar_t nie pamiętam :D nadpisania buforów w mojej głowie) w WinAPI odpowiednik to WCHAR, a przy inicjowaniu stringa....

a zresztą www.winapi.rox.pl, tam masz w kursie C++ lekcję o unikodzie w Dev C++

0

OK. Wszystko pięknie teraz mi działa i zapisuje ładnie bo pliku w UTF-8 :-) Problemem był ostatni parametr który myślałem ze ma rosnąć a on tak naprawdę maleje :D
Bardzo dziękuję za pomoc. Jestem wam winien [browar]

Pozdrawiam :-)

PS. Teraz tylko kombinowanie zeby to pod Linuxem sie skompilowało bo z tymi bibliotekami to nigdy nic nie wiadomo... :-/

0
crayze napisał(a)

w Dev C++ jeśli chcesz mieć UNICODE domyślnie, na początku każdego *.cpp definiujesz(przed includami) [...]

Trochę nie w temacie ;-P

0

Kurde... a miało być tak pięknie...

Was może spytam bo może bedziecie znać przyczynę a nie bede tworzył nowego wątku...

Dlaczego podczas połączenia cURLem z google.pl ściąga mi się 1107 bajtów, czasami mniej, a raz na jakieś 20 uruchomień programu cała strona mi się zaladuje czyli ok. 6000?? Timeouty mam ustawione na 20 sekund więc to nie powinien być problem...
Otrzymuję błąd: Filed to write body oraz Filed to write data.

Strona normalnie mi się otwiera w przeglądarce a tutaj ściągnie kawałek i error. Jak wpiszę jaką inną strone np. dupa.pl to działa dobrze i ściąga 845 bajtów.

Chyba to nie jest problem sprzętowy co nie? (tj pamięc itp.)

Wiem że troche poza tematem ale może ktoś bedzie wiedział i odpowie żeby nie zaśmiecać forum nowymi tematami...

PS a i jeszcze zauważyłem ze na PC pobiera mi z 2000 bajtów z google.pl więcej niż na laptopie na którym piszę ten program. :-/

1 użytkowników online, w tym zalogowanych: 0, gości: 1