Trang mã / mã hóa nào được cmd.exe sử dụng?


271

Khi tôi mở cmd.exe trong Windows, nó đang sử dụng mã hóa gì?

Làm thế nào tôi có thể kiểm tra mã hóa hiện đang sử dụng? Có phụ thuộc vào cài đặt khu vực của tôi hoặc có bất kỳ biến môi trường nào để kiểm tra không?

Điều gì xảy ra khi bạn nhập một tệp với một mã hóa nhất định? Đôi khi tôi nhận được các ký tự bị cắt xén (sử dụng mã hóa không chính xác) và đôi khi nó là loại công việc. Tuy nhiên tôi không tin bất cứ điều gì miễn là tôi không biết chuyện gì đang xảy ra. Bất cứ ai có thể giải thích?

Câu trả lời:


389

Có, đôi khi nó làm nản lòng typevà các chương trình khác in vô nghĩa, và đôi khi chúng không.

Trước hết, các ký tự Unicode sẽ chỉ hiển thị nếu phông chữ bảng điều khiển hiện tại có chứa các ký tự . Vì vậy, hãy sử dụng phông chữ TrueType như Bảng điều khiển Lucida thay vì Phông chữ Raster mặc định.

Nhưng nếu phông chữ bảng điều khiển không chứa ký tự bạn đang cố hiển thị, bạn sẽ thấy các dấu hỏi thay vì vô nghĩa. Khi bạn cảm thấy vô nghĩa, sẽ có nhiều hơn là chỉ cài đặt phông chữ.

Khi các chương trình sử dụng các chức năng I / O của thư viện C tiêu chuẩn như printf, mã hóa đầu ra của chương trình phải khớp với mã hóa đầu ra của bàn điều khiển , nếu không bạn sẽ bị sai lệch. chcphiển thị và thiết lập bảng mã hiện tại. Tất cả đầu ra sử dụng các chức năng I / O của thư viện C tiêu chuẩn được xử lý như thể nó nằm trong bảng mã được hiển thị bởi chcp.

Việc kết hợp mã hóa đầu ra của chương trình với mã hóa đầu ra của bàn điều khiển có thể được thực hiện theo hai cách khác nhau:

  • Một chương trình có thể lấy bảng mã hiện tại của bàn điều khiển bằng cách sử dụng chcphoặc GetConsoleOutputCP, và định cấu hình chính nó để xuất ra mã hóa đó, hoặc

  • Bạn hoặc một chương trình có thể thiết lập bảng mã hiện tại của bàn điều khiển bằng cách sử dụng chcphoặc SetConsoleOutputCPđể khớp với mã hóa đầu ra mặc định của chương trình.

Tuy nhiên, các chương trình sử dụng API Win32 có thể ghi các chuỗi UTF-16LE trực tiếp vào bảng điều khiển với WriteConsoleW. Đây là cách duy nhất để có được đầu ra chính xác mà không cần thiết lập bảng mã. Và ngay cả khi sử dụng chức năng đó, nếu một chuỗi không có trong mã hóa UTF-16LE để bắt đầu, một chương trình Win32 phải chuyển mã chính xác đến MultiByteToWideChar. Ngoài ra, WriteConsoleWsẽ không hoạt động nếu đầu ra của chương trình được chuyển hướng; khó khăn hơn là cần thiết trong trường hợp đó.

typehoạt động đôi khi vì nó kiểm tra sự bắt đầu của mỗi tệp cho Dấu thứ tự byte (BOM) UTF-16LE , tức là các byte 0xFF 0xFE. Nếu nó tìm thấy một dấu như vậy, nó sẽ hiển thị các ký tự Unicode trong tệp bằng cách sử dụng WriteConsoleW bất kể bảng mã hiện tại. Nhưng khi nhập typebất kỳ tệp nào không có BOM UTF-16LE hoặc để sử dụng các ký tự không phải ASCII với bất kỳ lệnh nào không gọi thì WriteConsoleWbạn sẽ cần phải thiết lập bảng mã điều khiển và mã hóa đầu ra chương trình để khớp với nhau.


Làm thế nào chúng ta có thể tìm ra điều này?

