Открытие файла Unicode в чистом C

Я пытаюсь открыть файл .txt, полностью китайский. Могу ли я использовать для него обычные процедуры fopen/fclose, даже если поток будет на 100% Unicode, или есть ли какие-либо эксклюзивные инструменты для обработки широких символов? Буду признателен за точные ответы, я начинающий программист. Я использую Linux со стандартным gcc.

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

#include<stdio.h>
#include<stdlib.h>
#include<wchar.h>
#include <locale.h>
#define PLIK_IN in /*filenames*/
#define PLIK_OUT out
#define LKON 49 /*specifying the length of a string on the left from a desired sign*/
#define PKON 50 /*...and on the right*/
int wczytaj_pliki(FILE*, FILE*); /*open file*/
void krocz_po_pliku(FILE*, FILE*); /*search through file*/
int slownik(wchar_t); /*compare signs*/
void zapisz_pliki(FILE*, FILE*); /*write to file*/

void main(void)
{
    FILE *bin,*bout;
    setlocale(LC_CTYPE, "");

    wczytaj_pliki(bin, bout);
    krocz_po_pliku(bin, bout);
    zapisz_pliki(bin, bout);
}/*main*/

int slownik(wchar_t znak) /*compare characters*/
{
    wchar_t gznak1 = L'股', gznak2 = L'利', gznak3 = L'红';
    if ( ( znak == gznak1) || (znak == gznak2) || (znak == gznak3) ) return 1;
    return 0;
}/*slownik*/

void krocz_po_pliku(FILE* bin, FILE* bout) /*search through file*/
{
    wchar_t wch;
    wchar_t* kontekst;
    int i = 0, j, step = LKON, counter = 0, token = 0;

    while ( (wch = getwchar() ) != EOF )
    {
        if (!token) /*comparing consecutive signs*/
    {
        if ( slownik(wch) == 1 )
        {
            counter++;
            fprintf(bout,"###Wystapienie %d.\n\n", counter);
            if ( i<step ) step = i;
            fseek(bin,-step,1);
            j=0, token = 1;
        }/*if*/
        else i++;
    }/*if*/
    else /*writing consecutive signs within context*/
    {
        if ( j < LKON + PKON)
        {
            putwc(wch, bout);
            j++;
        }/*if*/
        else
        {
            fprintf(bout,"###\n\n");
            fflush(bout);
            token = 0;
        }/*else*/
    }/*else*/
    }/*while*/
        printf("Znalazlem %d wystapien\n", counter);
}/*krocz_po_pliku*/

int wczytaj_pliki(FILE* bin, FILE* bout)
{
    bin=fopen("PLIK_IN","r");
    bout=fopen("PLIK_OUT","w");
    rewind(bin);
    if(bin==NULL || bout==NULL)
{
    printf("Blad plikow\n");
    exit(0);
}/*if*/
    return 1;
}/*wczytaj pliki*/

void zapisz_pliki(FILE* bin, FILE* bout)
{
fclose(bin);
fclose(bout);
}

person yauser    schedule 29.11.2011    source источник
comment
Впервые я увидел комбинацию литералов китайских иероглифов и польских (?) имен переменных.   -  person dan04    schedule 30.11.2011
comment
100% Юникод? Не из концентрата? Как будет выглядеть файл, содержащий только 85% Unicode?   -  person Kerrek SB    schedule 07.12.2011


Ответы (2)


Ваша проблема может быть вызвана тем, что вы

#define PLIK_IN in /*filenames*/

а потом

bin=fopen("PLIK_IN","r");

Ваша программа пытается открыть файл с именем PLIK_IN, а не файл с именем in. Если PLIK_IN не существует, fopen возвращает 0. Передача 0 в rewind приводит к тому, что ваш исполняемый файл умирает.

Если вы хотите открыть in, вам следует

#define PLIK_IN "in" /*filenames*/
/* ... */
bin=fopen(PLIK_IN,"r");

То же самое касается PLIK_OUT.

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

person Jan    schedule 29.11.2011

Да, fopen может открыть файл, содержащий любые данные, включая данные Unicode, если вы можете представить имя файла в виде char*. (На некоторых платформах, а именно в Windows, файлы могут иметь имена, которые не могут быть представлены в виде char*).

Вы захотите открыть файл в двоичном режиме, чтобы предотвратить любую новую замену строки, которая может быть выполнена (если только кодировка Unicode не является UTF-8, и тогда это не имеет значения), потому что замена будет выполняться с точки зрения символов. Кроме того, если единицы кода составляют более одного байта, вам необходимо убедиться, что вы читаете их с правильным порядком байтов.

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

person bames53    schedule 29.11.2011
comment
Вы можете fopen файл с именем, отличным от ANSI, в Windows, используя его короткое имя. - person dan04; 30.11.2011
comment
Короткие имена не всегда доступны, и в будущем Windows перейдет на новую файловую систему (ReFS), которая их вообще не будет поддерживать. - person bames53; 19.10.2012