Повторное открытие файла в родном C-коде Android приводит к испорчению данных - PullRequest
0 голосов
/ 23 октября 2019

Собственный C открывает файл с ровно 10 строками по 24 символа в каждой и сохраняет их в массиве jstrings. Таймер используется для передачи поворота по линиям, передавая их в Java через функцию обратного вызова. Когда программа запускается, она изначально работает как задумано.

Java-часть имеет функции для изменения файла. Затем часть c обнаруживает, что файл изменился, и пытается перезагрузить файл. Это та часть, которая не работает. После якобы перезагрузки файла один и тот же текст каждый раз передается в java вместо того, чтобы вращаться по строкам, как ожидалось.

Я определил следующее

  • Когда файл обновляется, вызывается функция переустановки, которая завершает
  • , если вместо передачи намеченного jsting в java, я передаюjstring представление номера строки, я определяю, что таймер все еще работает и приращение все еще работает
  • Я полагаю, что Java-часть сохраняет файл правильно, потому что, если я полностью закрою и перезапущу приложение, обновленный файлоткрывается и данные передаются в Java, как и ожидалось

вот код, который открывает файл, пытается открыть файл и передает строки в java

#include "global_includes.h"
#include<stdio.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define  linelenght 24
#define  linecount 10

static jstring lines [linecount];
static int selected_line = 0;
struct stat sb;
static jstring filename;
char thisline [linelenght + 1];
JNIEnv* env;
jobject thiz;
jclass mainActivityObj;
jmethodID timerId2;

void reinit(){

    FILE *fp;
    fp = fopen((*env)->GetStringUTFChars(env, filename, 0), "r");
    if (fp)
    {
        for (int i = 0 ; i < 10; i++){
            size_t char_byte_size = 1;
            size_t char_count = linelenght;
            fread(&thisline, char_byte_size, char_count, fp);
            lines [i] =    (*env)->NewStringUTF(env, (const char*) &thisline);

            //1102119 JP discard linefeed
            char_count = 1;
            fread(&thisline, char_byte_size, char_count, fp);

        }

        fclose(fp);
    }
    else {
        lines[0] = (*env)->NewStringUTF(env, "Default-else-Line 1    ");
        lines[1] = (*env)->NewStringUTF(env, "Default-else-Line 2    ");
        lines[2] = (*env)->NewStringUTF(env, "Default-else-Line 3    ");
        lines[3] = (*env)->NewStringUTF(env, "Default-else-Line 4    ");
        lines[4] = (*env)->NewStringUTF(env, "Default-else-Line 5    ");
        lines[5] = (*env)->NewStringUTF(env, "Default-else-Line 6    ");
        lines[6] = (*env)->NewStringUTF(env, "Default-else-Line 7    ");
        lines[7] = (*env)->NewStringUTF(env, "Default-else-Line 8    ");
        lines[8] = (*env)->NewStringUTF(env, "Default-else-Line 9    ");
        lines[9] = (*env)->NewStringUTF(env, "Default-else-Line 10   ");

        fp = fopen((*env)->GetStringUTFChars(env, filename, 0), "w");
        if (fp)
        {
            for (int i = 0 ; i < 10; i++){
                size_t char_byte_size = 1;
                size_t char_count = linelenght;
                //fwrite(&lines [i], char_byte_size, char_count, fp);
                fwrite((*env)->GetStringUTFChars(env, lines [i], 0), char_byte_size, char_count, fp);
            }
            fclose(fp);
        }
        else{
            const char *message = strerror(errno);
            jstring errormessage = (*env)->NewStringUTF(env, message);
            (*env)->CallVoidMethod(env, mainActivityObj, timerId2, errormessage);
            //(*env)->CallVoidMethod(env, mainActivityObj, timerId2, filename);
            while (true);
        }
    }

    //101919 JP store the file info to compare to determine if latter changed
    stat((*env)->GetStringUTFChars(env, filename, 0), &sb);

    //102219 JP uncomment these 2 line and comment next 2 to see that function end reached
    // jstring statusMessage = (*env)->NewStringUTF(env, "finish reinit");
    //(*env)->CallVoidMethod(env, mainActivityObj, timerId2, statusMessage );

    //101919 JP display 1rst line initially
    selected_line = 0;
    (*env)->CallVoidMethod(env, mainActivityObj, timerId2, get_line());

}

void data_init(JNIEnv* p_env, jobject p_thiz, jstring p_filename, unsigned long interval  ) {

    filename = p_filename;
    env = p_env;
    thiz = p_thiz;
    //JP-CF 090819 originally incorrectly used just this in place of next 2
    jclass clz = (*env)->GetObjectClass(env, thiz);
    //JP-CF 090819 added following line, passing jniHelperClz to GetMethodID:
    jclass jniHelperClz = (*env)->NewGlobalRef(env, clz);
    //JP-CF 090819 added following line, passing mainActivityObj to CallVoidMethod:
    mainActivityObj = (*env)->NewGlobalRef(env, thiz);
    timerId2 = (*env)->GetMethodID(env, jniHelperClz,
                                   "updateSign", "(Ljava/lang/String;)V");

    reinit();
    tmr_init(interval);
}



bool data_poll(void){

    struct stat local_sb;
    stat((*env)->GetStringUTFChars(env, filename, 0), &local_sb);
    if (local_sb.st_mtime != sb.st_mtime)  {
        reinit();
    }

    if (tmr_poll() )  {

        selected_line  = selected_line + 1;
        if (selected_line >= 10 )
            selected_line = 0;
/*
        jstring linechar;
        if (selected_line == 0) {
            linechar = (*env)->NewStringUTF(env, "0");
        }
        if (selected_line == 1) {
            linechar = (*env)->NewStringUTF(env, "1");
        }
        if (selected_line == 2) {
            linechar = (*env)->NewStringUTF(env, "2");
        }
        if (selected_line == 3) {
            linechar = (*env)->NewStringUTF(env, "3");
        }
        if (selected_line == 4) {
            linechar = (*env)->NewStringUTF(env, "4");
        }
        if (selected_line == 5) {
            linechar = (*env)->NewStringUTF(env, "5");
        }
        if (selected_line == 6) {
            linechar = (*env)->NewStringUTF(env, "6");
        }
        if (selected_line == 7) {
            linechar = (*env)->NewStringUTF(env, "7");
        }
        if (selected_line == 8) {
            linechar = (*env)->NewStringUTF(env, "8");
        }
        if (selected_line == 9) {
            linechar = (*env)->NewStringUTF(env, "9");
        }

        if (selected_line == 10) {
            linechar = (*env)->NewStringUTF(env, "10");
        }

  */
         //(*env)->CallVoidMethod(env, mainActivityObj, timerId2,  lines[1]  );
        (*env)->CallVoidMethod(env, mainActivityObj, timerId2, get_line());

        return true;
    }
    return false;
}

jstring get_line(void){
    return lines[selected_line];
}
...