Đây là một tệp thử nghiệm chứa các ký tự Unicode:

ASCII     abcde xyz
German    äöü ÄÖÜ ß
Polish    ąęźżńł
Russian   абвгдеж эюя
CJK       你好

Đây là một chương trình Java để in ra tệp thử nghiệm trong một loạt các mã hóa Unicode khác nhau. Nó có thể là trong bất kỳ ngôn ngữ lập trình; nó chỉ in các ký tự ASCII hoặc byte được mã hóa thành stdout.

import java.io.*;

public class Foo {

    private static final String BOM = "\ufeff";
    private static final String TEST_STRING
        = "ASCII     abcde xyz\n"
        + "German    äöü ÄÖÜ ß\n"
        + "Polish    ąęźżńł\n"
        + "Russian   абвгдеж эюя\n"
        + "CJK       你好\n";

    public static void main(String[] args)
        throws Exception
    {
        String[] encodings = new String[] {
            "UTF-8", "UTF-16LE", "UTF-16BE", "UTF-32LE", "UTF-32BE" };

        for (String encoding: encodings) {
            System.out.println("== " + encoding);

            for (boolean writeBom: new Boolean[] {false, true}) {
                System.out.println(writeBom ? "= bom" : "= no bom");

                String output = (writeBom ? BOM : "") + TEST_STRING;
                byte[] bytes = output.getBytes(encoding);
                System.out.write(bytes);
                FileOutputStream out = new FileOutputStream("uc-test-"
                    + encoding + (writeBom ? "-bom.txt" : "-nobom.txt"));
                out.write(bytes);
                out.close();
            }
        }
    }
}

Đầu ra trong codepage mặc định? Tổng rác!

Z:\andrew\projects\sx\1259084>chcp
Active code page: 850

Z:\andrew\projects\sx\1259084>java Foo
== UTF-8
= no bom
ASCII     abcde xyz
German    ├ñ├Â├╝ ├ä├û├£ ├ƒ
Polish    ąęźżńł
Russian   ð░ð▒ð▓ð│ð┤ðÁð ÐìÐÄÐÅ
CJK       õ¢áÕÑ¢
= bom
´╗┐ASCII     abcde xyz
German    ├ñ├Â├╝ ├ä├û├£ ├ƒ
Polish    ąęźżńł
Russian   ð░ð▒ð▓ð│ð┤ðÁð ÐìÐÄÐÅ
CJK       õ¢áÕÑ¢
== UTF-16LE
= no bom
A S C I I           a b c d e   x y z
 G e r m a n         õ ÷ ³   ─ Í ▄   ▀
 P o l i s h         ♣☺↓☺z☺|☺D☺B☺
 R u s s i a n       0♦1♦2♦3♦4♦5♦6♦  M♦N♦O♦
 C J K               `O}Y
 = bom
 ■A S C I I           a b c d e   x y z
 G e r m a n         õ ÷ ³   ─ Í ▄   ▀
 P o l i s h         ♣☺↓☺z☺|☺D☺B☺
 R u s s i a n       0♦1♦2♦3♦4♦5♦6♦  M♦N♦O♦
 C J K               `O}Y
 == UTF-16BE
= no bom
 A S C I I           a b c d e   x y z
 G e r m a n         õ ÷ ³   ─ Í ▄   ▀
 P o l i s h        ☺♣☺↓☺z☺|☺D☺B
 R u s s i a n      ♦0♦1♦2♦3♦4♦5♦6  ♦M♦N♦O
 C J K              O`Y}
= bom
■  A S C I I           a b c d e   x y z
 G e r m a n         õ ÷ ³   ─ Í ▄   ▀
 P o l i s h        ☺♣☺↓☺z☺|☺D☺B
 R u s s i a n      ♦0♦1♦2♦3♦4♦5♦6  ♦M♦N♦O
 C J K              O`Y}
== UTF-32LE
= no bom
A   S   C   I   I                       a   b   c   d   e       x   y   z
   G   e   r   m   a   n                   õ   ÷   ³       ─   Í   ▄       ▀
   P   o   l   i   s   h                   ♣☺  ↓☺  z☺  |☺  D☺  B☺
   R   u   s   s   i   a   n               0♦  1♦  2♦  3♦  4♦  5♦  6♦      M♦  N
