c gtk+:将文本文件加载到 GtkSourceView 的 TextBuffer 中

发布于 2024-10-18 03:28:27 字数 2223 浏览 7 评论 0原文

我正在使用 C 语言与 gtk+ 和 gtksourceview-2.0 编写一个程序。

我使用 GtkFileChooser 供用户选择一个文件,当他单击它时,我希望将内容加载到 GtkSourceView 的 TextBuffer 中,

这是当用户双击 GtkFileChooser 上的文件时执行的函数:

void on_file_activated(GtkWidget *widget, gpointer data) {
    GFile *file;
    FILE *fp;
    gchar *path_name;
    long file_size;
    gchararray file_buffer;
    file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(widget));
    path_name=g_file_get_path(file);
    g_debug("%s is chosen\n", path_name);
    fp=fopen(path_name, "r");
    g_assert( fp != NULL);
    fseek(fp, 0L, SEEK_END);
    file_size = ftell(fp);
    rewind(fp);
    g_debug("file size: %ld\n",file_size*sizeof(gchar));
    file_buffer=calloc(file_size, sizeof(gchar));
    g_assert(file_buffer != NULL);
    fread(&file_buffer,file_size,1,fp);
    g_debug("after fread");
    //file_buffer[file_size*sizeof(gchar)]=0;
    //g_debug("after adding zero: %s",file_buffer);
    gtk_text_buffer_set_text (textbuffer, file_buffer,2);
    g_debug("after set text");
    g_object_unref(file);
}

这是我的应用程序的输出:

** (tour_de_gtk:18107): DEBUG: /home/ufk/Projects/gtk-projects/tour-de-gtk/Debug/src/examples/example_gtk_label/main.c is chosen

** (tour_de_gtk:18107): DEBUG: file size: 16

** (tour_de_gtk:18107): DEBUG: after fread 

之后我在命令 gtk_text_buffer_set_text 上出现分段错误,

如您所见,我有两个命令被注释掉。尝试 g_debug 缓冲区,这显然会产生分段错误,因为我没有在字符串末尾添加零,甚至当我尝试在字符串末尾添加零时,我也会遇到分段错误。我可能做错了什么。

在这里,我试图只写入缓冲区的前两个字符,但没有成功。

有什么想法吗?

更新

完成的功能:

void on_file_activated(GtkWidget *widget, gpointer data) {
GFile *file;
gchar *path_name;
long file_size;
gchar *file_buffer;
GError *error;
gboolean read_file_status;
file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(widget));
path_name=g_file_get_path(file);
g_debug("%s is chosen\n", path_name);
read_file_status=g_file_get_contents (path_name,&file_buffer,NULL, &error);

if (read_file_status == FALSE) {
    g_error("error opening file: %s\n",error && error->message ? error->message : "No Detail");
    return;
}
gtk_text_buffer_set_text (textbuffer, file_buffer,-1);
g_debug("after set text");
g_object_unref(file);
}

I'm writing a program using the C language with gtk+ and gtksourceview-2.0.

I'm using a GtkFileChooser for the user to choose a file and when he clicks on it, i want the content to be loaded to the GtkSourceView' TextBuffer

this is the function that gets executed when a user double click's a file on the GtkFileChooser:

void on_file_activated(GtkWidget *widget, gpointer data) {
    GFile *file;
    FILE *fp;
    gchar *path_name;
    long file_size;
    gchararray file_buffer;
    file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(widget));
    path_name=g_file_get_path(file);
    g_debug("%s is chosen\n", path_name);
    fp=fopen(path_name, "r");
    g_assert( fp != NULL);
    fseek(fp, 0L, SEEK_END);
    file_size = ftell(fp);
    rewind(fp);
    g_debug("file size: %ld\n",file_size*sizeof(gchar));
    file_buffer=calloc(file_size, sizeof(gchar));
    g_assert(file_buffer != NULL);
    fread(&file_buffer,file_size,1,fp);
    g_debug("after fread");
    //file_buffer[file_size*sizeof(gchar)]=0;
    //g_debug("after adding zero: %s",file_buffer);
    gtk_text_buffer_set_text (textbuffer, file_buffer,2);
    g_debug("after set text");
    g_object_unref(file);
}

this is the output of my application:

** (tour_de_gtk:18107): DEBUG: /home/ufk/Projects/gtk-projects/tour-de-gtk/Debug/src/examples/example_gtk_label/main.c is chosen

** (tour_de_gtk:18107): DEBUG: file size: 16

** (tour_de_gtk:18107): DEBUG: after fread 

after then i get a segmentation fault on the command gtk_text_buffer_set_text

as you can see i have two commands that are commented out. trying to g_debug the buffer which obviously creates a segmentation fault because i didn't add a zero to the end of the string, and even when I try to add zero to the end of the string i get a segmentation fault. I probably did something wrong.

here i'm trying to write only the first two characters of the buffer but with no luck.

any ideas?

update

the finished function:

void on_file_activated(GtkWidget *widget, gpointer data) {
GFile *file;
gchar *path_name;
long file_size;
gchar *file_buffer;
GError *error;
gboolean read_file_status;
file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(widget));
path_name=g_file_get_path(file);
g_debug("%s is chosen\n", path_name);
read_file_status=g_file_get_contents (path_name,&file_buffer,NULL, &error);

if (read_file_status == FALSE) {
    g_error("error opening file: %s\n",error && error->message ? error->message : "No Detail");
    return;
}
gtk_text_buffer_set_text (textbuffer, file_buffer,-1);
g_debug("after set text");
g_object_unref(file);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心奴独伤 2024-10-25 03:28:27

这里有很多可能的改进,您可能已经知道很多并且只是在乱搞,但我将列出几个以防万一。

gchararray file_buffer;

只需使用 char*

g_assert(fp!= NULL);

应该使用断言来处理编程错误,而不是运行时错误,所以这里 g_printerr() 或对话框会更好

fseek(fp, 0L, SEEK_END);
文件大小=ftell(fp);
快退(fp);

fstat(fileno(fp), &statbuf) 可能是更好的方法,但整个方法有点糟糕;与其获取大小,不如直接读入动态增长的缓冲区。或者,如果您愿意预分配整个缓冲区,只需使用 g_file_get_contents()。另一种方法是 g_file_query_info() (它更便携并且使用 vfs)

file_buffer=calloc(file_size, sizeof(gchar));

g_new0(char, file_size) 更好,或者 g_malloc0(file_size)。此外,您还需要 file_size+1 为 nul 字节腾出空间。

fread(&file_buffer,file_size,1,fp);

这里你需要 file_buffer (a char*) 而不是 &file_buffer (a char**)。这可能是立即破损的真正原因。

您还需要检查 fread() 的返回值。

这里还缺少读入数据的 g_utf8_validate()。

查看 g_file_get_contents() 的实现以了解此处的一种方法。您还可以使用 g_file_load_contents 来使用 GFile 而不是路径(可移植,使用 vfs),或者在现实应用程序中更好的是 g_file_load_contents_async()。

要调试段错误,两个最好的工具是:

  • 在 gdb 中运行,等待崩溃,然后输入“bt”;当你在 valgrind 中编译运行时,一定要在你的编译器中使用 -g
  • ,看看它说你在哪里查看坏内存

There are a lot of improvements possible here, you may already know many and just be messing around, but I'll list several in case.

gchararray file_buffer;

Just use char*

g_assert( fp != NULL);

Should use assert for programming errors, not runtime errors, so here g_printerr() or a dialog would be better

fseek(fp, 0L, SEEK_END);
file_size = ftell(fp);
rewind(fp);

fstat(fileno(fp), &statbuf) is probably a better way to do this, but the whole approach is kind of bad; rather than get the size, it's better to just read into a dynamically-growing buffer. Or if you're willing to preallocate the whole buffer, just use g_file_get_contents(). Another approach is g_file_query_info() (which is more portable and uses the vfs)

file_buffer=calloc(file_size, sizeof(gchar));

g_new0(char, file_size) is nicer, or g_malloc0(file_size). Also you need file_size+1 to make room for the nul byte.

fread(&file_buffer,file_size,1,fp);

Here you want file_buffer (a char*) rather than &file_buffer (a char**). This is probably the actual cause of the immediate breakage.

You also need to check the return value of fread().

Also missing here is g_utf8_validate() on the data read in.

Have a look at the implementation of g_file_get_contents() to see one approach here. You could also use g_file_load_contents to use a GFile instead of a path (portable, uses vfs) or better yet in a real-world app, g_file_load_contents_async().

To debug segfaults, the two best tools are:

  • run in gdb, wait for crash, then type "bt"; be sure to use -g with your compiler when you compile
  • run in valgrind, see where it says you look at bad memory
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文