wking's blog

  • 文章分类
    • 日常随笔
    • IT技术
    • 系统封装
    • 大航海时代
  • 关于博主
GOD'S IN HIS HEAVEN, ALL'S RIGHT WITH THE WORLD.
  1. 首页
  2. IT技术
  3. C++
  4. 正文

Visual Studio C++在控制台、文件存取和json库中正确显示和保存UTF-8字符编码

2023-01-30 1475点热度 0人点赞 0条评论

2023年了,堂堂大微软、宇宙第一IDE竟然连字符集都没法解决or统一,甚至都没有可设置项!虽然编程是全英语环境(ASCII码),但每个国家编写出来的程序肯定要和这个国家的语言打交道,世界上流行的语言也有十多种,只能用ASCII怎么行!

本文实验和记录如何在Visual Studio C++中的控制台、文件存取和json库中正确显示和保存UTF-8字符编码,包括中文、俄文、日文、希腊文和特殊符号等。UTF-8字符编码的好处参见http://utf8everywhere.org/zh-cn。

微软自己有一篇字符编码及转换的文章https://learn.microsoft.com/zh-cn/cpp/text/text-and-strings-in-visual-cpp?view=msvc-170。

实现效果

  • 控制台可正确显示UTF-8字符集。
  • nlohmann/json库可正确创建包含UTF-8字符的json对象实例。
  • 可正确保存包含UTF-8字符串的json格式文件。文件编码为UTF-8 with not BOM(无签名)。
  • 可正确读取包含UTF-8字符串的json格式文件。读取后json可正确解析UTF-8字符串。
实现效果

设置步骤

设置Visual Studio编译

Visual StudioMSVC 编译器选项,将源字符集和执行字符集设置为 UTF-8。

设置后,程序使用fstream等代码生成的文件会保存为UTF-8 with not BOM编码。

设置Visual Studio源文件保存编码

用扩展实现更方便:https://marketplace.visualstudio.com/items?itemName=WinstonFeng.VSFormatOnSave2022。安装扩展后,在VS工具-选项-format on save中,最后一个Enable ForceUtf8WithBom改为True。

Visual Studio菜单-文件-高级保存选项,编码设置为“UNICODE(UTF-8带签名) - 代码页 65001”。如果没找到高级保存选项,参考https://www.cnblogs.com/willingtolove/p/12121577.html。此设置生效范围为当前正在浏览的代码文件,之前已经生成的和未来创建的代码文件的编码仍然是GB2312。所以用扩展实现更方便。

main()函数添加代码

在Main()或wWinMain()函数的开头,添加以下代码:

Main()或wWinMain()函数开头添加代码
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  // 开启控制台
  AllocConsole();
 
  // 控制台显示乱码纠正
  system("chcp 65001"); //设置字符集 (使用SetConsoleCP(65001)设置无效,原因未知)
  CONSOLE_FONT_INFOEX info = { 0 }; // 以下设置字体
  info.cbSize = sizeof(info);
  info.dwFontSize.Y = 16; // 字体大小
  info.FontWeight = FW_NORMAL;
  wcscpy_s(info.FaceName, L"Consolas");  //你想显示的字体
  SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), NULL, &info);
 
  freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
  freopen_s((FILE**)stdout, "CONOUT$", "w", stderr);
  freopen_s((FILE**)stdout, "CONIN$", "r", stdin);
  std::cout.clear();
  std::clog.clear();
  std::cerr.clear();
  std::cin.clear();
 
  // std::wcout, std::wclog, std::wcerr, std::wcin
  HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  HANDLE hConIn = CreateFile(_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
  SetStdHandle(STD_ERROR_HANDLE, hConOut);
  SetStdHandle(STD_INPUT_HANDLE, hConIn);
  std::wcout.clear();
  std::wclog.clear();
  std::wcerr.clear();
  std::wcin.clear();
  cout << "cout  This works γηυ测试國ふそ▁☒☑■☾•♫¶¤φÇÏÅはにてヌホム㉢ㅆㅔㅃㅋㅝㅘㅎЩОёыфцэыъшмбгжф" << endl;
  // 开启控制台END

设置后,程序的控制台就可以正确显示UTF-8字符,不会出现乱码了。

下面是测试代码:

测试代码
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <fstream>
#include <nlohmann/json.hpp>
using namespace std;
using json = nlohmann::json;
  json j = {
    {"read",{
      {"player_id", {
        {"addr", 0x011B90C4},
        {"offest", {}},
        {"comment", "游戏角色的ID"},
      }},
      {"player_name", {
        {"addr", 0x011B90B8},
        {"offest", {0x10,0x20,0x30}},
        {"comment", "γηυ测试國ふそ▁☒☑■☾•♫¶¤φÇÏÅはにてヌホム㉢ㅆㅔㅃㅋㅝㅘㅎЩОёыфцэыъшмбгжф"},
      }},
    }},
  };
  try {
    ofstream o("pretty.json");
    o << std::setw(0) << j << std::endl;
    // read a JSON file
    std::ifstream k("pretty.json");
    json l = json::parse(k);
    json read = l["read"];
    cout << read["player_name"] << endl;
  }
  catch (exception& e) {
    cout << e.what() << endl;
  }
本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2023-01-30

wking

不管博客型博主

点赞
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

目录
  • 实现效果
  • 设置步骤
    • 设置Visual Studio编译
    • 设置Visual Studio源文件保存编码
    • main()函数添加代码
标签聚合
大航海时代 wordpress 一支红杏 C++ win10 linux R6300V2 OneNote

COPYRIGHT © 2024 wkings.blog. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang