首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何让getLine接受unicode字符?

如何让getLine接受unicode字符?
EN

Stack Overflow用户
提问于 2018-08-02 11:52:16
回答 1查看 341关注 0票数 4

运行以下代码时

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
do line <- getLine
   putStrLn line

或,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
getLine >>= putStrLn

然后,之后

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 getLine >>= putStrLn

入场

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
µ

我们会遇到这样的输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

现在,我已经预先尝试过chcp 65001了,它不起作用,而stdin的编码是utf8

没有putStrLn的考试显示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 getLine
µ
'\NIL'

我的环境:

Windows 10版本10.0.17134构建17134

联想ideapad 510-15 510

BIOS版联想3JCN30WW

GHCi诉8.2.2

如何解决这一问题?

编辑:具体来说,以下操作顺序导致了这种情况:

  1. 开放cmd
  2. chcp 65001
  3. ghci
  4. getLine >>= putStrLn
  5. µ

然而,以下并不是:

  1. 搜索ghci
  2. 开放ghci.exe at %PROGRAMS%\Haskell Platform\8.2.2\bin
  3. 重复4-5次。

注意:%PROGRAMS%不是真实的环境变量。

编辑:根据请求,GHC.IO.Encoding.getLocaleEncoding的输出

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
UTF-8

此外,System.IO.hGetEncoding stdin的输出

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Just UTF-8

(使用chcp 65001时)

编辑:字符是U+00B5。我使用德国键盘,系统本地化德国,语言设置英语,键盘语言ENG与德语布局。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-05 02:14:10

控制台输入/输出在Windows上完全崩溃,而且已经有一段时间了。下面是跟踪Windows上与IO相关的所有问题的顶级票证:https://ghc.haskell.org/trac/ghc/ticket/11394

我相信,这两张票最能描述你正在经历的行为:

现在唯一的工作就是手动使用Windows来处理控制台输出/输入,这本身就是一个痛苦。

编辑

所以,我决定忍受一些痛苦。:)

下面是代码的输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
====
Input: µ
Output: µ
====

这绝不是一个完全正确或安全的解决方案,但它确实有效:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module Main where

import Control.Monad
import System.IO
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.C.String
import Foreign.C.Types
import Foreign.Storable

import System.Win32
import System.Win32.Types
import Graphics.Win32.Misc

foreign import ccall unsafe "windows.h WriteConsoleW"
  c_WriteConsoleW :: HANDLE -> LPWSTR -> DWORD -> LPDWORD -> LPVOID -> IO BOOL

foreign import ccall unsafe "windows.h ReadConsoleW"
  c_ReadConsoleW :: HANDLE -> LPWSTR -> DWORD -> LPDWORD -> LPVOID -> IO BOOL

-- | Read n characters from a handle, which should be a console stdin
hwGetStrN :: Int -> Handle -> IO String
hwGetStrN maxLen hdl = do
  withCWStringLen (Prelude.replicate maxLen '\NUL') $ \(cstr, len) -> do
    lpNumberOfCharsWrittenForeignPtr <- mallocForeignPtr
    withHandleToHANDLE hdl $ \winHANDLE ->
      withForeignPtr lpNumberOfCharsWrittenForeignPtr $ \lpNumberOfCharsRead -> do
        c_ReadConsoleW winHANDLE cstr (fromIntegral len) lpNumberOfCharsRead nullPtr
        numWritten <- peek lpNumberOfCharsRead
        peekCWStringLen (cstr, fromIntegral numWritten)

-- | Write a string to a handle, which should be a console stdout or stderr.
hwPutStr :: Handle -> String -> IO ()
hwPutStr hdl str = do
  void $ withCWStringLen str $ \(cstr, len) -> do
    lpNumberOfCharsWrittenForeignPtr <- mallocForeignPtr
    withHandleToHANDLE hdl $ \winHANDLE ->
      withForeignPtr lpNumberOfCharsWrittenForeignPtr $ \ lpNumberOfCharsWritten ->
      c_WriteConsoleW winHANDLE cstr (fromIntegral len) lpNumberOfCharsWritten nullPtr

