给我烤些莫吉


26

给定一个字符串,字符列表,字节流,序列…,它们既是有效的UTF-8,又是有效的Windows-1252(大多数语言可能会希望使用普通的UTF-8字符串),然后将其转换为(即假装为)Windows-1252UTF-8

演练示例

UTF-8字符串
I            UTF-8
表示为字节,
49 20E2 99 A520 55 54 46 2D 38
这些字节在Windows-1252表字节值为我们提供了Unicode等效形式
49 20 E2 2122 A5 20 55 54 46 2D 38
,这些形式表示为
I ⥠UTF-8

例子

£Â£

£Â£

£Â£

I ♥ UTF-8I ♥ UTF-8

árvíztűrő tükörfúrógépárvÃztűrÅ‘ tükörfúrógép


9
@ user202729请参阅“转换”链接。双关语。
暴民埃里克(Erik the Outgolfer)

5
为方便起见:Windows 1252字符集与Unicode相同,但0x80..0x9F中的字符为€ ‚ƒ„…†‡ˆ‰Š‹Œ Ž ‘’“”•–—˜™š›œ žŸ。(空间=未使用)
user202729

3
@ user202729嗯,我不确定您要说的是什么,但这远不是真的。Unicode有几百万字的,Windows的1252只256
大卫·康拉德

1
@DavidConrad,“ Unicode有数百万个字符”被夸大了。Unicode定义了1,114,112个代码点。当前使用了136,690个代码点。
Wernfried Domscheit,

1
@Wernfried的重点是将其与256个字符的字符集进行比较。
戴维·康拉德

Answers:



19

Java 8,72 66 36 25字节

s->new String(s,"cp1252")

在线尝试。

s->  // Method with byte-array (UTF-8 by default) as parameter and String return-type
  new String(s,"cp1252")
     //  Pretend this UTF-8 input is (and convert it to) Windows-1252,
     //  and return it as UTF-8 String (by default) as well

cp1252是的别名Windows-1252。该别名cp1252java.iojava.langAPI 的规范名称,而全名Windows-1252java.nioAPI 的规范名称。有关受支持的Java编码的完整列表,请参见此处,我们始终希望使用两者中的最短代码进行编码。


13
Java赢得代码高尔夫‽这是不对的。
亚当

1
@AdámHehe,我也很高兴看到所有这些更长的答案。;)但是我很确定Jelly,05AB1E等很快就会击败我。
凯文·克鲁伊森

1
我不信。他们可能没有内置的转换表。Dyalog APL做,虽然...
亚当

java.nioAPI的规范名称”:P
仅ASCII的2006年

8

R 3.5.0或更高版本,32 20字节

scan(,"",e="latin1")

在线尝试!

奇怪的是R中的挑战的简称... 多亏JayCe高尔夫球了12个字节!

scan(可选)采用encoding参数来设置输入字符串的编码。latin1对应于,根据Encoding

关于“ Latin-1”语言环境的含义存在一些歧义,因为某些操作系统(尤其是Windows)使用用于ISO 8859-1字符集中的控制字符的字符位置。此类字符的解释方式取决于系统,但从R 3.5.0版本开始,如果可能,在转换为例如UTF-8时,将根据Windows代码页1252(Microsoft称为“ Windows Latin 1(ANSI)”)对其进行解释。


3
我点击了Encoding... 文档的链接,并得知它scan也有一个encoding参数O_O ... 20个字节
JayCe

@JayCe da打它!非常好!
朱塞佩

6

Python 2中40 38个字节

-2个字节,感谢Outgolfer的Erik

lambda s:s.decode('1252').encode('u8')

在线尝试!

u8是的别名utf-8


也许您可以通过以下方式“作弊”:input().decode(...).encode(...):)另外,我认为如果在Powershell中,您也许可以使用某些Windows控制台编码(但我对此完全不确定)。
KeyWeeUsr


@KeyWeeUsr您的建议的问题是与链接的答案相反,它实际上没有输出任何内容。R会输出裸表达式的值,而不会。
ovs


3

JavaScript,64字节

x=>new TextDecoder('cp1252').decode(new TextEncoder().encode(x))

