Odczyt i zapis polskich znakow UTF-16

0

Witam.
Sytuacja wyglada nastepujaco. Mam pliki zapisane w formacie UTF-16 LE:
http://i.wp.pl/a/f/rar/12658/dane_cz2.rar
Pochodza one z matury 2007 z informatyki oczywiscie.
Chcialbym zaznaczyc, iz prosze o rozwiazania zgodne z programem FreePascal. Aktualnie korzystam z najnowszej jego wersji 2.2.2.
W paczce znajduje sie m.in. plik dane_k.txt. Chcialbym sie dowiedziec jak po odczytaniu polskiego znaku z takiego pliku (przypominam - format UTF-16 LE) moglbym zapisac go poprawnie do pliku wynikowego. Z odczytem i zapisam znakow z angielskiego alfabetu nie mam problemow - moge zarowno odczytac dana litere (np. 'a') z pliku wejsciowego i poprawnie ja zapisac do pliku wynikowego.
Chcac natomiast zapisac litere z polskiego alfabetu (chr > 255) otrzymuje krzaczki jak ponizej:

Id_k Nazwisko Imie Wzrost Nazwa_sieci Wiek Symbol_woj
1 Adamczuk Magdalena 147 Hejka 69 G
2 Adamczyk Urszula 177 Citrone 41 S
3 Adamowicz Jakub 183 Multi 34 T
4 Anielska Ewelina 152 Erka 34 N
5 Antoniuk Izabela 172 Citrone 36 P
6 Arciszewski Piotr 165 Multi 29 Z
7 Awacka Izabela 183 Hejka 58 W
8 Babul Julia 143 Citrone 33 O
9 BaraD☺czuk Adam 174 Hejka 78 R

W ostatniej linijce widac, iz zamiast nazwiska "Barańczuk" wystapil "krzaczek". Jak wiec moge poprawnie odczytac polskie znaki z pliku w formacie UTF-16, a nastepnie je poprawnie zapisac ?

  1. Probowalem uzyc do odczytu danych z pliku wejsciowego zmiennej typu "widechar" (wchar) lub ciagu "widestring". Przy takowej probie dostaje jednakze nastepuje bledy:
  • Fatal: Unknown compilerproc "fpc_read_text_widechar". Check if you use correct run time library
  • Fatal: Unknown compilerproc "fpc_read_text_widestr". Check if you use correct run time library
    Widzac druga czesc komunikatu probowalem ladowac (choc wydawalo sie to byc zupelnie niepotrzebne) moduly: sysutils, strutils, dos, crt, classes, strings. Probowalem takze ustawic tryb pracy: "{$Mode Delphi}", jednk to tez nie pomoglo
  1. Jestem w stanie, w miejscu gdzie wystepuje polski znak, uzyskac odpowiadajacy mu numer w UTF-8 (np. jak program ma odczytac z pliku wejsciowego litere "ń" moge uzyskac liczbe "324" odpowiadajaca jej numeracji w UTF-8). Czy istnieje sposob, by zamienic dany numer (np. wspomniany wczesniej "324") na znak w formacie UTF-8 ? Ewentualnue jak moge zamienic dany ciag liczb w postaci binarnej, na znak w UTF-8?
  2. Probowalem reinstalowac FPC, bez efektow.
    A moze istnieje w ogóle inna, prostsza metoda poprawnego odczytu polskich znakow z plikow w formacie UTF-16 i ich pozniejszego zapisu?
    Przypominam, iz musze korzystac z programu FreePascal w jego "podstawowej" wersji (tzn. bez jakis pomocniczych, zewnetrznych modulow).
0

napisz sobie funkcje ktora bedzie konwertowac polskie znaki np. (Iso -> Win) sa przyklady na necie do tego i na tym forum tez, to powinno rozwiazac twoj problem

0