♦  O♦
   C   J   K                               `O  }Y
   = bom
 ■  A   S   C   I   I                       a   b   c   d   e       x   y   z

   G   e   r   m   a   n                   õ   ÷   ³       ─   Í   ▄       ▀
   P   o   l   i   s   h                   ♣☺  ↓☺  z☺  |☺  D☺  B☺
   R   u   s   s   i   a   n               0♦  1♦  2♦  3♦  4♦  5♦  6♦      M♦  N
♦  O♦
   C   J   K                               `O  }Y
   == UTF-32BE
= no bom
   A   S   C   I   I                       a   b   c   d   e       x   y   z
   G   e   r   m   a   n                   õ   ÷   ³       ─   Í   ▄       ▀
   P   o   l   i   s   h                  ☺♣  ☺↓  ☺z  ☺|  ☺D  ☺B
   R   u   s   s   i   a   n              ♦0  ♦1  ♦2  ♦3  ♦4  ♦5  ♦6      ♦M  ♦N
  ♦O
   C   J   K                              O`  Y}
= bom
  ■    A   S   C   I   I                       a   b   c   d   e       x   y   z

   G   e   r   m   a   n                   õ   ÷   ³       ─   Í   ▄       ▀
   P   o   l   i   s   h                  ☺♣  ☺↓  ☺z  ☺|  ☺D  ☺B
   R   u   s   s   i   a   n              ♦0  ♦1  ♦2  ♦3  ♦4  ♦5  ♦6      ♦M  ♦N
  ♦O
   C   J   K                              O`  Y}

Tuy nhiên, điều gì sẽ xảy ra nếu chúng ta lưu typecác tệp? Chúng chứa các byte chính xác được in ra bàn điều khiển.

Z:\andrew\projects\sx\1259084>type *.txt

uc-test-UTF-16BE-bom.txt


■  A S C I I           a b c d e   x y z
 G e r m a n         õ ÷ ³   ─ Í ▄   ▀
 P o l i s h        ☺♣☺↓☺z☺|☺D☺B
 R u s s i a n      ♦0♦1♦2♦3♦4♦5♦6  ♦M♦N♦O
 C J K              O`Y}

uc-test-UTF-16BE-nobom.txt


 A S C I I           a b c d e   x y z
 G e r m a n         õ ÷ ³   ─ Í ▄   ▀
 P o l i s h        ☺♣☺↓☺z☺|☺D☺B
 R u s s i a n      ♦0♦1♦2♦3♦4♦5♦6  ♦M♦N♦O
 C J K              O`Y}

uc-test-UTF-16LE-bom.txt


ASCII     abcde xyz
German    äöü ÄÖÜ ß
Polish    ąęźżńł
Russian   абвгдеж эюя
CJK       你好

uc-test-UTF-16LE-nobom.txt


A S C I I           a b c d e   x y z
 G e r m a n         õ ÷ ³   ─ Í ▄   ▀
 P o l i s h         ♣☺↓☺z☺|☺D☺B☺
 R u s s i a n       0♦1♦2♦3♦4♦5♦6♦  M♦N♦O♦
 C J K               `O}Y

uc-test-UTF-32BE-bom.txt


  ■    A   S   C   I   I                       a   b   c   d   e       x   y   z

   G   e   r   m   a   n                   õ   ÷   ³       ─   Í   ▄       ▀
   P   o   l   i   s   h                  ☺♣  ☺↓  ☺z  ☺|  ☺D  ☺B
   R   u   s   s   i   a   n              ♦0  ♦1  ♦2  ♦3  ♦4  ♦5  ♦6      ♦M  ♦N
  ♦O
   C   J   K                              O`  Y}

