Tabelle mit Asci zeichen wie anlegen (besten)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
patrickk
User
Beiträge: 31
Registriert: Donnerstag 18. August 2005, 09:07

a ='ü'
>>> b =a.encode( "utf8" )
Traceback (most recent call last):
File "<stdin>", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

Hab das Problem entdeckt:

Wenn man a = u'ü' setzt kommt immer ein anderes Zeichen raus, wenn man a = 'ü' setzt geht es, aber wie mache ich dann eine utf-8 datei daraus, s.o. es erscheint eine fehlermeldung?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Also bei mir klappt beide varianten:

Code: Alles auswählen

f = file( "test.txt", "w" )
f.write( "äöü" )
f.close
produziert auch eine UTF8 konvertierte Text-Datei, obwohl nirgendwo etwas von utf8 angegeben wurde. Warum Python dennoch utf8 verwendet weiß nicht nicht...

Allerdings gibt's ein Fehler bei f.write( u"äöü" ) !

oder

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import codecs
f = codecs.open('test.txt','wb', encoding="utf-8" )
f.write( u"äöü" )
f.close()
In dieser Variante muß es mit u"äöü" gemacht werden. Hierbei ist auch die Angabe # -*- coding: UTF-8 -*- wichtig!

In beiden Varanten wird eine Textdatei erstellt mit dem Inhalt äöü (Wenn man es sich mit normalen 8Bit Encoding anschaut!) Erst wenn ich im SciTE editor auf utf8-datei-encodierung umschalte sehe ich mein äöü-String richtig, was ja normal ist!

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
patrickk
User
Beiträge: 31
Registriert: Donnerstag 18. August 2005, 09:07

Hallo,

kann jetzt mit print (a) das z.b. ü richtig anzeigen lassen.

Ich mache es so:
a=u'ü'
b=a.encode('latin-1')
print(b)

Aber in der datei klappt es nicht??

f = file('/home/'+curtime+'zz','wt')
f.write(codecs.BOM_LE)
final_utf=final.encode("latin-1")
f.write(final_utf)
f.close()

Ist doch so richtig, oder? Ich schaue die datei mit kwrite an. Ich kann nach latin wechseln... es sieht immer faslch aus:

Flughafen K&#xf6;ln/Bonn
was mache ich nich immer falsch???
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich dachte du willst utf8 haben... OK dann probiere es dochmal hiermit:

Code: Alles auswählen

import codecs
f = codecs.open( '/home/'+curtime+'zz', 'wb', encoding="latin-1" )
f.write( final )
f.close()

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
patrickk
User
Beiträge: 31
Registriert: Donnerstag 18. August 2005, 09:07

Hallo, so bekomme ich immer einen syntax fehler. Daher habe ich es wie oben gemacht. stimmt hier etwas nicht? Ich will keine datei oeffnen...
import codecs
f= codecs.open( '/home/'+curtime+'zz', 'wb', encoding="latin-1" )

Patrick

Die Probleme mit den umlauten und utf-8 haben bestimmt damit zu tun, dass utf8 Ascii entspricht, aber nur bis 128. Dann fangen die umlaute... an.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

patrickk hat geschrieben:Hallo, so bekomme ich immer einen syntax fehler.
Hm???
Poste mal den Traceback!

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@patrikk: Du hast ganz grosse Probleme mit dem Verständnis von Unicode und Kodierungen. Bevor Du Dich nicht gründlich damit auseinandergesetzt hast, solltest Du aufhören einfach nur wild herum zu probieren.
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Was willst du eigentlich machen? SMS verschicken?
BlackJack

Nachdem jetzt endlich die wirklich wichtigen Informationen bekannt sind, mal ein Versuch. Die Binärdaten sind also über Bytegrenzen hinweg gespeichert. Damit scheidet `str.translate()` aus. Das schwierigste ist das extrahieren der Werte aus den GSM kodierten Daten. Bits zu verschieben und zu maskieren ist immer ein wenig unübersichtlich.

Die Übersetzungstabelle legt man am besten in einer Unicode-Zeichenkette der Länge 128 ab. Ein Zeichen für jeden Wert, der in den GSM kodierten Daten vorkommen kann.

