首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C: UTF-8程序打印UTF-8终端中导入的UTF-8文件“?表示未知符号的字符

C: UTF-8程序打印UTF-8终端中导入的UTF-8文件“?表示未知符号的字符
EN

Stack Overflow用户
提问于 2020-02-20 07:44:55
回答 1查看 130关注 0票数 0

我有一个C程序test.elf,它应该处理UTF-8编码的文件,并在UTF-8系统的终端中打印它。现在有人给了我一个文件components.csv,它是ISO-8859-1编码的。我遇到了一些问题。

我的系统的编码可以在终端中签入,它确实是UTF-8

代码语言:javascript
复制
[ziga@localhost ~]$ echo $LANG
en_US.UTF-8

我还可以检查或猜测(!)文件的编码,这是ISO-8859-{1,2,3,4,5,6,7,8,9,10,11,13,14,15} (来源)之一:

代码语言:javascript
复制
[ziga@localhost ~]$ file components.csv 
components.csv: ISO-8859 text, with very long lines, with CRLF line terminators

如果我直接使用cat读取这个文件,并将输出限制在使用head的前几行,我将看到第一个未知字符。这是预期的,因为系统在UTF-8中可以处理ASCII字符,但不能处理扩展ASCII字符(来源),而可能属于:

代码语言:javascript
复制
[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

现在,如果我用我的程序直接处理这个文件,程序将以这个精确的字符结束它的执行,这也是预期的:

代码语言:javascript
复制
[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

但是现在,我将转换文件的编码,并以UTF-8编码创建一个新的文件UTF-8。对于每个ISO-8859-{1,2,3,4,5,6,7,8,9,10,11,13,14,15}编码,我多次尝试了这个过程,下面的解决方案得到了最好的结果:

代码语言:javascript
复制
iconv -f ISO-8859-1 -t UTF-8 components.csv > components-utf8.csv

如果我使用cathead处理新文件,未知字符现在呈现为÷

代码语言:javascript
复制
[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

如果我用我的程序处理新文件,它从一开始一直执行到结束(这里我只粘贴前几行),但将÷呈现为?

代码语言:javascript
复制
[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

这对我来说是个误会。特别是因为我的程序将内部编码设置为发送系统的编码,而且我还使用了广泛的打印功能。以下是该程序的源代码:

代码语言:javascript
复制
// 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;

}
EN

回答 1

Stack Overflow用户

发布于 2020-02-20 07:58:41

您需要使用正确的类型来表示宽字符-- char是不够的。

代码语言:javascript
复制
char c = fgetwc(csv_file);

应:

代码语言:javascript
复制
wint_t c = fgetwc(csv_file);

根据fgetwc引用。

用于其他用途(如当不处理返回值时,有wchar_t来表示宽字符。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60315068

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档