2009-11-04 7 views
7

Potrzebuję uzyskać znak ASCII dla każdego znaku w ciągu znaków. Właściwie jest to każda postać w (małym) pliku. Poniższe 3 pierwsze linie z powodzeniem wyciągnąć całą zawartość pliku jest na ciąg znaków (za this recipe):Tcl do uzyskania kodu ASCII dla każdego znaku w ciągu znaków

set fp [open "store_order_create_ddl.sql" r] 
set data [read $fp] 
close $fp 

wierzę ja poprawnie wymagających kodu ASCII dla znaków (patrz http://wiki.tcl.tk/1497). Mam jednak problem z ustaleniem, jak zapętlić każdy znak w ciągu znaków.

Po pierwsze, nie sądzę, że poniższy jest szczególnie idiomatyczny sposób zapętlenia znaków w łańcuchu przy pomocy Tcl. Po drugie, co ważniejsze, zachowuje się niepoprawnie, wstawiając dodatkowy element między każdą postacią.

Poniżej znajduje się kod, który napisałem, aby działać na zawartość powyższej zmiennej "data", a następnie kilka przykładowych danych wyjściowych.

KOD:

for {set i 0} {$i < [string length $data]} {incr i} { 
    set char [string index $data $i] 
    scan $char %c ascii 
    puts "char: $char (ascii: $ascii)" 
} 

WYJŚCIE:

char: C (ascii: 67) 
char: (ascii: 0) 
char: R (ascii: 82) 
char: (ascii: 0) 
char: E (ascii: 69) 
char: (ascii: 0) 
char: A (ascii: 65) 
char: (ascii: 0) 
char: T (ascii: 84) 
char: (ascii: 0) 
char: E (ascii: 69) 
char: (ascii: 0) 
char: (ascii: 32) 
char: (ascii: 0) 
char: T (ascii: 84) 
char: (ascii: 0) 
char: A (ascii: 65) 
char: (ascii: 0) 
char: B (ascii: 66) 
char: (ascii: 0) 
char: L (ascii: 76) 
char: (ascii: 0) 
char: E (ascii: 69) 
+0

Nie wiem nic na temat TCL, ale to, co mogę powiedzieć z wyjścia, to to, że twój ciąg wejściowy jest w UTF-16, w szczególności UTF-16, little-endian, a nie ASCII. –

+0

Arthur, doceniam ten komentarz, ale jestem bardzo ciekawy, aby wiedzieć, * jak * możesz powiedzieć, że to (jest to mały endian UTF-16) z wyjścia? –

+1

UTF-16 używa jednostek dwubajtowych do kodowania znaków. Dla pierwszych 65536 znaków Unicode (tak zwany Płaszczyzna 0) używa jednej z tych jednostek, dla wszystkich pozostałych używa dwóch (tj. 4 bajtów, ale rozróżnia się na dwa * zastępcze znaki * zakodowane na dwóch bajtach) . Znaki ASCII tworzą pierwsze 128 znaków Unicode, dlatego są kodowane za pomocą dwóch bajtów, przy czym najważniejszym z nich jest zawsze 0, najmniej znaczący jest równy kodowi ASCII postaci. Tutaj widzisz, że po każdym kodzie ASCII występuje bajt zerowy, dlatego najpierw masz najmniejszy porządek bajtu, czyli UTF-16LE. –

Odpowiedz

9

Poniższy kod powinien działać:

set data {CREATE TABLE} 
foreach char [split $data ""] { 
    lappend output [scan $char %c] 
} 
set output ;# 67 82 69 65 84 69 32 84 65 66 76 69 

ile dodatkowych znaków w twojej mocy, wydaje się, że problem jest z twoimi danymi wejściowymi z pliku. Czy istnieje jakiś powód, że pomiędzy poszczególnymi znakami w pliku byłyby puste znaki (\ 0)?

+0

Zacząłem podejrzewać, że może to być problem z danymi wejściowymi, chociaż nie ma żadnego powodu dla znaków pustych między poszczególnymi znakami, z wyjątkiem tego, że został wygenerowany za pomocą narzędzia Microsoft (SQL Server);) –

+0

To jest twoja odpowiedź . Większość narzędzi Microsoftu (a przy okazji także Apple) używa UTF-16 jako wewnętrznego kodowania; UTF-16LE jest znacznie bardziej rozpowszechniony, ponieważ jest to endogeniczność Intela. Musisz powiedzieć Tcl, aby zinterpretował plik wejściowy jako UTF-16. Ponownie, nie mam pojęcia, jak to zrobić, przepraszam, ale powinieneś szukać w dokumencie słów kluczowych takich jak "kodowanie" lub "zestaw znaków" lub, ogólnie rzecz biorąc, Unicode. –

+0

Pomyśl, co możesz zrobić: fconfigure $ kodowanie-fp unicode po otwarciu pliku, ale przed jego odczytaniem. –

0

Natknąłem się na to pytanie starszych patrząc na coś innego .. Idąc odpowiedzieć go z korzyścią dla każdego, kto może być patrząc na odpowiedź na to pytanie ..

pierwsze, zrozumieć, jakie są kodowania znaków . Dane źródłowe w tym przykładzie nie są kodowaniem znaków ASCII, więc kody znaków ASCII (kody 0-127) naprawdę nie mają znaczenia - z wyjątkiem tego przykładu kodowanie wygląda na UTF-16, który zawiera kody ASCII jako podzestaw . Prawdopodobnie potrzebujesz pełnego zakresu kodów "znaków" od 0 do 255, ale w zależności od systemu, źródłem danych itp., Kody 128-255 mogą być ANSI, ISO lub inna dziwna strona kodowa. To, co chcesz zrobić, to przekonwertować dane do formatu, który znasz, jak obsługiwać, na przykład bardzo powszechny kod ISO 8859-1 (kodowanie "iso8859-1"), który jest bardzo podobny do standardowego kodowania Windows 1252 (kodowanie " [kodowania danych ConvertTo UTF-8 $]

danych; # UTF-8

zbiór danych CP1252") ​​lub UTF-8 (kodujące "UTF-8") z "polecenia kodowanie" [kodowanie przekonwertowanych danych iso8859-1 $]; # Dla ISO 8859-1

i tak dalej. Jeśli czytasz dane z pliku, możesz chcieć ustawić kodowanie plików (za pomocą fconfigure) przed odczytaniem danych, aby upewnić się, że czytasz dane pliku poprawnie. Wyszukaj strony podręcznika "kodowanie" (i "fconfigure"), aby uzyskać więcej informacji na temat przekazywania kodowania zestawu znaków.

Po zakodowaniu danych pod kontrolą reszta kodu przykładowego powinna działać zgodnie z oczekiwaniami.

Powiązane problemy