main :: IO ()
main = do
  hwPutStr stdout "====\nInput: "
  str <- hwGetStrN 10 stdin
  hwPutStr stdout "Output: "
  hwPutStr stdout str
  hwPutStr stdout "====\n"

编辑2

@dfeuer要求我列出不安全、不正确或不完整的问题,并给出答案。我只在Linux上编写代码,所以我不是Windows程序员,但在真正的程序中使用这些代码之前,我会突然想到一些需要改变的东西:

  • 最重要的部分是代码只能与控制台句柄一起工作,控制台句柄可以通过GetConsoleMode API调用来确定。
  • 对于其他类型的句柄,上面的代码将什么也不做,例如。如果与管道或文件句柄一起使用,则在编码方面有自己的问题,但这是一个完全不同的问题。
  • 未考虑API调用失败的原因。因此,我们必须通过查看返回的BOOL来检查调用是否成功,并在不使用GetLastError向用户报告错误时进行检查。
  • 上面实现的函数是非常有限的,没有检查它们实际读/写了多少缓冲区。因此,hwGetStrN只能处理n字符,因此需要递归调用才能获得类似于hGetLine的行为。
  • 做所有的健全检查(如)。DWORDWord32,因此fromIntegral len调用容易受到整数溢出的影响,这既不正确又不安全。
  • 在32位操作系统上,FFI调用必须是stdcall,而ccall则是x86_64,所以有些CPP是必需的。
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51661192

