关于ASCII_8BIT

Encoding :: ASCII_8BIT是一种特殊的编码,通常用于字节字符串,而不是字符串。 但是,顾名思义,其在ASCII范围内的字符被视为ASCII字符。 当您将ASCII-8BIT字符与其他ASCII兼容字符一起使用时,这很有用。

资料来源: ruby-doc.org/core-2.6.4

语境

我想使用ASCII_8BIT,因为我需要对0x00(0d00)和0xff(0d255)之间的所有字符进行编码,因此ASCII(0-127)加上扩展的ASCII(128-255)。 ASCII(编码,US-ASCII)是一种7位编码,只能识别ASCII(字符集)字符(0-127)。 顾名思义,我期望ASCII_8BIT将其扩展到8位以增加对128-255的支持。

问题

当我使用chr时,编码会自动设置为ASCII_8BIT,但是当我放入时,我直接将128-255(0x80-0xff)之间的一个字符放在字符串中,然后询问我使用的是UTF-8编码是什么,以及是否尝试将其转换为ASCII_8BIT会出错。

irb(main):014:0> 0x8f.chr
=> "\x8F"
irb(main):015:0> 0x8f.chr.encoding
=> #<Encoding:ASCII-8BIT>
irb(main):016:0> "\x8f".encode(Encoding::ASCII_8BIT)
Traceback (most recent call last):
        5: from /usr/bin/irb:23:in `<main>'
        4: from /usr/bin/irb:23:in `load'
        3: from /usr/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
        2: from (irb):16
        1: from (irb):16:in `encode'
Encoding::InvalidByteSequenceError ("\x8F" on UTF-8)
irb(main):021:0> "\x8F".encoding
=> #<Encoding:UTF-8>

红宝石核心中是否存在错误? 我需要能够编码8之间的所有内容

ASCII 8BIT的另一个名称是BINARY,因为如前一个引号所述,它应该能够编码任何字节。

irb(main):035:0> Encoding::ASCII_8BIT.names
=> ["ASCII-8BIT", "BINARY"]

其他编码

请告诉我使用其他编码不是该问题的答案,除非它是一种确实映射了所有255个扩展ASCII字符的编码。

  • 我不想使用UTF-8,因为编码是多字节而不是单字节。
  • ISO / IEC 8859-1(拉丁文1位,8位)仅包含191个字符(ASCII + 63个字符)

    ISO字符集与代码页不同的一种值得注意的方式是,尽管ISO字符集经常使用,但对应于具有高位位集的ASCII控制字符的字符位置128至159在ISO标准中并未特别使用和未定义专有代码页中的可打印字符,几乎打破了通用的ISO标准。 参考 扩展的ASCII- ISO 8859和专有的修改

  • Windows-1252(CP-1252,8bits)不包含所有255个字符,并且不包含ASCII扩展名

红宝石可用的编码:

irb(main):036:0> Encoding.name_list
=> ["ASCII-8BIT", "UTF-8", "US-ASCII", "UTF-16BE", "UTF-16LE", "UTF-32BE", "UTF-32LE", "UTF-16", "UTF-32", "UTF8-MAC", "EUC-JP", "Windows-31J", "Big5", "Big5-HKSCS", "Big5-UAO", "CP949", "Emacs-Mule", "EUC-KR", "EUC-TW", "GB2312", "GB18030", "GBK", "ISO-8859-1", "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-11", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-8859-16", "KOI8-R", "KOI8-U", "Shift_JIS", "Windows-1250", "Windows-1251", "Windows-1252", "Windows-1253", "Windows-1254", "Windows-1257", "BINARY", "IBM437", "CP437", "IBM737", "CP737", "IBM775", "CP775", "CP850", "IBM850", "IBM852", "CP852", "IBM855", "CP855", "IBM857", "CP857", "IBM860", "CP860", "IBM861", "CP861", "IBM862", "CP862", "IBM863", "CP863", "IBM864", "CP864", "IBM865", "CP865", "IBM866", "CP866", "IBM869", "CP869", "Windows-1258", "CP1258", "GB1988", "macCentEuro", "macCroatian", "macCyrillic", "macGreek", "macIceland", "macRoman", "macRomania", "macThai", "macTurkish", "macUkraine", "CP950", "Big5-HKSCS:2008", "CP951", "IBM037", "ebcdic-cp-us", "stateless-ISO-2022-JP", "eucJP", "eucJP-ms", "euc-jp-ms", "CP51932", "EUC-JIS-2004", "EUC-JISX0213", "eucKR", "eucTW", "EUC-CN", "eucCN", "GB12345", "CP936", "ISO-2022-JP", "ISO2022-JP", "ISO-2022-JP-2", "ISO2022-JP2", "CP50220", "CP50221", "ISO8859-1", "ISO8859-2", "ISO8859-3", "ISO8859-4", "ISO8859-5", "ISO8859-6", "Windows-1256", "CP1256", "ISO8859-7", "ISO8859-8", "Windows-1255", "CP1255", "ISO8859-9", "ISO8859-10", "ISO8859-11", "TIS-620", "Windows-874", "CP874", "ISO8859-13", "ISO8859-14", "ISO8859-15", "ISO8859-16", "CP878", "MacJapanese", "MacJapan", "ASCII", "ANSI_X3.4-1968", "646", "UTF-7", "CP65000", "CP65001", "UTF-8-MAC", "UTF-8-HFS", "UCS-2BE", "UCS-4BE", "UCS-4LE", "CP932", "csWindows31J", "SJIS", "PCK", "CP1250", "CP1251", "CP1252", "CP1253", "CP1254", "CP1257", "UTF8-DoCoMo", "SJIS-DoCoMo", "UTF8-KDDI", "SJIS-KDDI", "ISO-2022-JP-KDDI", "stateless-ISO-2022-JP-KDDI", "UTF8-SoftBank", "SJIS-SoftBank", "locale", "external", "filesystem", "internal"]

为了比较python编码https://docs.python.org/3/library/codecs.html#standard-encodings

注意事项

通过阅读扩展ASCII多字节字符编码 ,似乎唯一真正的扩展ASCII编码是UTF-8,但是是Multi-byte。 似乎也不存在真正的扩展ASCII单字节编码。

从字节的角度来看,我可以使用这里所说的任何8位(单字节)编码扩展的ASCII-在计算机可读语言中的用法

所有ASCII字节(0x00至0x7F)在扩展ASCII的所有变体中都具有相同的含义,

但是问题在于,像ISO-8859-1这样的实现专门未定义某些char范围,因此将以错误结尾。

irb(main):009:0> (0..255).map { |c| c.chr}.join.encode(Encoding::ISO_8859_1)
Traceback (most recent call last):
        6: from /usr/bin/irb:23:in `<main>'
        5: from /usr/bin/irb:23:in `load'
        4: from /usr/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
        3: from (irb):9
        2: from (irb):9:in `rescue in irb_binding'
        1: from (irb):9:in `encode'
Encoding::UndefinedConversionError ("\x80" to UTF-8 in conversion from ASCII-8BIT to UTF-8 to ISO-8859-1)

更新-force_encoding

我发现了字符串方法force_encoding

irb(main)> a = "\x8f"
=> "\x8F"
irb(main)> a.encoding
=> #<Encoding:UTF-8>
irb(main)> a.encode(Encoding::ASCII_8BIT)
Traceback (most recent call last):
        5: from /usr/bin/irb:23:in `<main>'
        4: from /usr/bin/irb:23:in `load'
        3: from /usr/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
        2: from (irb):42
        1: from (irb):42:in `encode'
