C: файл UTF-8, импортированный в программе UTF-8, печатается в терминале UTF-8 "?" символы, обозначающие неизвестные символы - PullRequest
0 голосов
/ 20 февраля 2020

У меня есть C программа test.elf , которая должна обработать UTF-8 закодированный файл и распечатать его внутри терминала в системе UTF-8. Теперь кто-то дал мне файл components.csv , который ISO-8859-1 закодирован. И я столкнулся с проблемами.

Кодировка моей системы может быть проверена в терминале, и это действительно UTF-8:

[ziga@localhost ~]$ echo $LANG
en_US.UTF-8

Я также могу проверить или угадать (!) кодировка файла, которая является одной из ISO-8859-{1,2,3,4,5,6,7,8,9,10,11,13,14,15} ( source ):

[ziga@localhost ~]$ file components.csv 
components.csv: ISO-8859 text, with very long lines, with CRLF line terminators

Если я читаю этот файл напрямую, используя cat и ограничиваю вывод первой парой строк, используя head, я вижу первый неизвестный символ . Это ожидается, поскольку система в UTF-8 может обрабатывать ASCII символов, но не расширена ASCII символов ( source ), где, вероятно, принадлежит:

[ziga@localhost ~]$ cat components.csv | head -n4
id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5�5,5V 400kHz SOIC8",92,0000,92,0000,92,0000,0,0,0,0,50,6000,0,0,0,0,57010274,GSE s.r.l.,0,0,0,NR,0,0

Теперь, если я обработаю этот файл непосредственно с моей программой, программа завершит свое выполнение с точно таким же символом, и это также ожидается:

[ziga@localhost ~]$ ./test.elf components.csv a 
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
1:
    Commencing import procedure of file "components.csv" into SQLite database "a".
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2:
    CSV file "components.csv" found.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
3:
    Printing inputed file "components.csv":

id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5

Но теперь я преобразую кодировку файла и создам новую файл components-utf8.csv в UTF-8 кодировке. Я пробовал эту процедуру несколько раз для каждой кодировки ISO-8859-{1,2,3,4,5,6,7,8,9,10,11,13,14,15}, и приведенное ниже решение дает наилучшие результаты:

iconv -f ISO-8859-1 -t UTF-8 components.csv > components-utf8.csv

Если я обрабатываю новый файл с использованием cat и head, неизвестный символ теперь отображается как ÷:

[ziga@localhost ~]$ cat components-utf8.csv | head -n4
id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5÷5,5V 400kHz SOIC8",92,0000,92,0000,92,0000,0,0,0,0,50,6000,0,0,0,0,57010274,GSE s.r.l.,0,0,0,NR,0,0

Если я обрабатываю новый файл с моей программой, он запускается с начала до конца (здесь я просто вставлю первые пару строк) , но рендер ÷ как ?:

[ziga@localhost ~]$ ./test.elf components-utf8.csv a 
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
1:
    Commencing import procedure of file "components-utf8.csv" into SQLite database "a".
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2:
    CSV file "components-utf8.csv" found.
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
3:
    Printing inputed file "components-utf8.csv":

id_articolo,codice,descrizione,esistenza,disponibilita,qta_rim_iniziale,qta_caricata,qta_scaricata,qta_ord_clienti,qta_ord_fornitori,val_rim_iniziale,val_caricato,val_scaricato,ultimo_costo,c_scorta_min,c_cod_fornitore,c_des_fornitore,c_prd_qta_avanz,c_prd_qta_wip,prezzo_listino,codice,qta_altri_carichi,qta_altri_scarichi
41,15MQ040N,Diodo schottky 3A 40V SMA,6755,0000,6755,0000,6755,0000,0,0,0,0,0,0,0,0,0,,,0,0,0,NR,0,0
49,24LC256-I/SN,Memoria flash 8 pin SOIC-8 256kbit,22,0000,22,0000,22,0000,0,0,0,0,16,0600,0,0,0,0,57010035,EBV Elektronik,0,0,0,NR,0,0
2156,24LC512-I/SN,"Memoria EEPROM I2C 64kx8bit 2,5?5,5V 400kHz SOIC8",92,0000,92,0000,92,0000,0,0,0,0,50,6000,0,0,0,0,57010274,GSE s.r.l.,0,0,0,NR,0,0

Это для меня загадка. Особенно потому, что моя программа устанавливает внутреннюю кодировку для имитации кодирования системы, и я также использую широкие функции печати. Вот исходный код программы:

// Headers:
#include <locale.h>
#include <wchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// Function prototypes:
void ruler(void);

// Function definitions:
void ruler(void){
    char* r1 = getenv("COLUMNS");
    int r2;
    if(r1 == NULL){
        r2 = 100;
    }
    else{
        r2 = strtol(r1, NULL, 10);
    }
    int i;
    for(i = 0; i < r2; i++){
        putwchar(L'―');
    }
    putwchar(L'\n');
}

// Entry point:
int main(int argc, char** argv){

    // Setting the user-perfered locale.
    setlocale(LC_ALL, "en_US.UTF-8");

    ruler();

    // Check if exactly two arguments are passed to the binary
    if(argc != 3){
        wprintf(L"USAGE:\n\t%s <CSV file in UTF-8 encoding> <database>\n\nHINT:\n\tUse terminal application \"file\" to guess CSV file's encoding and \"iconv\" to transcode it to UTF-8\n", argv[0]);
        ruler();
        return 1;
    }
    else{
        wprintf(L"1:\n\tCommencing import procedure of file \"%s\" into SQLite database \"%s\".\n", argv[1], argv[2]);
        ruler();
    }

    // Open CSV file
    FILE* csv_file = fopen(argv[1], "r");
    if(csv_file == NULL){
        wprintf(L"2:\n\tCSV file \"%s\" not found.\n", argv[1]);
        ruler();
        return 1;
    }
    else{
        wprintf(L"2:\n\tCSV file \"%s\" found.\n", argv[1]);
        ruler();
    }

    // Print CSV file
    wprintf(L"3:\n\tPrinting inputed file \"%s\":\n\n", argv[1]);
    char c = fgetwc(csv_file);
    while(c != WEOF){
        putwchar(c);
        c = fgetwc(csv_file);
    }
    putwchar(L'\n');

    return 0;

}

1 Ответ

1 голос
/ 20 февраля 2020

Вам необходимо использовать правильный тип для представления широких символов - для этого недостаточно char.

char c = fgetwc(csv_file);

должно быть:

wint_t c = fgetwc(csv_file);

согласно fgetwc ссылка.

Для других целей (ie. Когда не требуется возвращаемое значение), есть wchar_t для представления широких символов.

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