использование libiconv в *nix
Пишу простой код:
#include <stdio.h>
#include <iconv.h>
#include <errno.h>
int main() {
char outbuf[512];
char *inbuf=strdup("SDFуваASDF");
size_t inbytesleft, outbytesleft;
char *inptr = inbuf;
char *outptr = outbuf;
inbytesleft = strlen(inbuf);
outbytesleft = sizeof(outbuf) - 1;
iconv_t iconv_desc = iconv_open ("KOI8-U", "UTF-8");
printf("inbuf='%s' inbytesleft=%i outbytesleft=%i\n", inbuf, inbytesleft, outbytesleft);
if (iconv(iconv_desc, (const char **) &inptr, &inbytesleft, &outptr, &outbytesleft) == (size_t)(-1)) {
printf("errno= %i\n", errno);
};
*outptr = 0;
printf("converted='%s' inbytesleft=%i outbytesleft=%i\n", outbuf, inbytesleft, outbytesleft);
free(inbuf);
iconv_close(iconv_desc);
return errno;
}
Выдает:
inbuf='SDFываASDF' inbytesleft=10 outbytesleft=511
errno= 86
converted='SDF' inbytesleft=7 outbytesleft=508
86 — это EILSEQ An invalid multibyte sequence has been encountered in the input.
что ему может не нравится?
строка с англ символами конвертится нормально.
Спасибо!
Re: использование libiconv в *nix
Забыл добавить.
проверялось на gnu libiconv-1.9.2 на FreeBSD 6.1.
и на встроенной в libc iconv на Debian Sarge.
Re: использование libiconv в *nix
От:
zaufi
Дата: 04.09.06 09:23
Оценка:
Здравствуйте, Палий Олег, Вы писали:
ПО>Пишу простой код:
ПО>#include <stdio.h>
ПО>#include <iconv.h>
ПО>#include <errno.h>
#include <locale.h>
ПО>int main() {
if (setlocale(LC_ALL, "") == 0) return -1; // Return if unable to set locale
ПО> char outbuf[512];
ПО> char *inbuf=strdup("SDFуваASDF");
ПО> size_t inbytesleft, outbytesleft;
ПО> char *inptr = inbuf;
ПО> char *outptr = outbuf;
ПО> inbytesleft = strlen(inbuf);
ПО> outbytesleft = sizeof(outbuf) - 1;
ПО> iconv_t iconv_desc = iconv_open ("KOI8-U", "UTF-8");
ПО> printf("inbuf='%s' inbytesleft=%i outbytesleft=%i\n", inbuf, inbytesleft, outbytesleft);
ПО> if (iconv(iconv_desc, (const char **) &inptr, &inbytesleft, &outptr, &outbytesleft) == (size_t)(-1)) {
ПО> printf("errno= %i\n", errno);
ПО> };
ПО> *outptr = 0;
ПО> printf("converted='%s' inbytesleft=%i outbytesleft=%i\n", outbuf, inbytesleft, outbytesleft);
ПО> free(inbuf);
ПО> iconv_close(iconv_desc);
ПО> return errno;
ПО>}
попробуй выставить локаль сначала
Re[2]: использование libiconv в *nix
Здравствуйте, zaufi, Вы писали:
Z> if (setlocale(LC_ALL, "") == 0) return -1; // Return if unable to set locale
Z>попробуй выставить локаль сначала
не помогает,
на консоли стоит
$ locale
LANG=uk_UA.KOI8-U
LC_CTYPE="uk_UA.KOI8-U"
LC_COLLATE="uk_UA.KOI8-U"
LC_TIME="uk_UA.KOI8-U"
LC_NUMERIC="uk_UA.KOI8-U"
LC_MONETARY="uk_UA.KOI8-U"
LC_MESSAGES="uk_UA.KOI8-U"
LC_ALL=
Re: использование libiconv в *nix
От:
zaufi
Дата: 04.09.06 11:27
Оценка:
Вот набросал примерчег:
# include <iconv.h>
# include <cassert>
# include <cerrno>
# include <string>
# include <stdexcept>
# include <iostream>
class charset_converter
{
iconv_t m_cd;
public :
charset_converter(const std::string& from, const std::string& to)
: m_cd(iconv_open(to.c_str(), from.c_str()))
{
if (m_cd == reinterpret_cast <iconv_t>(-1))
throw std::runtime_error("iconv init failure" );
}
~charset_converter()
{
int r = iconv_close(m_cd);
assert(r != -1);
}
std::string convert(const std::string&);
};
class convert
{
std::string m_str;
std::string m_from;
std::string m_to;
public :
convert(const std::string& str) : m_str(str) {}
convert& from(const std::string& from_enc)
{
m_from = from_enc;
return *this ;
}
convert& to(const std::string& to_enc)
{
m_to = to_enc;
return *this ;
}
operator std::string() const
{
if (m_from.empty() || m_to.empty())
throw std::runtime_error("Bad use of conversion helper class" );
return charset_converter(m_from, m_to).convert(m_str);
}
};
std::string charset_converter::convert(const std::string& str)
{
using namespace std;
const size_t MAX_BUFFER_SIZE = 4096;
/// \warning iconv wants to have `char**` to input buffer -- WHY? Is it can be modified?
char * in_buffer = const_cast <char *>(str.data());
size_t in_bytes_left = str.size();
string result;
size_t out_bytes_left;
char out_buffer[MAX_BUFFER_SIZE];
char * out_buffer_ptr;
for (bool exit = false ; !exit && in_bytes_left; )
{
out_buffer_ptr = out_buffer;
out_bytes_left = MAX_BUFFER_SIZE;
size_t sz = iconv(m_cd, &in_buffer, &in_bytes_left, &out_buffer_ptr, &out_bytes_left);
if (static_cast <int >(sz) == -1)
{
switch (errno)
{
case E2BIG:
result += string(out_buffer, MAX_BUFFER_SIZE - out_bytes_left);
break ;
case EILSEQ:
throw runtime_error("invalid byte sequence" );
case EINVAL:
throw runtime_error("incomplete byte sequence" );
case EBADF:
default :
throw runtime_error("Bad use" );
}
}
}
size_t sz = iconv(m_cd, 0, 0, &out_buffer_ptr, &out_bytes_left);
assert(sz >= 0 && "No errors possible here!" );
result += string(out_buffer, MAX_BUFFER_SIZE - out_bytes_left);
//reset convert descriptor
iconv(m_cd, 0, 0, 0, 0);
return result;
}
int main(int argc, char * argv[])
{
if (setlocale(LC_ALL, "" ) == 0)
{
std::cerr << "Unable to setup default locale.\n" ;
return -1;
}
if (argc >= 2)
{
for (int i = 1; i < argc; ++i)
{
std::string result_1251 = convert(argv[i]).from("UTF-8" ).to("CP1251" );
std::cout << "arg[" << i << "] = \"" << result_1251 << "\"\n" ;
}
}
return 0;
}
у меня вроде нормально работает:
zaufi tests # ./iconv_test "Превед" | hexdump
0000000 7261 5b67 5d31 3d20 2220 f0cf e2e5 e4e5
0000010 0a22
0000012
zaufi tests # locale
LANG=en_US.UTF-8
LC_CTYPE=ru_RU.UTF-8
LC_NUMERIC=POSIX
LC_TIME=en_US.UTF-8
LC_COLLATE=ru_RU.UTF-8
LC_MONETARY=ru_RU.UTF-8
LC_MESSAGES=en_US.UTF-8
LC_PAPER=ru_RU.UTF-8
LC_NAME=ru_RU.UTF-8
LC_ADDRESS=ru_RU.UTF-8
LC_TELEPHONE=ru_RU.UTF-8
LC_MEASUREMENT=ru_RU.UTF-8
LC_IDENTIFICATION=ru_RU.UTF-8
LC_ALL=
Re[2]: использование libiconv в *nix
Здравствуйте, zaufi, Вы писали:
Z>Вот набросал примерчег:
:-O Вы меня просто ошеломили
.
Все оказалось проще — я перепутал откуда и куда в вызове iconv_open
Но, все равно спасибо, пока я разобрался с Вашим примером я понял в чем ошибка.
Re[2]: использование libiconv в *nix
От:
Аноним
Дата: 15.02.08 07:51
Оценка:
Здравствуйте, zaufi, Вы писали:
char * in_buffer = const_cast <char *>(str.data());
// ...
size_t sz = iconv(m_cd, &in_buffer, &in_bytes_left, &out_buffer_ptr, &out_bytes_left);
error C2664: 'libiconv' : cannot convert parameter 2 from 'char **__w64 ' to 'const char ** '
что бы это значило? не догоню, чесслово
Re[3]: использование libiconv в *nix
От:
Аноним
Дата: 15.02.08 14:56
Оценка:
Все заработало, когда const поставил
const char * in_buffer = const_cast <char *>(str.data());
теперь возник другой вопрос, может и глупый, но не пойму: где можно посмотреть формат записи строковых констант, которые передаются как параметры перекодирования (типа "CP1251").
спасибо.
Re[2]: использование libiconv в *nix
Здравствуйте, zaufi, Вы писали:
Z>Вот набросал примерчег:
Z>zaufi tests # ./iconv_test "Превед" | hexdump
Но-но!
До последнего не верил в пирамиду Лебедева.
От:
Кодт
Дата: 19.02.08 22:32
Оценка:
Здравствуйте, zaufi, Вы писали:
Z>Вот набросал примерчег:
Z>zaufi tests # ./iconv_test "Превед" | hexdump
Падонческая лексика противоречит правилам форума.
Перекуём баги на фичи!
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить