解码base64时GtkTextView中出现UTF-8错误

UTF-8 error in GtkTextView while decoding base64

本文关键字:UTF-8 错误 base64 GtkTextView 解码      更新时间:2023-10-16

我已经想了好几天了。我所要做的就是解码一个base64字符串,并将其添加到Gtk::TextView中。以下是代码:

txtbuffer_ = Gtk::TextBuffer::create();
txtview_.set_buffer(txtbuffer_);
const Glib::ustring str = Glib::Base64::decode("YmJi3A==");
txtbuffer_->set_text(str);

当我运行程序时,我得到错误:

Gtk-CRITICAL **: gtk_text_buffer_emit_insert: assertion 'g_utf8_validate (text, len, NULL)' failed

此错误仅发生在Unicode字符中。当文本是ASCII时,一切都很正常。我尝试了三种不同的base64解码器,我尝试使用std::string和Glib::ustring与所有不同的解码器配合使用。我还尝试使用函数Glib::locale_to_utf8(),但这会导致错误terminate called after throwing an instance of 'Glib::ConvertError'。我尝试使用Glib::convert,但出现了同样的错误。

我知道Gtk::TextView可以显示Unicode,因为如果我将文本设置为具有Unicode的字符串,它将显示文本。我读到Gtk::TextView以UTF-8显示文本,所以我认为我的问题是解码的字符串不是以UTF-8编码的,但我不确定。所以我的问题是如何让Gtk::TextView显示解码后的base64?

添加说明:我使用的是Gtkmm 的3.8版本

使用3.12版本进行测试,相同错误消息

最小程序:

//test.h

#ifndef TEST_H_
#define TEST_H_
#include <gtkmm.h>
class MainWindow : public Gtk::Window
{
public:
    MainWindow();
    virtual ~MainWindow();
protected:
    Gtk::Box box_main;
    Gtk::TextView txtview_;
    Glib::RefPtr<Gtk::TextBuffer> txtbuffer_;
};
#endif /* TEST_H_ */

//test.cpp

#include "test.h"
MainWindow::MainWindow()
{   
    Gtk::Window::add(box_main);
    box_main.pack_start(txtview_);
    txtbuffer_ = Gtk::TextBuffer::create();
    txtview_.set_buffer(txtbuffer_);
    const Glib::ustring str = Glib::Base64::decode("YmJi3A==");
    txtbuffer_->set_text(str);
    Gtk::Window::show_all_children();
}
MainWindow::~MainWindow()
{
}

//main.cpp

#include "test.h"
int main(int argc, char* argv[])
{
    Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "test.program");
    MainWindow mw;
    return app->run(mw);
}

它不起作用的原因是我编码的字符串不是UTF-8。感谢:https://mail.gnome.org/archives/gtk-list/2014-April/msg00016.html.我发现编码是ISO-8859-1。因此,有两种修复方法,第一,首先将字符串编码为utf8:

const Glib::ustring str2 = Glib::Base64::encode("bbbÜ");

或者你必须弄清楚字符串的原始编码,所以对我来说这很有效:

Glib::convert(base64_str, "UTF-8", "ISO-8859-1");

来自文档:

注意,返回的二进制数据不一定是零终止的,因此不应将其用作字符串。

这意味着utf8-validate将在接近1的情况下读取超出界限的数据,并获得一个无效utf8字符的字节序列。


但即使这样也不能解决问题。似乎长度太长了一个,最后一个值只是垃圾。

所以你可以使用(我建议)

std::string stdstr = Glib::Base64::decode (x);
const Glib::ustring str(stdstr.c_str(), stdstr.length()-1);

gsize len = 0;
const gchar *ret = (gchar*)g_base64_decode (x, &len);
len --;
const Glib::ustring str(ret, len);
g_free (ret);

所以我猜这是gtk+(gtkmm封装的)中的一个错误