Encoding::InvalidByteSequenceError ("\x8F" on UTF-8)
irb(main)> a.force_encoding(Encoding::ASCII_8BIT)
=> "\x8F"
irb(main):040:0> a.encoding
=> #<Encoding:ASCII-8BIT>

什么是使用的危险force_encoding而非encode 仅仅是如果我不小心传递了一个多字节字符,它将被转换为多个单字节字符吗? 因此,如果可以确保传递给应用程序的所有字符都在扩展的ASCII范围(单字节)中,但是不安全,并且例如将某些UTF-8字符传递给应用程序,将导致无提示转换问题,这并不危险。

irb(main):044:0> "\ud087".force_encoding(Encoding::ASCII_8BIT)
=> "\xED\x82\x87"
irb(main):045:0> "\ud087".bytes
=> [237, 130, 135]

更新-答案

@ mu-is-too-short的答案和@ ForeverZer0注释表明,我宁愿使用packunpack来处理原始字节。

因此,与其使用编码和变通方法

pattern = 'A' * 2606 + "\x8F\x35\x4A\x5F" + 'C' * 390
pattern.force_encoding(Encoding::ASCII_8BIT)

我应该直接使用字节

pattern = ['A'.ord] * 2606 + [0x8F, 0x35, 0x4A, 0x5F] + ['C'.ord] * 390
pattern = pattern.pack('C*')

或者这更易于阅读的语法

pattern = 'A'.bytes * 2606 + "\x8F\x35\x4A\x5F".bytes + 'C'.bytes * 390
pattern = pattern.pack('C*')

#1楼 票数:4 已采纳

字符串字面量(通常)是UTF-8编码的,与字节是否有效的UTF-8无关。 因此:

"\x8f".encoding

即使字符串不是有效的UTF-8,也要说UTF-8。 使用String#force_encoding应该是安全的,但是如果您真的想使用原始字节,则最好使用整数数组并使用Array#pack将它们混搭为字符串:

[ 0x8f, 0x11, 0x06, 0x23, 0xff, 0x00 ].pack('C*')
# "\x8F\x11\x06#\xFF\x00" 
[ 0x8f, 0x11, 0x06, 0x23, 0xff, 0x00 ].pack('C*').encoding
# #<Encoding:ASCII-8BIT> 
[ 0x8f, 0x11, 0x06, 0x23, 0xff, 0x00 ].pack('C*').bytes
# [143, 17, 6, 35, 255, 0] 

结果应该是相同的,但是,IMO,这是显式地使用二进制数据(即原始字节),使您的意图明确,并且应该避免任何编码问题。

如果正在读取的字节有已知的结构,并且您想将其破解,则还有String#unpack

#2楼 票数:2

如果您正在执行原始数据包操作,则所有内容都必须处于BINARY / ASCII_8BIT模式,因为它不是文本 ,因此不应被视为此类。 如果您有其他编码方式,Ruby将尝试对其进行转换,在最佳情况下,它将严重破坏二进制数据,在最坏情况下,由于转换错误而导致崩溃。

用Ruby术语来说, ASCII_8BIT实际上是原始数据缓冲区。

代码中字符串的默认编码为UTF-8:

p "example".encoding
# => #<Encoding:UTF-8>

您可以使用# encoding: BINARY为每个文件的内联字符串设置Ruby编码:

# encoding: BINARY

p "example".encoding
# => #<Encoding:ASCII-8BIT>

正如mu指出的那样,通常最好使用pack工具来表示二进制数据,在这种情况下,您不会出错并且一开始就没有真正使用字符串。 这很重要,因为8位值易于处理,但是16位和32位值必须正确地进行端序编码,因此您经常会看到很多这样的情况:

header = pack('nn', qtype, qclass)

这是组成一个包含两个16位值的DNS标头的地方。

  ask by noraj translate from so

未解决问题?本站智能推荐:

1回复

这是什么扩展的ASCII编码,如何让ruby理解它?

字符0x91 , 0x92 , 0x93和0x94应该代表在Unicode的是什么U+2018 , U+2019 , U+201c和U+201d ,或“开单引号”, “收单引号”,“开头的双引号”和“结尾的双引号”。 我以为是ISO-8859-1但是当我尝试使用IO.read('file',
4回复

在Ruby中显示扩展ASCII字符

如何将扩展ASCII字符打印到控制台。 例如,如果我使用以下内容 它会在控制台上打印“9”。 如果我要使用 它只会显示“?”。 它对所有从128到254的扩展ASCII代码执行此操作。是否有一种方法可以显示正确的字符而不是“?”。
1回复

将Unicode字符转换为扩展ASCII

我有一些二进制数据,必须对其进行百分比编码才能通过长度受限制的查询字符串参数传输到远程服务。 回到我身上,其中一些值的编码如下: 我希望将此值转换回二进制数据。 Unicode字符与扩展ASCII中的原始值相同。 如何将以上内容转换回扩展ASCII? 编辑:Windows
1回复

PHP:将扩展的 Ascii 文件转换为 UTF-8

我没有任何机会获得有效的 utf-8 作为输出... 如何转换或删除 ? 28.05.2020 更新:找到解决方案,感谢 Andrea Pollini! 一些注意事项: 这是我真正的问题(我后来经过多次测试才发现): 现在它正在工作。 但是如果有人知道为什么数组要转换字符串以及如何
6回复

如何使用Perl在文件中找到扩展的ASCII字符?

如何使用Perl在文件中找到扩展的ASCII字符? 任何人都可以获得脚本吗? .....提前致谢.....
1回复

在Ruby中将字符串从UTF-8转换为ASCII-8BIT?

我必须将包含意大利语语句的UTF-8编码的Ruby字符串打印到ESC / POS热敏打印机(仅接受ASCII-8BIT(1字节)字符集的打印机: http : //maxdb.sap.com/doc/ 7_6 / ca /​​ bd35406ee32e34e10000000a155106 / c
2回复

使用准备好的语句在mySql中扩展ascii字符

使用准备好的语句和值绑定在mysql中插入(或更新)记录时,我遇到了一个问题,试图插入包含扩展的ASCII字符145(右单引号)的child's单词。 “ d”之后的所有数据均被截断。 对于插入任何MS Word奇数字符都是如此。 我的表被编码为utf8_general_ci,并且在我的代
1回复

如何读取ASCII值在128-130范围内并将其转换为int值的char

我有一个字符数组,其中一些是ASCII 128和十进制130。 我试图将它们作为普通字符读取,但不是128,而是将8218作为int(转换为字节,得到26)。 我需要在128到130之间得到这个数字。我发现了一些关于编码的文章,有些人说我需要使用编码439。 有任何想法吗?