Wiem, ze istnieje taka mozliwosc, ale niestety nie moge miec tej funkcji napisanej "na stale" tzn. jak bede pisal program to nie bede mogl miec do niej dostepu (musialbym ja "na goraco" napisac). A zapamietanie numerow wszystkich polskich znakow FPC "#xxx" (< 255) i ich odpowiednikow > 255 tez nie wchodzi w gre. Chyba, ze miales na mysli typ konwersji, o ktorej pisalem w punkcie 2), w pierwszym poscie.
Jesli tak to rzuc linka do jakiegos rozwiazania zgodnego z FPC. Wszystkie rozwiazania, ktore do tej pory widzialem nie sprawdzaja sie w FreePascal.

0

czyli czego potrzebujesz? UTF16->UTF8?

function utf16toutf8(wc : word) : string;
var
        utf8c : integer;
        res   : array[1..3] of byte;
          i   : integer;
        res2  : string;
begin
        if (wc < $80) then
                utf8c := 1
        else if (wc < $800) then
                utf8c := 2
        else
                utf8c := 3;

        if (utf8c >= 3) then begin res[3] := $80 or (wc and $3f); wc := wc shr 6; wc := wc or $800; end;
        if (utf8c >= 2) then begin res[2] := $80 or (wc and $3f); wc := wc shr 6; wc := wc or $c0; end;
        if (utf8c >= 1) then begin res[1] := wc; end;

        res2 := '';
        for i := 1 to utf8c do begin
                res2 := res2 + chr(res[i]);
        end;
        utf16toutf8 := res2;
end;

// Moze da sie ladniej, /me to przepisywal ze zrodel w C.
// Copyright (C) 1999-2001, 2004 Free Software Foundation, Inc.
// z libiconv na LGPL-2

przykladowe uzycie:

var
           f : File of byte;
        data : array[0..2047] of byte;
          ret: LongInt;
            i: Integer;
begin
        assign(f, 'dane_k.txt');
        reset(f);

        while (not eof(f)) do begin
                BlockRead(f, data, Sizeof(data), ret);

                (* XXX, gdy ret jest nieparzyste, to albo mamy obciete utf-16, albo przeczytamy w nastepnym rekordzie *)
                i := 0;
                while (i < ret) do begin
                        write(utf16toutf8((data[i+1] shl 8) or (data[i])));
                        i := i + 2;
                end;
        end;
        close(f);
end.

jak potrzebujesz UTF16->ISO-8859-2, UTF16->WINDOWS-1250, lub inne, to musisz zapamietac ~100 cyferek.
No chyba ze Ci wystarczy ąęśźć... to wtedy mniej :)

0

sorry moj post byl nie na temat, nie doczytalem jaki faktycznie masz problem :)

Ja bym traktowal plik jako file of word; czytal/zapisywal do niego wordy zamiast stringow, i powinno smigac :)

0

Niestety po wykonaniu powyzszej funkcji dostaje cale "pole" krzaczkow :-D. Oto fragment wyniku jej dzialania:

´╗┐Id_k○Nazwisko○Imie○Wzrost○Nazwa_sieci○Wiek○Symbol_woj
1○Adamczuk○Magdalena○147○Hejka○69○G
2○Adamczyk○Urszula○177○Citrone○41○S
3○Adamowicz○Jakub○183○Multi○34○T
4○Anielska○Ewelina○152○Erka○34○N
5○Antoniuk○Izabela○172○Citrone○36○P
6○Arciszewski○Piotr○165○Multi○29○Z
7○Awacka○Izabela○183○Hejka○58○W
8○Babul○Julia○143○Citrone○33○O
9○Bara┼äczuk○Adam○174○Hejka○78○R
10○Bartnik○Anna○143○Citrone○46○P
11○Bartoszewicz○Micha┼é○183○Erka○76○G
12○Bielecki○Grzegorz○165○Erka○60○S

Probowalem tez z "file of word" - wynik jak w pierwszym poscie.

