对于EBCDIC(CP500)到Latin1转换器,这是一种合理的方法吗?

2024-06-01 02:33:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我必须将许多EBCDIC 500编码文件的大文件(高达2GB)转换为拉丁文-1。由于我只能找到EBCDIC到ASCII转换器(d d,recode),并且文件包含一些额外的专有字符代码,所以我想我应该编写自己的转换器。

我有character mapping所以我对技术方面感兴趣。

到目前为止,这是我的方法:

# char mapping lookup table
EBCDIC_TO_LATIN1 = {
  0xC1:'41', # A
  0xC2:'42', # B
  # and so on...
}

BUFFER_SIZE = 1024 * 64
ebd_file = file(sys.argv[1], 'rb')
latin1_file = file(sys.argv[2], 'wb')

  buffer = ebd_file.read(BUFFER_SIZE)
  while buffer:
    latin1_file.write(ebd2latin1(buffer))
    buffer = ebd_file.read(BUFFER_SIZE)

ebd_file.close()
latin1_file.close()

这是执行转换的函数:

def ebd2latin1(ebcdic):

   result = []
   for ch in ebcdic:
     result.append(EBCDIC_TO_LATIN1[ord(ch)])

   return ''.join(result).decode('hex')

问题是,从工程的角度来看,这是否是一种明智的方法。它有严重的设计问题吗?缓冲区大小可以吗?等等。。。

至于一些人不相信的“专有字符”:每个文件都包含一年的SGML格式的专利文档。专利局一直在使用EBCDIC,直到2005年他们改用Unicode。所以每个文件中都有成千上万的文档。它们由一些十六进制值分隔,这些值不是任何IBM规范的一部分。它们是由专利局添加的。此外,在每个文件的开头都有几个ASCII数字,告诉您文件的长度。我真的不需要这些信息,但如果我想处理文件,我必须处理它们。

另外:

$ recode IBM500/CR-LF..Latin1 file.ebc
recode: file.ebc failed: Ambiguous output in step `CR-LF..data'

谢谢你到目前为止的帮助。


Tags: 文件to方法sizebufferasciiresult字符
3条回答

EBCDIC 500,又名代码页500,是Python编码之一,虽然你链接到cp1047,但它没有。你在用哪一个,真的?不管怎样,这对cp500(或者你拥有的任何其他编码)都有效。

from __future__ import with_statement
import sys
from contextlib import nested

BUFFER_SIZE = 16384
with nested(open(sys.argv[1], 'rb'), open(sys.argv[2], 'wb')) as (infile, outfile):

    while True:
        buffer = infile.read(BUFFER_SIZE)
        if not buffer:
            break
        outfile.write(buffer.decode('cp500').encode('latin1'))

这样你就不需要自己跟踪映射了。

虽然这可能不再有助于原始海报,但不久前我发布了一个Python2.6+和3.2+的包,其中添加了大多数西方8位主机编解码器,包括CP1047(法语)和CP1141(德语):https://pypi.python.org/pypi/ebcdic。只需import ebcdic添加编解码器,然后使用open(..., encoding='cp1047')读取或写入文件。

如果正确设置了表格,则只需执行以下操作:

translated_chars = ebcdic.translate(EBCDIC_TO_LATIN1)

其中,ebcdic包含EBCDIC字符,EBCDIC_TO_LATIN1是一个256个字符的字符串,它将每个EBCDIC字符映射到它的拉丁-1等效字符。EBCDIC_TO_LATIN1中的字符是实际的二进制值,而不是它们的十六进制表示。例如,如果使用代码页500,则EBCDIC_TO_LATIN1的前16个字节将是

'\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F'

使用this reference

相关问题 更多 >