Das Übersetzen selbst beschränkt sich dann darauf, für jeden Wert das passende Zeichen in der Unicode-Zeichenkette abzufragen.

Code: Alles auswählen

from itertools import imap, cycle

def unpack_7bit(data):
    """Iterates over a string with 7 bit packed data and returns integer
    values between 0 and 127.
    
    The data is treated as a bitstream where the values are encoded as blocks
    of eight values in seven bytes according to the following pattern:
    
    ----  -------- -------- -------- -------- -------- -------- --------
    Byte         0        1        2        3        4        5        6
    ----  -------- -------- -------- -------- -------- -------- --------
    Bits  00000001 11111122 22222333 33334444 44455555 55666666 67777777
    ----  -------- -------- -------- -------- -------- -------- --------
    
    :param data: the data as byte string.
    :type data: `str`
    
    :returns: an iterator over the values.
    :rtype: iterator of `int`
    """
    bytes = imap(ord, data)
    tmp = bytes.next()
    try:
        for i in cycle(xrange(8)):
            # 
            # The first value in each 7 byte block is the only value that has
            # to be shifted right in the first byte.
            # 
            if i == 0:
                result = tmp >> 1
            else:
                # 
                # Extract the first part of the value from the first byte.
                # Move the bits to the correct position and clip everything
                # above bit 6.
                # 
                result = (tmp << (7 - i)) & 127
                # 
                # Extract the second part of the value from the second byte.
                # Move the bits to the correct position and ``or`` them into
                # the first part.
                # 
                tmp = bytes.next()
                result |= (tmp >> ((i + 1) % 8))
            yield result
    except StopIteration:
        # 
        # If the last byte was an '8th' value then result contains this
        # value and has to be returned.
        # 
        if i == 7:
            yield result


# 
# Mapping GSM codes to unicode characters.
# 
# There are 128 characters, written as 16 characters per line, in ISO-8859-15
# encoding.  The second line contains some ``?`` where the GSM charset defines
# a couple of greek symbols which are not in ISO-8859-15.
# 
gsm_unicode_map = ('@\xa3$\xa5\xe8\xe9\xf9\xec\xf2\xc7\n\xd8\xf8\r\xc5\xe5'
                   '?_??????????\xc6\xe6\xdf\xc9'
                   ' !"#\xa4%&\'()*+,-./'
                   '0123456789:;<=>?'
                   '\xa1ABCDEFGHIJKLMNO'
                   'PQRSTUVWXYZ\xc4\xd6\xd1\xdc\xa7'
                   '\xbfabcdefghijklmno'
                   'pqrstuvwxyz\xe4\xf6\xf1\xfc\xe0').decode('iso-8859-15')


def gsm_decode(data):
    """Decodes GSM encoded text to unicode."""
    return ''.join(gsm_unicode_map[code] for code in unpack_7bit(data))
BlackJack

Noch eine kleine Ergänzung. Die fehlenden griechischen Zeichen und der erweiterte GSM Zeichensatz sollten jetzt auch unterstützt werden.

Code: Alles auswählen

# 
# Mapping GSM codes to unicode characters.
# 
# There are 128 characters, written as 16 characters per line, except line 2
# which is splitted across two lines because it's length.
# 
gsm_unicode_map = (u'@\xa3$\xa5\xe8\xe9\xf9\xec\xf2\xc7\n\xd8\xf8\r\xc5\xe5'
                   u'\u0394_\u03a6\u0393\u039b\u03a9\u03a0\u03a8\u03a3\u0398'
                        u'\u039e?\xc6\xe6\xdf\xc9' # <- continued line 2
                   u' !"#\xa4%&\'()*+,-./'
                   u'0123456789:;<=>?'
                   u'\xa1ABCDEFGHIJKLMNO'
                   u'PQRSTUVWXYZ\xc4\xd6\xd1\xdc\xa7'
                   u'\xbfabcdefghijklmno'
                   u'pqrstuvwxyz\xe4\xf6\xf1\xfc\xe0')

# 
# Extended GSM charset.  These characters are escaped by code 27.
# 
gsm_extended_chars = {  10: u'\x0c',
                        20: u'^',
                        40: u'{',
                        41: u'}',
                        47: u'\\',
                        60: u'[',
                        61: u'~',
                        62: u']',
                        64: u'|',
                       101: u'\u20ac' }