uc-test-UTF-32BE-nobom.txt


   A   S   C   I   I                       a   b   c   d   e       x   y   z
   G   e   r   m   a   n                   õ   ÷   ³       ─   Í   ▄       ▀
   P   o   l   i   s   h                  ☺♣  ☺↓  ☺z  ☺|  ☺D  ☺B
   R   u   s   s   i   a   n              ♦0  ♦1  ♦2  ♦3  ♦4  ♦5  ♦6      ♦M  ♦N
  ♦O
   C   J   K                              O`  Y}

uc-test-UTF-32LE-bom.txt


 A S C I I           a b c d e   x y z
 G e r m a n         ä ö ü   Ä Ö Ü   ß
 P o l i s h         ą ę ź ż ń ł
 R u s s i a n       а б в г д е ж   э ю я
 C J K               你 好

uc-test-UTF-32LE-nobom.txt


A   S   C   I   I                       a   b   c   d   e       x   y   z
   G   e   r   m   a   n                   õ   ÷   ³       ─   Í   ▄       ▀
   P   o   l   i   s   h                   ♣☺  ↓☺  z☺  |☺  D☺  B☺
   R   u   s   s   i   a   n               0♦  1♦  2♦  3♦  4♦  5♦  6♦      M♦  N
♦  O♦
   C   J   K                               `O  }Y

uc-test-UTF-8-bom.txt


´╗┐ASCII     abcde xyz
German    ├ñ├Â├╝ ├ä├û├£ ├ƒ
Polish    ąęźżńł
Russian   ð░ð▒ð▓ð│ð┤ðÁð ÐìÐÄÐÅ
CJK       õ¢áÕÑ¢

uc-test-UTF-8-nobom.txt


ASCII     abcde xyz
German    ├ñ├Â├╝ ├ä├û├£ ├ƒ
Polish    ąęźżńł
Russian   ð░ð▒ð▓ð│ð┤ðÁð ÐìÐÄÐÅ
CJK       õ¢áÕÑ¢

Điều duy nhất hoạt động là tệp UTF-16LE, với BOM, được in ra bàn điều khiển thông qua type.

Nếu chúng tôi sử dụng bất cứ thứ gì ngoài typeviệc in tệp, chúng tôi sẽ nhận được rác:

Z:\andrew\projects\sx\1259084>copy uc-test-UTF-16LE-bom.txt CON
 ■A S C I I           a b c d e   x y z
 G e r m a n         õ ÷ ³   ─ Í ▄   ▀
 P o l i s h         ♣☺↓☺z☺|☺D☺B☺
 R u s s i a n       0♦1♦2♦3♦4♦5♦6♦  M♦N♦O♦
 C J K               `O}Y
         1 file(s) copied.

Từ thực tế copy CONkhông hiển thị Unicode chính xác, chúng ta có thể kết luận rằng typelệnh có logic để phát hiện BOM UTF-16LE khi bắt đầu tệp và sử dụng API Windows đặc biệt để in.

Chúng ta có thể thấy điều này bằng cách mở cmd.exetrình gỡ lỗi khi nó đi type ra một tệp:

nhập mô tả hình ảnh ở đây

Sau khi typemở một tệp, nó sẽ kiểm tra BOM của 0xFEFFĐieie, các byte 0xFF 0xFEtrong Little endian endian và nếu có BOM như vậy, hãy typeđặt fOutputUnicodecờ nội bộ . Cờ này được kiểm tra sau để quyết định có gọi hay không WriteConsoleW.

Nhưng đó là cách duy nhất để có được typeđầu ra Unicode và chỉ cho các tệp có BOM và ở dạng UTF-16LE. Đối với tất cả các tệp khác và đối với các chương trình không có mã đặc biệt để xử lý đầu ra của bàn điều khiển, các tệp của bạn sẽ được diễn giải theo bảng mã hiện tại và có thể sẽ hiển thị dưới dạng vô nghĩa.

Bạn có thể mô phỏng cách typexuất Unicode cho bảng điều khiển trong các chương trình của riêng bạn như sau:

#include <stdio.h>
#define UNICODE
#include <windows.h>

static LPCSTR lpcsTest =
    "ASCII     abcde xyz\n"
    "German    äöü ÄÖÜ ß\n"
    "Polish    ąęźżńł\n"
    "Russian   абвгдеж эюя\n"
    "CJK       你好\n";

int main() {
    int n;
    wchar_t buf[1024];

    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

    n = MultiByteToWideChar(CP_UTF8, 0,
            lpcsTest, strlen(lpcsTest),
            buf, sizeof(buf));

    WriteConsole(hConsole, buf, n, &n, NULL);

    return 0;
}

Chương trình này hoạt động để in Unicode trên bảng điều khiển Windows bằng cách sử dụng bảng mã mặc định.


Đối với chương trình Java mẫu, chúng ta có thể nhận được một chút đầu ra chính xác bằng cách đặt mã hóa theo cách thủ công, mặc dù đầu ra bị rối theo những cách kỳ lạ:

Z:\andrew\projects\sx\1259084>chcp 65001
Active code page: 65001

Z:\andrew\projects\sx\1259084>java Foo
== UTF-8
= no bom
ASCII     abcde xyz
German    äöü ÄÖÜ ß
Polish    ąęźżńł
Russian   абвгдеж эюя
CJK       你好
ж эюя
CJK       你好
 你好
好
�
= bom
ASCII     abcde xyz
German    äöü ÄÖÜ ß
Polish    ąęźżńł
Russian   абвгдеж эюя
CJK       你好
еж эюя
CJK       你好
  你好
好
�
== UTF-16LE
= no bom
A S C I I           a b c d e   x y z
…

Tuy nhiên, chương trình C thiết lập bảng mã Unicode UTF-8:

#include <stdio.h>
#include <windows.h>

int main() {
    int c, n;
    UINT oldCodePage;
    char buf[1024];

    oldCodePage = GetConsoleOutputCP();
    if (!SetConsoleOutputCP(65001)) {
        printf("error\n");
    }

    freopen("uc-test-UTF-8-nobom.txt", "rb", stdin);
    n = fread(buf, sizeof(buf[0]), sizeof(buf), stdin);
    fwrite(buf, sizeof(buf[0]), n, stdout);

    SetConsoleOutputCP(oldCodePage);

    return 0;
}

không có đầu ra chính xác:

Z:\andrew\projects\sx\1259084>.\test
ASCII     abcde xyz
German    äöü ÄÖÜ ß
Polish    ąęźżńł
Russian   абвгдеж эюя
CJK       你好

Noi dung chinh cua cau chuyen?

  • type có thể in các tệp UTF-16LE bằng BOM bất kể mã hóa hiện tại của bạn
  • Các chương trình Win32 có thể được lập trình để xuất Unicode ra bàn điều khiển, bằng cách sử dụng WriteConsoleW.
  • Các chương trình khác thiết lập codepage và điều chỉnh mã hóa đầu ra của chúng phù hợp có thể in Unicode trên bàn điều khiển bất kể codepage là gì khi chương trình bắt đầu
  • Đối với mọi thứ khác, bạn sẽ phải loay hoay với chcp, và có thể vẫn sẽ nhận được đầu ra kỳ lạ.

73
Whoa, đây phải là câu trả lời chi tiết nhất tôi từng thấy trên SO. Tín dụng thêm cho các bản in tháo gỡ và skillz đa ngôn ngữ! Đẹp quá, thưa ngài!
cuộc không kích

2
Người ta cũng có thể muốn nghiên cứu phần mở rộng cụ thể của Microsoft _setmode (_fileno (stdout), _O_U16TEXT) đã được giới thiệu trong VS2008. Xem stackoverflow.com/a/9051543stackoverflow.com/a/12015918msdn.microsoft.com/en-us/l Library / tw4k6df8 (v = vs.90) .aspx Bên cạnh những khác biệt về tính di động rõ ràng giữa _setmode () và SetConsoleOutputCP (), cũng có thể có những sự tinh tế và tác dụng phụ khác ẩn trong cả hai cách tiếp cận không được hiểu đầy đủ ngay từ cái nhìn đầu tiên. Nếu andrewdotn có thể cập nhật câu trả lời của mình với bất kỳ quan sát nào về _setmode (fd, _O_U16TEXT), điều đó sẽ rất tuyệt.
JasDev

13
Mặc dù đây là một câu trả lời tuyệt vời, nhưng thật sai lầm khi nói rằng bảng điều khiển hỗ trợ UTF-16. Nó bị giới hạn ở UCS-2, tức là giới hạn ở các ký tự trong mặt phẳng đa ngôn ngữ cơ bản (BMP). Khi máy chủ bảng điều khiển Win32 (conhost.exe, ngày nay) được thiết kế vào khoảng năm 1990, Unicode là tiêu chuẩn 16 bit, do đó, bộ đệm màn hình bảng điều khiển sử dụng một WCHAR 16 bit cho mỗi ô ký tự. Một cặp thay thế UTF-16 in thành hai ký tự hộp.
Eryk CN

3
@ user200783, hình thức phân tách không được hỗ trợ; thông thường người ta có thể chuyển đổi thành tương đương NFC. Ngoài ra, bảng điều khiển ở các địa phương phương Tây không cho phép trộn các glyph toàn chiều rộng và nửa chiều rộng. Ngoài ra, khi sử dụng codepage 65001 (UTF-8), trước Windows 8 WriteFilebáo cáo số lượng ký tự được viết thay vì số byte, do đó, các nhà văn được đệm thử lại các byte 'còn lại' nhiều lần so với số ký tự không phải ASCII . Cũng trong năm 65001, việc đọc các ký tự không phải ASCII bị lỗi trong conhost.exe vì nó giả sử 1 byte ANSI cho mỗi mã UTF-16 khi gọi WideCharToMultiByte.
Eryk CN

2
Các chương trình demo đơn giản trong câu trả lời này giả định rằng GetStdHandle(STD_OUTPUT_HANDLE)và C stdoutlà tay cầm điều khiển. Trong thực tế, để kiểm tra một giao diện điều khiển, hãy kiểm tra xem GetConsoleModethành công. Ngoài ra, không sử dụng _isattychức năng thời gian chạy C để kiểm tra xem bộ mô tả tệp I / O thấp có phải là bàn điều khiển không; chỉ kiểm tra một thiết bị chế độ nhân vật, bao gồm NULnhững thiết bị khác. Thay vào đó, hãy gọi _get_osfhandlevà kiểm tra tay cầm trực tiếp.
Eryk CN

29

Kiểu

chcp

để xem trang mã hiện tại của bạn (như Dewfy đã nói).

Sử dụng

nlsinfo

để xem tất cả các trang mã được cài đặt và tìm hiểu ý nghĩa của số trang mã của bạn.

Bạn cần cài đặt bộ tài nguyên Windows Server 2003 (hoạt động trên Windows XP) nlsinfo.


19
Thật thú vị, nlsinfodường như không tồn tại trên Windows 7.
Joey

2
nlsinfocũng không tồn tại trên máy Windows XP SP3 của tôi.
Thomas Owens

2
Oh tôi xin lỗi. Tôi nghĩ rằng nó đi kèm với các công cụ Windows Server Resource Kit. Tôi đã sử dụng nó một vài lần trên máy Windows XP SP3 của tôi trước đó và không biết nó không được cài đặt theo mặc định.
Cagdas Altinkaya

À, điều đó giải thích tại sao nó có trên máy Vista của tôi, nơi tôi đã cài đặt chúng.
Joey

4
nlsinfocũng không tồn tại trên máy Windows 10E.
Yousha Aleayoub

21

Để trả lời lại truy vấn thứ hai của bạn. Làm thế nào mã hóa hoạt động, Joel Spolsky đã viết một bài viết giới thiệu tuyệt vời về điều này . Khuyến khích mạnh mẽ.


13
Tôi đã đọc nó và tôi biết điều đó. Tuy nhiên, trên Windows tôi luôn cảm thấy lạc lõng vì HĐH và hầu hết các ứng dụng dường như hoàn toàn không biết gì về mã hóa.
danglund

5

Lệnh CHCP hiển thị bảng mã hiện tại. Nó có ba chữ số: 8xx và khác với Windows 12xx. Vì vậy, nhập văn bản chỉ bằng tiếng Anh, bạn sẽ không thấy bất kỳ sự khác biệt nào, nhưng một bảng mã mở rộng (như Cyrillic) sẽ được in sai.


5
CHCP không chỉ hiển thị 3 chữ số và cũng không ở định dạng 8 ##. 437 là ví dụ về mã hóa của Hoa Kỳ và đó là tiêu chuẩn defacto trên các hệ thống tiếng Anh. - 65001 là mã hóa Unicode (Nếu tôi nhớ lại thì đó là UTF-8 và 65000 là UTF-7) và có thể được chọn. Ngoài ra, CMD cho phép chuyển sang trang mã 1250 chẳng hạn, nhưng tôi không biết từ khi nào các trang mã này có thể được chọn. (Nó nằm dưới Win7.)
Adam LS

4

Tôi đã thất vọng từ lâu bởi các vấn đề về trang mã Windows và các vấn đề về tính di động và nội địa hóa của chương trình C mà chúng gây ra. Các bài viết trước đã nêu chi tiết các vấn đề theo chiều dài, vì vậy tôi sẽ không thêm bất cứ điều gì về mặt này.

Để làm cho một câu chuyện dài ngắn, cuối cùng tôi đã viết lớp thư viện tương thích UTF-8 của riêng tôi trên thư viện C tiêu chuẩn Visual C ++. Về cơ bản thư viện này đảm bảo rằng một chương trình C tiêu chuẩn hoạt động đúng, trong bất kỳ trang mã nào, sử dụng UTF-8 trong nội bộ.

Thư viện này, được gọi là MsvcLibX, có sẵn dưới dạng mã nguồn mở tại https://github.com/JFLarvoire/SysToolsLib . Những đặc điểm chính:

  • Nguồn C được mã hóa trong UTF-8, sử dụng chuỗi char [] C thông thường và API thư viện C tiêu chuẩn.
  • Trong bất kỳ trang mã nào, mọi thứ đều được xử lý bên trong dưới dạng UTF-8 trong mã của bạn, bao gồm cả đối số chính () argv [], với đầu vào và đầu ra tiêu chuẩn tự động được chuyển đổi sang trang mã bên phải.
  • Tất cả các hàm tệp stdio.h đều hỗ trợ tên đường dẫn UTF-8> 260 ký tự, thực tế lên đến 64 KByte.
  • Các nguồn tương tự có thể biên dịch và liên kết thành công trong Windows bằng thư viện Visual C ++ và MsvcLibX và Visual C ++ C, và trong Linux sử dụng thư viện C tiêu chuẩn gcc và Linux, không cần khối #ifdef ... #endif.
  • Thêm bao gồm các tệp phổ biến trong Linux, nhưng thiếu trong Visual C ++. Vd: unistd.h
  • Thêm các chức năng còn thiếu, như các chức năng cho thư mục I / O, quản lý liên kết tượng trưng, ​​v.v., tất cả đều có hỗ trợ UTF-8 tất nhiên :-).

Thêm chi tiết trong MsvcLibX README trên GitHub , bao gồm cách xây dựng thư viện và sử dụng nó trong các chương trình của riêng bạn.

Phần phát hành trong kho GitHub ở trên cung cấp một số chương trình sử dụng thư viện MsvcLibX này, sẽ hiển thị các khả năng của nó. Ví dụ: Hãy thử công cụ which.exe của tôi với các thư mục có tên không phải ASCII trong PATH, tìm kiếm các chương trình có tên không phải ASCII và thay đổi trang mã.

Một công cụ hữu ích khác là chương trình conv.exe. Chương trình này có thể dễ dàng chuyển đổi một luồng dữ liệu từ bất kỳ trang mã nào sang bất kỳ trang nào khác. Mặc định của nó là đầu vào trong trang mã Windows và đầu ra trong trang mã bảng điều khiển hiện tại. Điều này cho phép xem chính xác dữ liệu được tạo bởi các ứng dụng GUI của Windows (ví dụ: Notepad) trong bảng điều khiển lệnh, với một lệnh đơn giản như:type WINFILE.txt | conv

Thư viện MsvcLibX này hoàn toàn không phải là hoàn thành và những đóng góp để cải thiện nó rất đáng hoan nghênh!


2

Trong Java, tôi đã sử dụng mã hóa "IBM850" để ghi tệp. Điều đó đã giải quyết vấn đề.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.