2015-07-20 50 views
0

我希望使用utf-8編碼中的cp437字符映射。utf-8中選定的字符映射

我有每個cp437字符的所有代碼點。

下面的代碼正確地顯示一個CP437字符:

import locale 
locale.setlocale(locale.LC_ALL, '') 
icon u'\u263A'.encode('utf-8') 
print icon 

而下面的代碼顯示大部分CP437字符,而不是全部:

for i in range(0x00,0x100): 
    print chr(i).decode('cp437') 

我的猜測是,第2個方法沒有引用utf-8編碼,而是單獨的不完整的cp437字符集。

我想從utf-8中調用一個cp437字符,而不必指定每個256個單獨的代碼點。我用手工在一個大型的16x16表格中輸入了unicode代碼點字符串。有沒有更好的辦法?

下面的代碼演示了這一點:

from curses import * 
import locale 
locale.setlocale(locale.LC_ALL, '') 

def main(stdscr): 
    maxyx = stdscr.getmaxyx() 
    text= str(maxyx) 
    y_mid=maxyx[0]//2 
    x_mid=maxyx[1]//2 
    next_y,next_x = y_mid, x_mid 
    curs_set(1) 
    noecho() 
    event=1 
    y=0; x=0 
    icon1=u'\u2302'.encode('utf-8') 
    icon2=chr(0x7F).decode('cp437') 

    while event !=ord('q'): 
     stdscr.addstr(y_mid,x_mid-10,icon1) 
     stdscr.addstr(y_mid,x_mid+10,icon2) 
     event = stdscr.getch() 

wrapper(main)  

圖標左邊是UTF-8和沒有打印到屏幕上。 右邊的圖標是從解碼(「CP437」),並且不打印到屏幕上正確[顯示爲^]

+0

你爲什麼認爲cp437字符集是不完整的?你錯過了什麼[codepage中的代碼點](https://en.wikipedia.org/wiki/Code_page_437)?請注意,並非所有的代碼點都是*可打印的字符。* –

+1

Python cp437實現遵循Windows代碼頁,它使用代碼點0-127的ASCII表。我看到IBM ROM爲這些位置定義了位圖。我擔心那些會要求你創建一個你自己的桌子。 –

回答

0

作爲評價提及@Martijn,該股cp437解碼器轉換的字符0-127直到他們的ASCII等價物中。對於某些應用,這將是正確的,因爲您不希望'\n'轉換爲u'\u25d9'。但爲了完全保持代碼頁,您需要一個自定義的解碼器和編碼器。

codec模塊可以很容易地添加自己的編解碼器,但很難找到示例。我使用http://pymotw.com/2/codecs/的樣本以及​​來生成此模塊 - 導入它時,它會自動註冊名爲'cp437ex'的編解碼器。

import codecs 

codec_name = 'cp437ex' 

_table = u'\0\u263a\u263b\u2665\u2666\u2663\u2660\u2022\u25d8\u25cb\u25d9\u2642\u2640\u266a\u266b\u263c\u25ba\u25c4\u2195\u203c\xb6\xa7\u25ac\u21a8\u2191\u2193\u2192\u2190\u221f\u2194\u25b2\u25bc !"#$%&\'()*+,-./:;<=>[email protected][\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\xc7\xfc\xe9\xe2\xe4\xe0\xe5\xe7\xea\xeb\xe8\xef\xee\xec\xc4\xc5\xc9\xe6\xc6\xf4\xf6\xf2\xfb\xf9\xff\xd6\xdc\xa2\xa3\xa5\u20a7\u0192\xe1\xed\xf3\xfa\xf1\xd1\xaa\xba\xbf\u2310\xac\xbd\xbc\xa1\xab\xbb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\xdf\u0393\u03c0\u03a3\u03c3\xb5\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u03c6\u03b5\u2229\u2261\xb1\u2265\u2264\u2320\u2321\xf7\u2248\xb0\u2219\xb7\u221a\u207f\xb2\u25a0\xa0' 

decoding_map = { i: ord(ch) for i, ch in enumerate(_table) } 

encoding_map = codecs.make_encoding_map(decoding_map) 

class Codec(codecs.Codec): 
    def encode(self, input, errors='strict'): 
     return codecs.charmap_encode(input, errors, encoding_map) 

    def decode(self, input, errors='strict'): 
     return codecs.charmap_decode(input, errors, decoding_map) 


class IncrementalEncoder(codecs.IncrementalEncoder): 
    def encode(self, input, final=False): 
     return codecs.charmap_encode(input, self.errors, encoding_map)[0] 

class IncrementalDecoder(codecs.IncrementalDecoder): 
    def decode(self, input, final=False): 
     return codecs.charmap_decode(input, self.errors, decoding_map)[0] 


class StreamReader(Codec, codecs.StreamReader): 
    pass 

class StreamWriter(Codec, codecs.StreamWriter): 
    pass 


def _register(encoding): 
    if encoding == codec_name: 
     return codecs.CodecInfo(
      name=codec_name, 
      encode=Codec().encode, 
      decode=Codec().decode, 
      incrementalencoder=IncrementalEncoder, 
      incrementaldecoder=IncrementalDecoder, 
      streamreader=StreamReader, 
      streamwriter=StreamWriter) 

codecs.register(_register) 

還要注意的是decode產生Unicode字符串,而encode產生字節串。打印一個Unicode字符串應該始終有效,但是你的問題表明你可能有一個不正確的默認編碼。其中一個應該工作:

icon2='\x7f'.decode('cp437ex') 
icon2='\x7f'.decode('cp437ex').encode('utf-8')