我正在尝试从文件中读取文本并将其放在TextView中。FileInputStream具有read_bytes
,可以set_text
在TextBuffer中使用ustring
,但是似乎没有办法从一个过渡到另一个。
在InputStream的子类中,我发现DataInputStream确实read_line_utf8
提供了一个std :: string(总比没有好),但即使DataInputStream也位于FileInputStream的单独的类层次结构分支上。
当然,从理论上讲,可以循环遍历返回的字节数组read_bytes
并将其转换为字符,但是以某种方式,我只是拒绝相信我没有忽略的现成函数。
最终,我正在寻找一个可以接受Glib::RefPtr<Glib::Bytes>
并返回给我的函数Glib::ustring
好吧,在四处搜寻之后,我设法确认在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
。该过程并不那么困难,并且在有关UTF-8的Wikipedia文章中对此进行了很好的描述。
幸运的是,wchar_t
可以将转换为gunichar
,然后可以将其添加到Glib::ustring
。
因此,我们必须走的路是:
对话框-> Gio :: File-> Glib :: Bytes-> gconstpointer-> char->(组合多个字符)wchar_t-> gunichar-> Glib :: ustring->(添加到TextArea的TextBuffer中)
:注意:目前这不是一个立即可用的代码,它只能读取8192字节,因此无法读取更多内容,因为不能保证在两次读取之间字符不会被破坏,也许我稍后再更新代码。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句