复制
相关文章
C#对字符串进行加密解密
明志德道
2023/10/21
3870
C#对字符串进行加密解密
如何使用Java进行加密和解密
在Java中,我们可以使用许多不同的加密和解密技术来保护数据。这些技术可以用于加密密码、保护敏感数据、网络通信等。下面将介绍Java中常用的加密和解密技术和实现方法。
用户1289394
2023/09/22
6690
如何使用Java进行加密和解密
使用PBE方式进行加密,解密
package com.demo.pbe; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKeyFactory; import javax.c
用户1215919
2018/02/09
2.7K0
PHP使用DES进行加密和解密
DES是一种标准的数据加密算法,关于这个算法的详细介绍可以参考wiki和百度百科:
大江小浪
2018/07/25
2K1
PHP使用DES进行加密和解密
DES是一种标准的数据加密算法,关于这个算法的详细介绍可以参考wiki和百度百科: wiki百科 百度百科 php中有一个扩展可以支持DES的加密算法,是:extension=php_mcrypt.dll 在配置文件中将这个扩展打开还不能够在windows环境下使用 需要将PHP文件夹下的 libmcrypt.dll 拷贝到系统的 system32 目录下,这是通过phpinfo可以查看到mcrypt表示这个模块可以正常试用了。  下面是PHP中使用DES加密解密的一个例子: 1 //$input - s
joshua317
2018/04/16
1.2K0
如何使用DotfuscatorPro_4.9对软件进行加密
DotfuscatorPro_4.9可以防止你的.NET软件被反编译,可以在一定程度上防止你的软件被反编译。现在很多软件都有被反编译的现象,虽然不能做到百分百的防范,但是你至少可以先做些技术上的处理,至少能挡住许多小白。
战神伽罗
2019/07/24
1.5K0
如何使用DotfuscatorPro_4.9对软件进行加密
使用hutool的非对称加密工具进行加密解密
RSA是最流行的非对称加密算法之一。也被称为公钥加密。它是由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)在1977年一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
JQ实验室
2023/01/13
4.8K0
使用crypto.js进行信息加密解密
<script type="text/javascript" src="./crypto-js.js"></script> <script type="text/javascript"> var password = 'password' // 待加密字段 var secretKey = 'fizz' // key console.log(`待加密字段: ${password}`) var aestext = CryptoJS.AES.encrypt(password,secretKey) co
拿我格子衫来
2022/01/24
4.7K0
使用crypto.js进行信息加密解密
JAVA对字符串内容进行AES、DES加密解密
有时候java项目中需要对我们传输的内容进行加密,以确保数据的安全性,所以用到了其中的AES加密解密,不多说,直接上代码,看AES如何对字符串进行加密解密的:
一诺千金
2020/06/24
3.7K0
JAVA对字符串内容进行AES、DES加密解密
C语言如何实现DES加密与解密
在工作中遇到的Des解密问题,第三方发来的数据需要我们进行des解密,但是解密的结果前几位始终是乱码。废了半天劲,终于找到了问题所在。
芯动大师
2023/10/14
5392
C语言如何实现DES加密与解密
C# AES 加密 解密
// 输入代码内容 /// <summary> /// Aes加密解密 /// @author lishuai /// @date 20220527 13:01 /// </summary> public class AesUtil { /// <summary> /// AES加密 (128-ECB加密模式) /// </summary> /// <param name="toEncrypt
BrianLee
2022/05/27
2.8K0
C# AES 加密 解密
使用jmeter对字符串进行加密
这次仍然使用百度通用翻译接口当做案例,因为它刚好有一个参数就是经过md5加密得来的
冰霜
2022/03/19
1.3K0
使用jmeter对字符串进行加密
实用脚本!利用 Python 对 PDF 进行加密、解密操作,代码拿走就用!
本文将分享如何利用 Python 对 PDF 进行加密和解密操作,主要利用到之前多次介绍过的PyPDF2 模块。
崔庆才
2021/06/24
2.8K0
实用脚本!利用 Python 对 PDF 进行加密、解密操作,代码拿走就用!
nodejs使用aes-128-ecb加密如何在c#中解密
却发现C#端怎么也解密不了,一直报错,改了一整天,后来终于发现,nodejs端加密用的key其实在使用之前已经使用md5加密了一次,而这个操作是默认的,暂时没发现有配置可以默认去掉,服务端如果需要使用这个key解密,则需要也同样使用MD5加密
frontoldman
2019/09/03
2.6K0
【C 语言】文件操作 ( 读文本文件 | 文本加密解密 | fgets 函数 | fputs 函数 )
多行文本读取 : 通过 feop 函数判定是否读取到了文件结尾 , 如果已经读取到了文件结尾 , 则返回 true ;
韩曙亮
2023/03/29
1.4K0
【C 语言】文件操作 ( 读文本文件 | 文本加密解密 | fgets 函数 | fputs 函数 )
C#加密解密(AES)-AESHelper
using System; namespace Encrypt { public class AESHelper { /// <summary> /// 默认密钥-密钥的长度必须是32 /// </summary> private const string PublicKey = "1234567890123456"; /// <summary> /// 默认向量 /// </
KenTalk
2018/09/11
9.1K0
【C 语言】文件操作 ( 文件加密解密 | 解密文件 )
个文件 , 一个是原始文件 , 一个是加密后的文件 , 将原始文件进行加密 , 然后将加密后的数据输出到加密文件中 ;
韩曙亮
2023/03/30
9.5K0
[Spring Boot] 如何优雅的对配置文件进行加密
Jasypt Spring Boot为Spring Boot Applications中的属性源提供加密支持。 有三种方法可以集成jasypt-spring-boot到您的项目中:
架构探险之道
2019/08/06
8.3K0
使用luks2对ceph rbd进行加密
多个行业(例如金融行业)越来越需要在主机上使用租户/用户提供的加密密钥以卷粒度加密数据。这是由国家法规和对安全性的日益重视所推动的。迄今为止,Ceph RBD 不提供任何此类解决方案,现有的替代方案是在 libRBD 之前添加一个加密层。此类解决方案的示例是使用 QEMU LUKS 加密或依赖 DM-Crypt。但是,在与 RBD 层中实现的存储功能接口时,使用 RBD 之上的加密层有局限性。当我们进行镜像克隆时,只有在父子节点使用相同的加密密钥加密时才会起作用。通过将加密向下移动到 libRBD,就可以灵活地使用 Ceph RBD 克隆了。
没有故事的陈师傅
2022/09/15
9420
使用luks2对ceph rbd进行加密
点击加载更多

相似问题

如何利用Azure IoT集线器的功能应用?

15

使用Azure MQTT集线器作为IoT代理

12

为什么Azure IoT集线器有事件集线器作为端点?

15

Azure IoT集线器验证

121

Azure IoT集线器证书

24
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文