【问题标题】:JNI: Reading a text file in C code and returning to sdkJNI:读取 C 代码中的文本文件并返回到 sdk
【发布时间】:2013-12-19 15:20:22
【问题描述】:

我正在尝试创建一个 android 应用程序以使用 NDK 从文本文件中读取文本。我的 C 代码将字符串读入变量并将字符串变量返回给 java 代码。但是当我运行 Android 应用程序时,字符串显示在TextView 显示为@ 等符号,后跟一些矩形。从 JNI 返回字符串的格式是什么?检查下面的代码。我可以在没有任何其他权限的情况下读取系统文件吗? printf() 语句会做什么?

Java 代码:

package com.example.openfile;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements OnClickListener{
public native String ndkopenfile();
static{
    System.loadLibrary("mylib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //TextView textView1 = new TextView(this);
    //textView1.setText(ndkopenfile());
    Button button1 = (Button)findViewById(R.id.button1);
    button1.setOnClickListener(this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public void onClick(View v) {
    // TODO Auto-generated method stub
    String str1;
    Log.d("Click","The button has been clicked to open the file");

    str1=ndkopenfile();

    //setTitle(str1);
    TextView tv = (TextView)findViewById(R.id.textView1);
    tv.setText(str1);
}

}

C 代码:

JNIEXPORT jstring JNICALL Java_com_example_openfile_MainActivity_ndkopenfile
(JNIEnv *env, jobject this)
{

    jstring str1[20];
    FILE* fp = fopen("/sdcard/x.txt","w+");
    if(fp!=NULL)
    {
        fgets(str1,20,fp);
        fflush(fp);
        fclose(fp);
        return(*env)->NewStringUTF(env,str1);
    }
    else
    {
        fclose(fp);
        return(*env)->NewStringUTF(env,"Error opening file!");
    }
 }

【问题讨论】:

  • 你是用 Java 写的文件吗?或者你是从另一台电脑下载的?
  • NewStringUTF 调用采用 UTF-8 文本。除非您确定“x.txt”包含有效的 UTF-8 数据,否则您应该自己转换它(根据实际使用的字符集,或者通过简单地踩踏任何非 7 位 ASCII 值)。请注意,您可以在 Java 中轻松地执行此处显示的操作...使用 NDK 不会授予您额外的权限。
  • @fadden 不,NewStringUTF 采用 modified UTF-8 文本。它不能接受所有有效的 UTF-8 字符串。见Android JNI Tips。作为过滤的更好替代方法,只需在将字符串复制到jbyteArray 后调用java.lang.String(byte[]) 构造函数。这样就不会丢失数据。
  • 关于 MUTF-8 的公平点(不知何故,我总是忽略提及)。我认为 String 构造函数仍然可能存在数据丢失 - 正如文档所说,“当给定字节在默认字符集中无效时,此构造函数的行为未指定。”无论如何,我已经看到很多代码尝试将任意 8 位数据(文件名、用户输入)传递给 NewStringUTF,这就是为什么 CheckJNI 在看到错误输入时会做出强烈反应的原因。
  • @fadden 在 Android 上,默认字符集是 Unicode,默认编码是 UTF-8。 Android JVM 说明了这一点。如果对 JVM 使用什么作为其操作系统默认值有任何疑问,请调用 java.lang.String(byte[], java.lang.Charset) 构造函数。

标签: android-ndk java-native-interface


【解决方案1】:

试试这个:

JNIEXPORT jstring JNICALL Java_com_example_openfile_MainActivity_ndkopenfile
(JNIEnv *env, jobject this)
{
        char myStr[20];
        FILE* fp = fopen("/sdcard/x.txt","w+");
        if(fp!=NULL)
        {
            fgets(myStr,20,fp);
            fflush(fp);
            fclose(fp);
            return(*env)->NewStringUTF(env,myStr);
        }
        else
        {
            fclose(fp);
            return(*env)->NewStringUTF(env,"Error opening file!");
        }
}

这项技术非常有效!经过测试。

【讨论】:

  • 天哪,做到了!谢谢你!但如果你能回答其他问题,我将不胜感激!!!
  • @user2745435:哪个问题?在这里发布您的问题的链接,我会尝试。
  • 我见过一些程序员在 Java 原生代码中添加了 printf 语句。出于好奇,我也试过了,但什么也没发生。
  • 如果文件打开失败,您不需要关闭它。必须删除 else 中的 fclose 行。正如文档所说, fclose NULL 会导致分段违规
  • @Zax 我从上面的代码中得到了一些问题。致命信号 11 (SIGSEGV) 代码 1,tid 13524 中的故障地址 0xc。
【解决方案2】:

我认为你的定义jstring str1[20];需要修改为char str1[20]。因为 jstring 类型被定义为一个 jobject,所以它不是 char 的基本类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    相关资源
    最近更新 更多