LINUX.ORG.RU

Помогите разобраться с libiconv

 ,


0

1

Скачал с http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz libiconv-1.14. Собрал с помощью mingw эту библиотеку под windows. Шедшая с ней в качестве примера iconv_no_i18n , нормально работает и все конвертит. Пишу свой код:

#include "testiconv.h"

void readdata(char** buf, size_t len){
FILE *pFile = fopen ("in.txt","r");
if (pFile!=NULL)
  {
    printf("readf file in.txt \n\n") ;
    fread(*buf, 1, len, pFile);
    fclose(pFile);
  }
}


void writedata(char* buf, size_t len){
FILE *pFile = fopen ("out.txt","w");
if (pFile!=NULL)
  {
    printf("write file out.txt \n\n") ;
    fwrite(buf, 1, len, pFile);
    fclose(pFile);
  }

}

int main(int argc, char* argv[])
{
    char input[BUFSIZ]; 
    char output[BUFSIZ]; 
    FILE * pFile;
    size_t insize = BUFSIZ; 
    size_t outsize = BUFSIZ; 
    char *outp = (char *)output;
    char *inp = (char *)input; 
    iconv_t cd = iconv_open((const char* )"CP1251",(const char *) "UTF-8"); 
    readdata(&inp,256) ;
    insize = 256; 
    printf("1: in-str=%s \n len=%d \n ===================== \n", input,insize); 
    iconv(cd, NULL, NULL, NULL, NULL); 
    iconv(cd, &inp, &insize, &outp, &outsize);
    iconv_close(cd); 	
    printf("2: out-str=%s \n len=%d \n ===================== \n", output,outsize);  
    writedata(output,outsize) ;
    return 0;
}
Программа по задумке должна брать 256 символов из файла in.txt в кодировке CP1251 и перекодировать в UTF-8, а затем сохранять в out.txt . Когда в файле in.txt текст латиницей это работает, как только текст с кириллицей то файл out.txt заполняется одними \x00 . Скомпилировал этот же код под linux( под федору-16 (3.3.1-5.fc16.x86_64) ) . Тот же самый результат. Что я не так делаю?

Кодировка in.txt точно CP1251? Как файл создавали? Если в «блокноте» каком-нить, то в линуксе скорее всего UTF-8, а в винде UTF-16.

kulti ★★ ()

Собрал с помощью mingw эту библиотеку под windows.

А зачем? Есть же порт. http://sourceforge.net/projects/mingw/files/MinGW/Base/libiconv/libiconv-1.14-2/

Теперь по сабжу.

1.

iconv_t cd = iconv_open((const char* )«CP1251»,(const char *) «UTF-8»);

в кодировке CP1251 и перекодировать в UTF-8

Неплохо бы документацию читать

2.

iconv_t cd = iconv_open((const char* )«CP1251»,(const char *) «UTF-8»);
iconv(cd, NULL, NULL, NULL, NULL);
iconv(cd, &inp, &insize, &outp, &outsize);

И на ошибки проверять то, что iconv возвращает.

В частности, insize не просто так передаётся указателем. В нём iconv возвращает количество символов, оставшихся не сконвертированными. Если после конвертации там нечто большее нуля, то есть некоторая (небольшая) вероятность, что произошла ошибка.

anonymous ()
Ответ на: комментарий от anonymous

1

На всякий случай более толстый намёк, прототип iconv_open:

iconv_t iconv_open(const char *tocode, const char *fromcode);

anonymous ()
Ответ на: комментарий от anonymous

Спасибо Анонимус! Вы очень помогли. Теперь все работает как должно. Документацию, читал, iconv.h тоже внимательно изучил. Строчку эту(с объявлением iconv_open) видел много раз, но в голове была какая-то установка заложена, что первым надо передавать «откуда» и вторым «куда». Странно это. Даже не предполагал и не думал на это.

Zero010 ()
Ответ на: комментарий от Zero010

первым надо передавать «откуда» и вторым «куда»

Так а memcpy, strcpy?

Ну проверкой возвращаемых значений (iconv в частности) пренебрегать никогда не стОит.

anonymous ()
Ответ на: комментарий от anonymous

Так а memcpy, strcpy?

C memcpy, strcpy у меня сейчас почему-то таких проблем нет. Хотя давно, очень давно, со strcpy была похожая заморочка. Кроме, этого я когда-то немного изучал аsm в intel`овском стандартном варианте и когда вижу, что-то вроде mov edx,eax , то я понимаю, что это означает поместить содержимое регистра eax в edx(хотя когда писал это первый раз написал наоборот, затем стер(через секунды две где-то) и написал правильно, хотя понимаю, что значит эта запись) . Но в случае с iconv_open (и правда было до этого со strcpy) ловил конкретного глюка. Я не знаю почему так, это связано с моей психологией, возможно какие-то сексуальные переживания в глубоком детстве, которых я не помню, я сам не психоаналитик, а на профессионального психоаналитика нету денег.

Ну проверкой возвращаемых значений (iconv в частности) пренебрегать никогда не стОит.

. В любом случае спасибо за совет. Тут у меня двоякое отношение Я разумеется слышал, что возвращаемые значения надо проверять и если произошла ошибка, то это надо как-то обрабатывать. Понятно, что это имеет смысл когда надо прервать программу, чтобы она не нанесла ущерба или когда невозможно дальнейшее выполнение программы, например с открытием файла, если не получилось открыть файл , то пытаться что-то из него считывать не стоит, а в моем случае желательно чтобы функции writedata, readdata возвращали значение сигнализирующее о том, что данные не были считаны из файла и дальше что-то конвертить не имеет смысла, нужно написать об этом и выходить.(но я писал этот код изначально с целью быстрой проверки работоспособности собранной библиотеки, поэтому поленился так делать). Однако считаю, что просто проверять ради проверки, чтобы потом сообщить пользователю, что «произошла такая-то» ошибка, которая ничего пользователю не скажет, а результат выполнения программы все-равно останется одним и тем я смысла я не вижу. В данном случае в случае ошибки при вызове iconv, все равно надо закрыть iconv, все равно нужно записать полученные данные( хотя-бы ради интереса) и результат выполнения программы все-равно будет одним и тем же. Какой смысл в данном случае в такой проверке?

Zero010 ()

Если задача исключительно по конвертации cpXXX -> юникод, то iconv можно пользоваться.

А вот если нужно с юникодом работать или конвертировать юникод -> cpXXX, то тогда лучше использовать ICU, хоть и помойка.

Macil ★★★★★ ()
Ответ на: комментарий от Zero010

все равно нужно записать полученные данные( хотя-бы ради интереса) и результат выполнения программы все-равно будет одним и тем же. Какой смысл в данном случае в такой проверке?

В данном конкретном случае смысла нет записывать буфер как раз. Потому что iconv остановился и ничего в тот кусок не записал, там что было до iconv, то там и осталось. О результате работы iconv оно не скажет ничего.

anonymous ()
Ответ на: комментарий от anonymous

В данном конкретном случае смысла нет записывать буфер как раз. Потому что iconv остановился и ничего в тот кусок не записал, там что было до iconv, то там и осталось.

Нет. В случае латинсткого текста будет записан он же(текст из первого файла) в случае кириллицы ничего не будет. Скажет/не скажет - в зависимости от сообразительности.

Zero010 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.