Unicode gtkmm中是否有一个函数可以从FileInputStream中读取数据,然后使用该函数设置TextArea

Unicode gtkmm中是否有一个函数可以从FileInputStream中读取数据,然后使用该函数设置TextArea,unicode,gtkmm,Unicode,Gtkmm,我正在尝试从文件中读取文本并将其放在文本视图中。有read_bytes,有set_text,可以执行ustring,但似乎没有办法从一个转到另一个 在InputStream的子类中,我发现它确实有read\u line\u utf8提供一个std::string(总比没有好),但即使是DataInputStream也位于与FileInputStream分离的类层次结构分支上 当然,从理论上讲,可以循环读取字节返回的字节数组,并将它们转换为字符,但不知何故,我拒绝相信没有我忽略的现成函数 最终,我

我正在尝试从文件中读取文本并将其放在文本视图中。有
read_bytes
,有
set_text
,可以执行
ustring
,但似乎没有办法从一个转到另一个

在InputStream的子类中,我发现它确实有
read\u line\u utf8
提供一个std::string(总比没有好),但即使是DataInputStream也位于与FileInputStream分离的类层次结构分支上

当然,从理论上讲,可以循环读取字节返回的字节数组,并将它们转换为字符,但不知何故,我拒绝相信没有我忽略的现成函数


最终,我正在寻找一个函数,它将接受
Glib::RefPtr
,并返回一个
Glib::ustring

OK,在广泛搜索之后,我已设法确认在gtkmm库的范围内没有这样做的方法。这对我来说确实很奇怪,但确实如此

下面是如何通过普通工具读取文件,然后转换您读取的内容,并将其显示在文本区域:

我假设您已经打开了对话框,并连接了所有需要连接的内容。如果您有一个控制器类,那么最终将得到以下内容:

fh = dialog->get_file();
fh->read_async( sigc::mem_fun( *this, &Controller::on_file_read_complete ));
确保你有
Glib::RefPtrfh
作为私有数据成员,而不是局部变量。然后,您将需要一个函数
来读取文件\u read\u complete

void Controller::on_file_read_complete(Glib::RefPtr<Gio::AsyncResult>& res)
{
    Glib::RefPtr<Gio::InputStream> fin = fh->read_finish(res);

    Glib::RefPtr<Glib::Bytes> fbytes = fin->read_bytes(8192, Glib::RefPtr<Gio::Cancellable>());
    Glib::ustring str = bytesToUstring(fbytes);

    Gtk::TextView *textview = NULL;

    refGlade->get_widget("textviewUser", textview);
    assert(textview!=NULL);


    textview->get_buffer()->set_text(str);
}
在这里,我们必须首先抓住字节的真正指针,因为
Glib::bytes
将拒绝为您提供所需的工具。然后您可以开始转换为
wchar\t
。这个过程并没有那么困难,在本文中描述得足够好

幸运的是,
wchar\u t
可以转换为
gunichar
,而这反过来又可以添加到
Glib::ustring

因此,我们必须走的道路是:

Dialog->Gio::File->Glib::Bytes->gconstpointer->char->(组合多个字符)wchar\u t->gunichar->Glib::ustring->(添加到TextArea的TextBuffer)

注:目前这不是一个现成的代码,它只读取8192个字节,它不能帮助读更多,因为不能保证字符在两次读取中间没有被破解,也许我稍后会更新代码。
Glib::ustring bytesToUstring(Glib::RefPtr<Glib::Bytes> data)
{
    Glib::ustring result = "";

    gsize s;
    gconstpointer d = g_bytes_get_data(data->gobj(), &s);

    unsigned char c;
    wchar_t wc;
    unsigned short toread = 0;
    for(int i=0; i<(int)s; ++i)
    {
        c = ((char*)d)[i];

        if((c >> 7) == 0b0)
        {
            //std::cout << "Byte 0b0" << std::endl;
            if(toread!=0)
            {
                std::cerr << "Help. I lost my place in the stream" << std::endl;
            }
            wc = (wchar_t)c;
        }
        else if((c >> 6) == 0b10)
        {
            //std::cout << "Byte 0b10" << std::endl;
            if(toread==0)
            {
                std::cerr << "Help. I lost my place in the stream" << std::endl;
            }
            wc <<= 6; // 6 more bits are coming in
            wc |= (c & 0b00111111);
            --toread;
        }
        else // we can be sure that we have something starting with at least 2 set bits
        {
            if(toread!=0)
            {
                std::cerr << "Help. I lost my place in the stream" << std::endl;
            }

            if((c >> 5) == 0b110)
            {
                //std::cout << "Byte 0b110" << std::endl;
                wc = c & 0b00011111;
                toread = 1;
            }
            else if((c >> 4) == 0b1110)
            {
                //std::cout << "Byte 0b1110" << std::endl;
                wc = c & 0b00001111;
                toread = 2;
            }
            else if((c >> 3) == 0b11110)
            {
                //std::cout << "Byte 0b11110" << std::endl;
                wc = c & 0b00000111;
                toread = 3;
            }
            else if((c >> 2) == 0b111110)
            {
                //std::cout << "Byte 0b111110" << std::endl;
                wc = c & 0b00000011;
                toread = 4;
            }
            else if((c >> 1) == 0b1111110)
            {
                //std::cout << "Byte 0b1111110" << std::endl;
                wc = c & 0b00000001;
                toread = 5;
            }
            else // wtf?
            {
                std::cerr << "Help! Something is probaby not a UTF-8 at all" << std::endl;
                for(int j=(8*(int)sizeof c) - 1; j>=0; --j)
                {
                    std::cerr << (char)('0'+ (char)((c >> j) & 1));
                }
                std::cerr << std::endl;
            }

        }

        if(toread == 0)
        {
            result += (gunichar)wc;
            wc = L'\0';
            //std::cout << i << ' ' << result << std::endl;
        }
    }
    return result;
}