c gtk +: загрузка текстового файла в TextBuffer GtkSourceView - PullRequest
0 голосов
/ 20 февраля 2011

Я пишу программу на языке 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);
}

1 Ответ

2 голосов
/ 20 февраля 2011

Здесь возможно множество улучшений, вы, возможно, уже знакомы со многими и просто возитесь, но на случай я перечислю несколько.

gchararray file_buffer;

Просто используйте символ *

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 (символ *), а не & file_buffer (символ **). Это, вероятно, фактическая причина немедленного поломки.

Вам также необходимо проверить возвращаемое значение fread ().

Здесь также отсутствует g_utf8_validate () для считанных данных.

Посмотрите на реализацию g_file_get_contents (), чтобы увидеть один подход здесь. Вы также можете использовать g_file_load_contents для использования GFile вместо пути (переносимый, использует vfs) или, что еще лучше, в реальном приложении g_file_load_contents_async ().

Для отладки ошибок сегмента два лучших инструмента:

  • запустить в gdb, дождаться сбоя, затем набрать "bt"; обязательно используйте -g со своим компилятором при компиляции
  • бегите в valgrind, посмотрите, где написано, что вы смотрите на плохую память
...