比Java答案还要更长的时间。好难过。:(



3

C#,81个字节

using e=System.Text.Encoding;s=>e.GetEncoding(1252).GetString(e.UTF8.GetBytes(s))

在线尝试!

感谢Schmalls提供了3个字节


可以将using e=System.Text.Encoding;s=>e.GetEncoding(1252).GetString(e.UTF8.GetBytes(s))其降低到81吗?
Schmalls

@Schmalls看起来是的,谢谢!
Mego

2

180字节机器码(16位x86)

我注意到大多数答案都使用内置的编码/解码(我认为这很好),但是我认为我将继续执行16位的查询

与以前的方法一样,无需使用编译器就可以完成此任务,使用HT hexeditorICY的hexplorer即可

00000000: eb40 ac20 0000 1a20 9201 1e20 2620 2020  .@. ... ... &                     
00000010: 2120 c602 3020 6001 3920 5201 0000 7d01  ! ..0 `.9 R...}.                  
00000020: 0000 0000 1820 1920 1c20 1d20 2220 1320  ..... . . . " .                   
00000030: 1420 dc02 2221 6101 3a20 5301 0000 7e01  . .."!a.: S...~.                  
00000040: 7801 89f7 4646 89fa 89d9 4143 4bb4 3fcd  x...FF....ACK.?.                  
00000050: 2185 c074 288a 053c 8073 05e8 1700 ebec  !..t(..<.s......                  
00000060: 3ca0 721a d440 0d80 c050 86c4 e806 0058  <.r..@...P.....X                  
00000070: e802 00eb d7b4 4088 05b3 01cd 21c3 2c80  ......@.....!.,.                  
00000080: d0e0 89c3 8b00 89cb 85c0 74c0 3dff 0773  ..........t.=..s                  
00000090: 08c1 c002 c0e8 02eb cd50 c1e8 0c0c e0e8  .........P......                  
000000a0: d3ff 5825 ff0f c1c0 02c0 e802 0d80 8050  ..X%...........P                  
000000b0: 86c4 ebb8                                ....                              

bake.com <input.txt> out.dat

解剖

实施非常简单明了,尽管我并没有想过要提前进行,所以那里有些意大利面条。

我将混合一些顺序,以使其更容易理解...

0000 eb40               jmp         0x42

跳过将chars> = 0x80 <0xa0映射到unicode代码的表。

data db ACh,20h, 00h,00h, 1Ah,20h, ...

无效的编码为0,不会映射到任何内容

0075 b440               mov         ah, 0x40   
0077 8805               mov         [di], al   
0079 b301               mov         bl, 0x1    
007b cd21               int         0x21       
007d c3                 ret                    

用于在中打印char的Helper函数al将被调用几次。

0042 89f7               mov         di, si     
0044 46                 inc         si         
0045 46                 inc         si         
0046 89fa               mov         dx, di     
0048 89d9               mov         cx, bx     
004a 41                 inc         cx         
004b 43                 inc         bx         

准备寄存器。数据将被读入0x100,让其si指向上面的转换表。

004c 4b                 dec         bx         
004d b43f               mov         ah, 0x3f   
004f cd21               int         0x21       
0051 85c0               test        ax, ax     
0053 7428               jz          0x7d       

从stdin读取char,如果EOF则跳转到0x7d。

旁注:这实际上是一个小技巧(但众所周知),0x7d contains ret,这将导致pop spsp在段的起点到终点00 00cs:0在DOS包含CD 20,这导致应用程序退出。

0055 8a05               mov         al, [di]   
0057 3c80               cmp         al, 0x80   
0059 7305               jnc         0x60       
005b e81700             call        0x75       
005e ebec               jmp         0x4c       

如果char <0x80,只需将其打印出来,然后转到循环的开头(因为辅助功能将BX设置为1-stdout,跳转将转到dec bx

0060 3ca0               cmp         al, 0xa0   
0062 721a               jc          0x7e       
0064 d440               aam         0x40       
0066 0d80c0             or          ax, c080   
0069 50                 push        ax         
006a 86c4               xchg        ah, al     
006c e80600             call        0x75       
006f 58                 pop         ax         
0070 e80200             call        0x75       
0073 ebd7               jmp         0x4c       

此部分处理chars> = 0xa0,将ascii代码分为“高”两位和“低” 6位,并为两个字节应用utf-8掩码c080,然后打印两个字节

007e 2c80               sub         al, 0x80   
0080 d0e0               shl         al, 0x1    
0082 89c3               mov         bx, ax     
0084 8b00               mov         ax, [bx+si]
0086 89cb               mov         bx, cx     
0088 85c0               test        ax, ax     
008a 74c0               jz          0x4c       
008c 3dff07             cmp         ax, 07ff   
008f 7308               jnc         0x99       
0091 c1c002             rol         ax, 0x2    
0094 c0e802             shr         al, 0x2    
0097 ebcd               jmp         0x66       

这部分处理chars> = 0x80 <0xa0,它在顶部的表中找到正确的utf-8代码,如果代码等于0,则在0x7ff以下时跳到开头(ergo:适合两个UTF-8字节) ,只需调整该值并在0x166处重复使用以前的代码即可。

0099 50                 push        ax         
009a c1e80c             shr         ax, 0xc    
009d 0ce0               or          al, e0     
009f e8d3ff             call        0x75       
00a2 58                 pop         ax         
00a3 25ff0f             and         ax, 0fff   
00a6 c1c002             rol         ax, 0x2    
00a9 c0e802             shr         al, 0x2    
00ac 0d8080             or          ax, 8080   
00af 50                 push        ax         
00b0 86c4               xchg        ah, al     
00b2 ebb8               jmp         0x6c       

最后一部分,处理高于0x7FF的代码,将低12位降低,应用0xE0(请参阅UTF-8编码说明以供参考)并打印出来,调整低12位并应用8080掩码,并再次使用将两个字符分开的部分。


1

PHP + mbstring63 49字节

<?=mb_convert_encoding($argv[1],'UTF8','CP1252');

由于缺少mbstring,因此在TIO上不起作用。第三个参数强制mbstring将字符串解释为Windows-1252编码

-14字节,感谢Ismael Miguel


<?=mb_convert_encoding($argv[1],'UTF8','CP1252');<-更短!
Ismael Miguel

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.