对于为什么脚本语言不能将Unicode输出到Windows控制台?感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍为什么脚本语言不需要编译,并为您提供关于Bash/WSL和Windows控制台的
对于为什么脚本语言不能将Unicode输出到Windows控制台?感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍为什么脚本语言不需要编译,并为您提供关于Bash / WSL和Windows控制台的新功能(Windows 10 Creato、c windows控制台输出颜色文字、c – 将数据传递到Windows控制台控制处理程序、Code - Windows 控制台关闭处理的有用信息。
本文目录一览:- 为什么脚本语言不能将Unicode输出到Windows控制台?(为什么脚本语言不需要编译)
- Bash / WSL和Windows控制台的新功能(Windows 10 Creato
- c windows控制台输出颜色文字
- c – 将数据传递到Windows控制台控制处理程序
- Code - Windows 控制台关闭处理
为什么脚本语言不能将Unicode输出到Windows控制台?(为什么脚本语言不需要编译)
Windows控制台至less有十年的时间了,而且可能早于Windows NT。 然而由于某些原因,包括Perl和Python在内的主要跨平台脚本语言只能输出各种8位编码,需要很多麻烦才能解决。 Perl给出了一个“宽字符打印”警告,Python给出一个charmap错误并退出。 为什么这些年来,他们不只是简单地调用输出UTF-16 Unicode的Win32-W API,而不是通过ANSI /代码页瓶颈强制所有的东西?
仅仅是跨平台性能低优先级? 难道这些语言在内部使用UTF-8,并且发现它太费心地输出UTF-16了吗? 或者是-W API固有地破坏到不能被原样使用的程度?
UPDATE
似乎这个责任可能需要各方分担。 我想到脚本语言只能在Windows上调用wprintf ,并让操作系统/运行时间担心redirect等问题。 但事实certificate, 即使Windows上的wprintf转换宽字符为ANSI,然后再打印到控制台 !
Java – 使用System.out.println()的Mac / Windows
键盘扫描码?
无法redirect程序的控制台输出
代码在Linux上运行良好,但在Windows操作系统上提供了不同的输出
C ++ AttachConsole包含错误
请让我知道,如果这已被修复,因为错误报告链接似乎中断,但我的Visual Ctesting代码仍然失败的wprintf和WriteConsoleW成功。
更新2
实际上你可以使用wprintf从C语言打印UTF-16到控制台,但是只有当你第一次使用_setmode(_fileno(stdout),_O_U16TEXT) 。
从C中可以打印UTF-8到代码页设置为代码页65001的控制台,但是Perl,Python,PHP和Ruby都有这样的错误。 Perl和PHP通过在包含至less一个宽字符的行之后添加额外的空行来破坏输出。 Ruby有不同的错误输出。 Python崩溃。
更新3
Node.js是第一个没有这个问题的脚本语言。
Python开发团队慢慢地意识到这是一个真正的问题,因为它是在2007年底第一次报告的,并且看到了大量的活动来充分理解和完全修复2016年的bug。
ruby。 如何在Windows上复制和粘贴irb?
用于Windows的Javascript控制台,如JSC
跨行分割命令
是否有Java的控制台分析器?
在.NET控制台应用程序中,防止Windows睡眠/hibernate
主要的问题似乎是,Windows上只能使用标准的C库而不使用平台相关或第三方扩展来使用Unicode。 你提到的语言来源于Unix平台,其实施Unicode的方法与C(它们使用普通的char*字符串,C语言环境函数和UTF-8)很好地融合在一起。 如果你想在C语言中做Unicode,那么你或多或少不得不写一切东西两次:一次使用非标准的Microsoft扩展,一次对所有其他操作系统使用标准C API函数。 虽然这可以完成,但通常没有高优先级,因为它很麻烦,大多数脚本语言开发人员无论如何都讨厌或忽略Windows。
在更技术层面上,我认为大多数标准库设计人员所做的基本假设是,所有I / O流本质上都是基于字节的,在操作系统级别上,这对所有操作系统上的文件以及Unix上的所有流类似的系统,Windows控制台是唯一的例外。 因此,如果要结合Windows控制台I / O,许多类库和编程语言标准的架构必须在很大程度上进行修改。
另一个更主观的观点是,微软只是不足以推动Unicode的使用。 第一个支持Unicode的Windows操作系统(支持它的时间)是1993年发布的Windows NT 3.1,早在Linux和OS X开始支持Unicode之后。 尽管如此,在这些操作系统中向Unicode的过渡却更加无缝和无争议。 微软再次听取了销售人员而不是工程师的意见,并将技术上过时的Windows 9x保留至2001年; 而不是迫使开发者使用一个干净的Unicode接口,他们仍然提供破碎的,现在不必要的8位API接口,并邀请程序员使用它(看看堆栈溢出最近的一些Windows API问题,大多数新手仍然使用可怕的遗留API!)。
当Unicode出来时,许多人意识到这是有用的。 Unicode开始是一个纯粹的16位编码,所以使用16位代码单元是很自然的。 微软然后显然说:“好吧,我们有这个16位编码,所以我们必须创建一个16位API”,没有意识到没有人会使用它。 然而,Unix界的佼佼者却认为,“我们怎样才能以高效,后向兼容的方式将其融入到当前系统中,以便人们真正使用它? 并随后发明了UTF-8,这是一个辉煌的工程。 就像Unix创建时一样,Unix的人想得更多,需要更长的时间,财务上的成功更少,但是最终做到了这一点。
我不能评论Perl(但是我认为Perl社区比Windows社区有更多的Windows仇恨),但是关于Python,我知道BDFL(谁不喜欢Windows)已经说明了足够的Unicode支持在所有平台上是一个主要目标。
对讨论的小贡献 – 我正在运行捷克本地化的Windows XP,它几乎在任何地方都使用CP1250代码页。 控制台有趣的是,它仍然使用传统的DOS 852代码页。
我能够使用非常简单的perl脚本来打印utf8编码的数据到控制台:
binmode STDOUT,":utf8:encoding(cp852)";
尝试了各种选项(包括utf16le),但只有以上设置正确打印重音捷克语字符。
编辑:我玩了一些问题,发现了Win32 :: Unicode 。 该模块导出的函数printW在输出和重定向中都能正常工作:
use utf8; use Win32::Unicode; binmode STDOUT,":utf8"; printW "Příliš žluťoučký kůň úpěl ďábelské ódy";
我不得不回答你的许多问题。
你知道吗
Windows为其API使用UTF-16,但仍默认使用用户空间中的各种“有趣的”遗留编码(例如Windows-1252,Windows-1251),包括文件名,对于Windows的许多本地化来说都是不同的?
你需要对输出进行编码,并且为系统选择合适的编码是通过语言环境编译指示来实现的,并且有一个叫做locale的POSIX标准,而且它是在这个标准上建立起来的,Windows与它是不兼容的?
Perl已经支持所谓的“宽”API了吗?
微软设法将UTF-8转换成字符编码的代码页系统,并且可以通过发出适当的chcp 65001命令来切换终端。
Michael Kaplan有一系列有关cmd控制台和Unicode的博客文章,这些博客文章可能是有用的(虽然没有真正回答你的问题):
传统智慧迟缓,又名@#%&*是_O_U16TEXT?
任何说控制台不能做Unicode的人都不像他们认为的那么聪明
情况的汇合留下了一块石头…
PS:谢谢@Jeff找到archive.org链接。
你确定你的脚本能正确地在其他平台上输出Unicode吗? “印刷中的宽字符”警告让我非常怀疑。
我建议查看这个概述
为什么这些年来,他们不只是简单地调用输出UTF-16 Unicode的Win32-W API,而是通过ANSI / codepage瓶颈来强制所有的东西?
因为Perl和Python不是Windows程序。 他们是Unix程序,几乎已经被移植到Windows。 因此,除非必要,否则他们不喜欢调用Win32函数。 对于基于字节的I / O,这是没有必要的; 这可以用标准C语言库来完成。 基于UTF-16的I / O是一个特例。
或者是-W API固有地破坏到不能被原样使用的程度?
我不会说,-W API本质上已经被打破了,就像我说的那样,微软在C(++)中的Unicode方法本质上已经被破坏了。
无论有多少Windows开发人员坚持认为程序应该使用wchar_t而不是char ,切换的障碍就太多了:
平台依赖:
在Windows上使用UTF-16 wchar_t在其他地方使用UTF-32 wchar_t 。 (新的char16_t和char32_t类型可能会有所帮助。)
UTF-16文件名函数(如_wfopen , _wstat等)的_wstat限制了在跨平台代码中使用wchar_t的能力。
教育。 有人用printf("Hello,world!n");学习C printf("Hello,world!n"); ,而不是wprintf(L"Hello,world!n"); 。 我在大学使用的C教科书从未提到宽字符,直到附录A.13。
现有的无数条使用char*字符串的代码行。
为了让Perl完全支持Windows,每一个print printf调用都会warn ,并且不得不被修改。
这是Windows吗?
哪个版本的Windows? Perl仍然主要在Windows 95上工作
这是去控制台,还是其他地方。
一旦你确定了,你就必须使用一组完全不同的API函数。
如果你真的想看到正确做这件事的一切,看看Win32 :: Unicode :: Console的来源 。
在Linux,OpenBSD,FreeBSD和类似的操作系统上,你通常可以在STDOUT和STDERR文件句柄上调用binmode 。
binmode STDOUT,':utf8'; binmode STDERR,':utf8';
这假定终端正在使用UTF-8编码。
对于Python,跟踪器中的相关问题是http://bugs.python.org/issue1602 (如评论中所述)。 请注意,这是开放7年。 我试图发布一个工作解决方案(基于问题中的信息)作为Python包: https : //github.com/Drekin/win-unicode-console,https : //pypi.python.org/pypi/win_unicode_console 。
在Perl中的Unicode问题
涵盖了Win32控制台如何与Perl协同工作,以及从ANSI到Unicode的场景后面的代码转换;尽管不仅仅是Perl问题,还会影响其他语言
Bash / WSL和Windows控制台的新功能(Windows 10 Creato
总结
以上是小编为你收集整理的Bash \/ WSL和Windows控制台的新功能(Windows 10 Creato全部内容。
如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。
c windows控制台输出颜色文字
#include <windows.h>
//设置文字颜色
void SetColor(int ForgC)
{
WORD wColor;
//We will need this handle to get the current background attribute
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
//We use csbi for the wAttributes word.
if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
{
//Mask out all but the background attribute, and add in the forgournd color
wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
SetConsoleTextAttribute(hStdOut, wColor);
}
}
0 - BLACK 黑 深色0 - 7
1 - BLUE 兰 2 - GREEN 绿
3 - CYAN 青 4 - RED 红
5 - MAGENTA 洋红 6 - BROWN 棕
7 - LIGHTGRAY 淡灰 8 - DARKGRAY 深灰 淡色8 - 15
9 - LIGHTBLUE 淡兰 10 - LIGHTGREEN 淡绿
11 - LIGHTCYAN 淡青 12 - LIGHTRED 淡红
13 - LIGHTMAGENTA 淡洋红 14 - YELLOW 黄
15 - WHITE 白
例子:
void print_char()
{
printf("Game\n");
printf("---------------------\n");
printf("\n|----|----|----|\n");
for(int i=0;i<3;i++)
{
printf("|");
for(int j=0;j<3;j++)
{
if (a[i][j]!=0)
{
if (randx == i && randy == j)
{
SetColor(4);
printf("%3d",a[i][j]);
SetColor(15);
printf(" |");
}
else
{
SetColor(15);
printf("%3d |",a[i][j]);
}
}
else
{
SetColor(15);
printf(" |");
}
}
if(i<=3)
{
printf("\n|____|____|____|\n");
}
}
}
c – 将数据传递到Windows控制台控制处理程序
我首先调用此代码来指定我的回调函数:
SetConsoleCtrlHandler((PHANDLER_ROUTINE)WindowsSystemManager::ConsoleControlHandler,true);
我的静态成员回调函数定义为:
bool WINAPI WindowsSystemManager::ConsoleControlHandler(DWORD controlType){ if(controlType == CTRL_CLOSE_EVENT){ MessageBox(NULL,L"Close Event Captured",NULL); } return true; }
一切正常 – 当我点击控制台中的关闭按钮时,会弹出此MessageBox.唯一的问题是,我需要在这种类型的关闭(以及其他清理)中调用将日志缓冲区刷新到日志文件的代码,并且Logger实例是我的WindowsSystemManager中的成员.
我已经成功地通过使用SetwindowLongPtr和getwindowlongPtr处理了将自定义数据传递给窗口句柄的类似问题,但我找不到有关如何使用控制台控件处理程序执行此类操作的任何信息.有什么想法吗?
编辑:我根据MSalters的建议实现了这项功能.控制台控制处理程序的最终代码在这里:
bool WINAPI WindowsSystemManager::ConsoleControlHandler(DWORD controlType){ BerserkEngine* engine = (BerserkEngine*)getwindowlongPtr(GetConsoleWindow(),GWLP_USERDATA); if(controlType == CTRL_CLOSE_EVENT){ engine->~BerserkEngine(); PostQuitMessage(0); } return true; }
我在WindowsSystemManager构造函数中设置此自定义数据指针的位置:
SetwindowLongPtr(GetConsoleWindow(),GWL_USERDATA,(LONG_PTR)this->engine);
解决方法
但是,GetConsoleWindow将为您提供控制台HWND,您可以在其上调用SetwindowLongPtr.不是很干净(你不应该在你不管理的窗户上这样做),但它可能只是工作.
Code - Windows 控制台关闭处理
#include <stdio.h>
#include <time.h>
#include <setjmp.h>
#include <Windows.h>
static jmp_buf g_JmpBuf;
static int g_ThreadRun = 0;
static HANDLE g_hThread = INVALID_HANDLE_VALUE;
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
{
puts("user interrupt!");
switch (dwCtrlType)
{
case CTRL_C_EVENT:
//longjmp(g_JmpBuf,1);
break;
case CTRL_BREAK_EVENT:
//longjmp(g_JmpBuf,1);
break;
case CTRL_CLOSE_EVENT:
longjmp(g_JmpBuf,1);
break;
case CTRL_LOGOFF_EVENT:
break;
case CTRL_SHUTDOWN_EVENT:
break;
}
return TRUE;
}
DWORD WINAPI pthread_start_routine(LPVOID lpThreadParameter)
{
WORD activeTime = *((WORD*)lpThreadParameter);
time_t beginTime = time(NULL);
time_t current = 0;
while( g_ThreadRun )
{
if( (current = time(NULL) - beginTime) < activeTime )
{
printf("%lu \r",activeTime - current);
fflush(stdout);
Sleep(500);
}
else
{
break;
}
}
puts("!!!");
return 0;
}
int main(int argc, char * argv[])
{
WORD activeTime = 0;
SetConsoleCtrlHandler(HandlerRoutine,TRUE);
if( 1 == setjmp(g_JmpBuf) )
{
g_ThreadRun = 0;
WaitForSingleObject(g_hThread,INFINITE);
CloseHandle(g_hThread);
return EXIT_FAILURE;
}
if(argc > 1)
{
activeTime = atoi(argv[1]);
}
else
{
puts("Input shutdown time(sec):");
scanf("%lu",&activeTime);
}
printf("SET(%lu) second\n",activeTime);
if(activeTime > 0)
{
g_hThread = CreateThread(NULL,0,pthread_start_routine,(LPVOID)&activeTime,0,NULL);
if(g_hThread == INVALID_HANDLE_VALUE)
{
puts("start thread fail");
return EXIT_FAILURE;
}
g_ThreadRun = 1;
}
if(g_hThread != INVALID_HANDLE_VALUE)
{
WaitForSingleObject(g_hThread,INFINITE);
CloseHandle(g_hThread);
}
puts("SHUT_DOWN!!!");
//ExitWindowsEx(EWX_SHUTDOWN,0x00);
return EXIT_SUCCESS;
}
今天的关于为什么脚本语言不能将Unicode输出到Windows控制台?和为什么脚本语言不需要编译的分享已经结束,谢谢您的关注,如果想了解更多关于Bash / WSL和Windows控制台的新功能(Windows 10 Creato、c windows控制台输出颜色文字、c – 将数据传递到Windows控制台控制处理程序、Code - Windows 控制台关闭处理的相关知识,请在本站进行查询。
本文标签: