是否有一个gtkmm函数以FileInputStream方式读取,然后可以用来设置TextArea

时间:2014-11-09 00:09:36

标签: unicode gtkmm

我试图从文件中读取文本并将其放入TextView中。 FileInputStreamread_bytesTextBuffer中有set_text可以ustring,但似乎没有办法从一个到另一个。

在InputStream的子类中,我发现DataInputStream确实read_line_utf8给了一个std :: string(总比没有好),但是甚至DataInputStream也在单独的类层次结构分支上来自FileInputStream。

当然,理论上可以循环遍历read_bytes返回的字节数组并将它们转换为字符,但不知怎的,我只是拒绝相信没有现成的函数,我可以使用它。俯视。

最终,我正在寻找能够Glib::RefPtr<Glib::Bytes>并返回Glib::ustring

的功能

1 个答案:

答案 0 :(得分:1)

好的,经过广泛的搜索,我已经设法确认在gtkmm库的范围内没有办法这样做。这对我来说似乎很奇怪,但确实如此。

以下是如何通过常规工具读取文件,然后转换您已阅读的内容,并将其显示在TextArea中:

我在这里假设您已经打开了对话框并连接了所有需要连接的对话框。如果你有一个Controller类,你最终会得到以下内容:

fh = dialog->get_file();
fh->read_async( sigc::mem_fun( *this, &Controller::on_file_read_complete ));

确保您拥有Glib::RefPtr< Gio::File > fh;作为私有数据成员而不是本地变量。然后,您将需要一个函数on_file_read_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);
}

此功能在读取文件时触发,您可以安全地与FileInputStream通话。使用该类read_bytes的父级函数,这里我要求读取8192个字节,但它可能更多,必须提供Cancellable引用,但可以为空,如上所述。现在是棘手的部分,抓住Glib::RefPtr<Glib::Bytes>并使用必须为此编写的函数进行转换:

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;
}

在这里我们必须首先抓住真正的字节指针,因为Glib::Bytes将拒绝为您提供所需的工具。然后您就可以开始转换为wchar_t。这个过程并不困难,并在Wikipedia article on UTF-8中得到了充分的描述。

幸运的是,wchar_t可以转换为gunichar,然后又可以添加到Glib::ustring

所以我们必须走的路是:

对话 - &gt; Gio ::文件 - &gt; Glib :: Bytes - &gt; gconstpointer - &gt; char - &gt; (结合几个字符)wchar_t - &gt; gunichar - &gt; Glib :: ustring - &gt; (添加到TextArea&#39; TextBuffer)

:注意:目前这不是一个可以使用的代码,它只读取8192个字节,并且它不会有帮助然后阅读更多,因为无法保证该字符不会被破坏在两次读取的中间,也许我稍后会更新代码。