عمليات الملفات في Android NDK
-
22-09-2019 - |
سؤال
أنا أستخدم Android NDK لتقديم تطبيق في المقام الأول في C لأسباب الأداء ، ولكن يبدو أن عمليات الملفات مثل FOPEN لا تعمل بشكل صحيح في Android. كلما حاولت استخدام هذه الوظائف ، يتعطل التطبيق.
كيف يمكنني إنشاء/الكتابة إلى ملف مع Android NDK؟
المحلول
إجابات أخرى صحيحة. يمكنك فتح ملف من خلال NDK باستخدام FILE
و fopen
, ولكن لا تنس وضع إذن لذلك.
في مكان Android Place:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
نصائح أخرى
File IO يعمل بشكل جيد على Android باستخدام JNI. ربما تحاول فتح ملف بمسار سيء وعدم التحقق من رمز الإرجاع؟ لقد قمت بتعديل مثال Hello-Jni لإثبات أنه من الممكن بالفعل فتح الملف والكتابة إليه. آمل أن يساعد هذا.
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <string.h>
#include <jni.h>
#include <stdio.h>
/* This is a trivial JNI example where we use a native method
* to return a new VM String. See the corresponding Java source
* file located at:
*
* apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java
*/
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
FILE* file = fopen("/sdcard/hello.txt","w+");
if (file != NULL)
{
fputs("HELLO WORLD!\n", file);
fflush(file);
fclose(file);
}
return (*env)->NewStringUTF(env, "Hello from JNI (with file io)!");
}
هذه هي النتيجة بعد تشغيله على هاتفي (مع بطاقة SD):
$ adb -d shell cat /sdcard/hello.txt
HELLO WORLD!
تأكد من استخدام جافا getExternalStorageDirectory()
اتصل للحصول على المسار الحقيقي إلى SDCARD لأن الأجهزة الأحدث لا تُخطط ببساطة إلى "/sdcard". في هذه الحالة ، سيفشل محاولة استخدام موقع متشددين لـ "/sdcard".
يمكنني أيضًا التحقق من أن FOPEN () يعمل بشكل صحيح ، ولكن ليس إذا كنت تحاول الوصول إلى ملف في مجلد موارد أو أصول التطبيق. أوصي ، لتجنب الاضطرار إلى إعادة اختراع العجلة ، وأن تقوم بإلصاق أي أصول تريد شحنها مع تطبيقك في مجلد الأصول ، حيث سيتم تعبئتها للتوزيع.
في حالة مجلد الأصول ، تحتاج إلى القيام بأحد أمرين ، اعتمادًا على ما إذا كان الملف مضغوطًا بواسطة Packager. كلاهما يستخدم أساليب AssetManager ، ويمكنك الحصول على AssetManager من السياق/التطبيق. تكون أسماء الملفات دائمًا بالنسبة إلى مجلد الأصول ، راجع للشغل: إذا كان لديك ملف "foo.png" مباشرة في مجلد الأصول ، فستفتح "foo.png" ، " ليس شيء مثل "الأصول/foo.png".
إذا لم يكن الملف مضغوطًا (أي ، فهو أحد الامتدادات التي لا يتم ضغطها ، مثل .png) ، يمكنك الحصول على واصف ملف من AssetManager.openfd () ونقله إلى C ++. ثم يمكنك استخدام FDOPEN (DUP (FD) ، "R") ؛ لفتح الملف كملف*. لاحظ لك يجب FSEEK () إلى الإزاحة ، وتتبع طول الملف بنفسك. يمكنك حقًا الحصول على مقبض ملف إلى حزمة الأصول بأكملها ، وملف اهتمامك هو جزء صغير فقط.
إذا كان ملفك مضغوطًا ، فأنت بحاجة إلى استخدام قارئ دفق Java: AssetManager.open () يمنحك inputstream يمكنك استخدام قراءة الملف فيه. هذا pita لأنه لا يمكنك الاستعلام عن حجم الملف ؛ أقوم بتشغيل خطوة معالجة مسبقة على مجلد الأصول الذي يولد قائمة بجميع الملفات بأحجامها الخاصة حتى أتمكن من معرفة ، على سبيل المثال ، كم حجم المخزن المؤقت لتخصيصه.
إذا كان ملفك موردًا ، فقد تحتاج إلى مرور فئة الموارد للوصول إليه ، على الرغم من أنه يبدو أن الموارد معبأة أيضًا في حزمة الأصول نفسها. يحتوي Resource على مكالمة OpenRawResource () للحصول على InputStream ومكالمة OpenRawResourceFD () للحصول على واصف الملف ، على النحو الوارد أعلاه ، على الرغم من.
حظا طيبا وفقك الله.