我试图从文件中读取文本并将其放入TextView中。 FileInputStream有read_bytes
,TextBuffer中有set_text
可以ustring
,但似乎没有办法从一个到另一个。
在InputStream的子类中,我发现DataInputStream确实read_line_utf8
给了一个std :: string(总比没有好),但是甚至DataInputStream也在单独的类层次结构分支上来自FileInputStream。
当然,理论上可以循环遍历read_bytes
返回的字节数组并将它们转换为字符,但不知怎的,我只是拒绝相信没有现成的函数,我可以使用它。俯视。
最终,我正在寻找能够Glib::RefPtr<Glib::Bytes>
并返回Glib::ustring
答案 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个字节,并且它不会有帮助然后阅读更多,因为无法保证该字符不会被破坏在两次读取的中间,也许我稍后会更新代码。