def gsm_decode(data):
    """Decodes GSM encoded text to unicode."""
    unpacked_data_iter = unpack_7bit(data)
    result = list()
    for code in unpacked_data_iter:
        if code == 27:
            result.append(gsm_extended_chars[unpacked_data_iter.next()])
        else:
            result.append(gsm_unicode_map[code])
    return ''.join(result)
Der Syntaxhighlighter mag irgendwie kein Semikolon in Zeichenketten!? Bug oder Feature?
patrickk
User
Beiträge: 31
Registriert: Donnerstag 18. August 2005, 09:07

Danke fuer die Hilfe. konnte erst jetzt mir den Beitrag anschauen. Die tabelle kann man einfach aufgelistet anlegen. Ich habe jeden Eintrag mit : zugewiesen...
Nur die Dekodierung stimmt so nicht.
Es muss so gehen:

b7a1a2a3a4a5a6a7
c6c7b1b2b3b4b5b6
0 0 c1c2c3c4c5

das bit b7 muss rechts eingefuegt werden im naechsten Codewort. Im zweiten Schritt, dann die naechsten beiden links nach rechts fuers dritte... und achtung: Bei dem 7.ten schritt kaemen ja 7 in das naechste byte, was aber einem byte entspricht. Daher ist dies direkt das naecshte byte und danach geht es wieder von vorne los...
Das kann ich aber nicht mit shiften :-) Daher habe ich die zeichen nach hex gewandelt. Dann eine tabelle von hex nach bin, was ich als Zeichenkette angelegt habe. Und dort habe ich dann mit :... und tmp speicher rumgeschoben..
Deine Loesung waere aber viel eleganter!!

atrick
BlackJack

patrickk hat geschrieben:Nur die Dekodierung stimmt so nicht.
Okay, so sollte sie jetzt stimmen:

Code: Alles auswählen

from itertools import imap, cycle

def unpack_7bit(data):
    """Iterates over a string with 7 bit GSM packed data and returns integer
    values between 0 and 127.
    
    The data is treated as a bitstream where the values are encoded as blocks
    of eight values in seven bytes according to the following pattern:
    
    ----  --- -------- -------- -------- -------- -------- -------- --------
    Byte  ...       6        5        4        3        2        1        0
    ----  --- -------- -------- -------- -------- -------- -------- --------
    Bits  ... 77777776 66666655 55555444 44443333 33322222 22111111 10000000
    ----  --- -------- -------- -------- -------- -------- -------- --------
    
    The values are given in reverse order in the table.  The blocks of bits are
    in the correct order then, e.g the first value is simply the lower seven
    bits of byte 0 and the second is the MSB of byte 0 as LSB and the lower six
    bits of byte 1 as higher bits.  The values can be read right to left in the
    table above.
    
    :param data: the data as byte string.
    :type data: `str`
    
    :returns: an iterator over the values.
    :rtype: iterator of `int`
    """
    bytes = imap(ord, data)
    tmp = bytes.next()
    try:
        for i in cycle(xrange(8)):
            if i == 0:
                # 
                # The first value of each seven byte block is the only one
                # that is a) limited to one byte and b) doesn't have to be
                # shifted at all.
                # 
                result = tmp
            else:
                result = tmp >> (8 - i)
                tmp = bytes.next()
                result |= tmp << i
            yield result & 127
    except StopIteration:
        # 
        # If the last byte was an '8th' value then `result` contains this
        # value and has to be returned.
        # 
        if i == 7:
            yield result
Jetzt hatte ich auch eine kleine Testnachricht im Netz gefunden:

Code: Alles auswählen

def test():
    """A little test."""
    data = ('\xC8\x34\x28\xC8\x66\xBB\x40\x54\x74\x7A\x0E\x6A\x97\xE7\xF3\xF0'
            '\xB9\x0C\xBA\x87\xE7\xA0\x79\xD9\x4D\x07\xD1\xD1\xF2\x77\xFD\x8C'
            '\x06\x19\x5B\xC2\xFA\xDC\x05\x1A\xBE\xDF\xEC\x50\x08')
    print decode(data)
Antworten