Co dziwi chyba najbardziej to, iz takowe zadanie jest i moze byc na maturze. Dlatego spodziewalbym sie, iz istnieje prostsze rozwiazanie odczytu i zapisu (tak, nic wiecej) pliku w standardzie UTF-16. Rozumiem, iz w innych jezykach mozna sobie z plikiem w takim formacie poradzic latwiej, jednak chyba musi istniec jakis prostszy sposob, niz wykucie numeracji polskich znakow diakrytycznych (ą, ę itp.) + napisanie odpowiedniej funkcji. Dla przypomnienia lista aktualnych dostepnych do wyboru jezykow programowania/kompilatorow z informatyki:

0
programmaturalny napisał(a)

Co dziwi chyba najbardziej to, iz takowe zadanie jest i moze byc na maturze. Dlatego spodziewalbym sie, iz istnieje prostsze rozwiazanie odczytu i zapisu (tak, nic wiecej) pliku w standardzie UTF-16. Rozumiem, iz w innych jezykach mozna sobie z plikiem w takim formacie poradzic latwiej, jednak chyba musi istniec jakis prostszy sposob, niz wykucie numeracji polskich znakow diakrytycznych (ą, ę itp.) + napisanie odpowiedniej funkcji. Dla przypomnienia lista aktualnych dostepnych do wyboru jezykow programowania/kompilatorow z informatyki:

oni to rozwiazali w accessie ( http://i.wp.pl/a/f/pdf/12659/inf_pr_cz2_rozw.pdf )

0

a nie możesz użyć WideCharToMultiByte, MultiByteToWideChar?

0
mh napisał(a)

<oni to rozwiazali w accessie ( http://i.wp.pl/a/f/pdf/12659/inf_pr_cz2_rozw.pdf )

Czyli na maturze obojetnie w czym stworze program, czy wykorzystam kwerendy w Accessie, byle by wynik byl OK? (w zasadzie juz dostalem odpowiedz na to pytanie :-P).
Wiec w wypadku pliku UTF-16 musialbym koniecznie wykorzystac Access-a. Dzieki za przydatna informacje, bede wiedzial jak sobie z takim "fantem" radzic.
Wracajac do tematu - jesli ktos ma jakis pomysl na rozwiazanie problemu - prosze smialo pisac.

@piechnat - niestety probowalem ta metoda juz sporo wczesniej, jednak program w ogóle nie chcial sie kompilowac. FPC nie ma tej funkcji zadeklarowanej pod ta nazwa, a za obsluge lancuchow "wide" odpowiedzialny jest tutejszy "WideStringManager":
http://www.freepascal.org/docs-html/rtl/system/twidestringmanager.html</quote>

0

Na Maturze jest tak, że nie ważne co sobie wybierzesz (wcześniej wybierało się preferowane środowisko, może teraz się to zmieniło, ale wątpię) to i tak dostaniesz zadania z Accessa itp. Wybrałem sobie Delphi7 to i tak zadania są dobrane tak, że może byś je i rozwiązał w Delphi, tylko po co się męczyć jak np.: w Accessie zrobisz to szybciej. Moim zdaniem to głupota - po co w takim razie wybierać Delphi, jeśli ostatecznie i tak wszystkie zadania są skonstruowane tak, że i tak nie ma sensu w nim nic robić. Na mojej maturze ostatecznie Delphi nawet nie włączyłem. Dochodzenie do niektórych rozwiązań na Delphi w wersji Personal byłoby nawet niemożliwe z uwagi na ograniczenia tej wersji. Zadania maturalne wymyślają debile.

0

Nie chce mi się specjalnie analizować jak się to ma do UTF16, ale pytałeś o UTF8 - więc jest cała masa funkcji, wystarczy nacisnąć F1

UTF8Encode, UTF8Decode, UTF8ToAnsi .... wszystkie działają mi od strzała na FPC 2.2.0

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