Проблемы с китайским иероглифом при использовании fopen / write - PullRequest
0 голосов
/ 26 сентября 2019

Мне нужно записать информацию о конфигурации в файл в Linux, в то время как информация о конфигурации содержит китайские символы.

Вместо использования wchar_t, я просто использую массив символов, это правильно?

Вот мой код:

код в paster.ubuntu

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#define MSG_LEN 4096

int save_config_info(const char *path, char* message)
{
    FILE *fp = NULL;

    fp = fopen(path, "wb");
    if (!fp)
    {
            //print error message
        return -1;
    }

    if (fwrite(message, 1, strlen(message), fp) != strlen(message)) 
        {
        //print error message
        fclose(fp);
        return -1;
    }

    fclose(fp);
    return 0;
}

int main()
{
    //config contain chinese character
    char str[MSG_LEN] = "配置文件中包含中文";
    char path[PATH_MAX] = "example.txt";
    save_config_info(path,str);

    return 0;
}

Если кодировкой исходного кода является ISO-8859-1, сгенерируйте файл example.txtи используя cat, чтобы показать с некоторыми ????.

Но измените кодировку исходного кода с utf-8, все работает хорошо.

Мой вопрос:

Есть какой-то элегантный способ справиться с китайским символом, так как я не могу обеспечить кодировку исходного файла.

Я хочу, чтобы example.txt всегда выглядел правильно.

[root workspace]#file fork.c
fork.c: C source, ASCII text
[root workspace]#gcc -g -o fork fork.c
[root workspace]#
[root workspace]#./fork
[root workspace]#
[root workspace]#
[root workspace]#file example.txt
example.txt: ASCII text, with no line terminators
[root workspace]#
[root workspace]#cat example.txt
?????????[root workspace]#
[root workspace]#
[root workspace]#
[root workspace]#file fork.c
fork.c: C source, UTF-8 Unicode text
[root workspace]#
[root workspace]#gcc -g -o fork fork.c
[root workspace]#./fork
[root workspace]#
[root workspace]#file example.txt
example.txt: UTF-8 Unicode text, with no line terminators
[root workspace]#cat example.txt
配置文件中包含中文[root workspace]#

Ответы [ 3 ]

1 голос
/ 26 сентября 2019

Существует ли элегантный способ представления символов, не найденных в ASCII, с использованием только символов ASCII?Нет.

Но это можно сделать не элегантным способом.

char str[MSG_LEN] = "\xE9\x85\x8D\xE7\xBD\xAE\xE6\x96\x87\xE4\xBB\xB6\xE4\xB8\xAD\xE5\x8C\x85\xE5\x90\xAB\xE4\xB8\xAD\xE6\x96\x87";

Конечно, как и в вашей исходной программе, это предполагает, что человек просматривает имена файлов (например, с помощью ls) имеет локаль, основанную на UTF-8.

0 голосов
/ 26 сентября 2019

Чтобы получить строку UTF-8 надежно, независимо от кодировки, используйте

char str[] = u8"\u914D\u7F6E\u6587\u4EF6\u4E2D\u5305\u542B\u4E2D\u6587";

char также может быть char8_t

Таким образом, вам не нужно находить закодированныйUTF-8 байтов, а когда вам нужна другая кодировка, такая как UTF-16 или UTF-32, просто измените тип и префикс (u8 на u или U)

0 голосов
/ 26 сентября 2019

Вместо использования wchar_t, я просто использую массив символов. Это правильно?

Я бы сказал нет.Набор символов и кодировка по умолчанию для char определяется реализацией (это может быть EBCDIC или ASCII или UTF-8 или независимо от того, какой исходный файл использовался или что-то еще), а набор символов и кодировка по умолчанию для wchar_t также определяется реализацией(может быть UTF-16LE или ...).

Если вам нужен вывод UTF-8;тогда (особенно для переносимого кода) вам нужно игнорировать случайные бессмысленные глупости, которые чувствовал компилятор Си.Вам также следует избегать использования char, потому что подписано или не подписано, определяется реализацией, избегайте использования unsigned char, потому что нет реальной гарантии, что это 8 бит, и избегайте использования wchar_t (поскольку его размер определяется реализацией)

В частности (для UTF-8) я бы использовал uint8_t, например:

uint8_t str[] = 0xE9, 0x85, 0x8D, 0xE7, 0xBD, 0xAE, 0xE6, 0x96, 0x87, 0xE4, 0xBB, 0xB6,
                0xE4, 0xB8, 0xAD, 0xE5, 0x8C, 0x85, 0xE5, 0x90, 0xAB, 0xE4, 0xB8, 0xAD,
                0xE6, 0x96, 0x87, 0x00;

Конечно, если вы хотите, чтобы файл содержал CNS-11643 (или что-то еще), вы могли бы сделатьэто тоже.Вам просто нужно найти подходящий тип и найти «массив чисел этого типа» (например, возможно, с помощью утилиты, такой как hexdump, в текстовом файле, который использует нужный набор символов и кодировку).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...