c gtk+: загрузка текстового файла в TextBuffer GtkSourceView
Я пишу программу с использованием языка Си с 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);
}
1 ответ
Здесь возможно много улучшений, вы, возможно, уже знакомы со многими и просто возитесь, но я перечислю несколько на всякий случай.
gchararray file_buffer;
Просто используйте char *
g_assert (fp! = NULL);
Следует использовать assert для ошибок программирования, а не ошибок времени выполнения, так что здесь лучше было бы использовать g_printerr () или диалог
fseek(fp, 0L, SEEK_END); file_size = 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, чтобы освободить место для нулевого байта.
Fread(&file_buffer, размер_файла,1, FP);
Здесь вам нужен file_buffer (char*), а не file_buffer (char**). Это, вероятно, фактическая причина немедленного поломки.
Вам также необходимо проверить возвращаемое значение fread().
Здесь также отсутствует g_utf8_validate() для считанных данных.
Взгляните на реализацию g_file_get_contents (), чтобы увидеть один подход здесь. Вы также можете использовать g_file_load_contents, чтобы использовать GFile вместо пути (переносимый, использует vfs) или, что еще лучше, в реальном приложении g_file_load_contents_async().
Для отладки segfaults, два лучших инструмента:
- запустите в gdb, дождитесь сбоя, затем наберите "bt"; обязательно используйте -g с вашим компилятором при компиляции
- беги в валгринде, посмотри где написано ты смотришь на плохую память