1# Rawfile开发指导
2
3## 场景介绍
4
5开发者可以通过本指导了解在OpenHarmony应用中,如何使用Native Rawfile接口操作Rawfile目录和文件。功能包括文件列表遍历、文件打开、搜索、读取和关闭Rawfile。  
664后缀相关接口属于新增接口,新接口支持打开更大的rawfile文件(超过2G以上建议使用),具体请参考:[Rawfile接口介绍](../reference/apis-localization-kit/rawfile.md)。64相关的开发步骤和非64一致,将非64接口替换为64接口即可,例如:OH_ResourceManager_OpenRawFile替换为OH_ResourceManager_OpenRawFile64。
7
8## 接口说明
9
10| 接口名                                                       | 描述                                     |
11| :----------------------------------------------------------- | :--------------------------------------- |
12| NativeResourceManager *OH_ResourceManager_InitNativeResourceManager(napi_env env, napi_value jsResMgr) | 初始化native resource manager。          |
13| RawDir *OH_ResourceManager_OpenRawDir(const NativeResourceManager *mgr, const char *dirName) | 打开指定rawfile目录。                    |
14| int OH_ResourceManager_GetRawFileCount(RawDir *rawDir)       | 获取指定rawfile目录下的rawfile文件数量。 |
15| const char *OH_ResourceManager_GetRawFileName(RawDir *rawDir, int index) | 获取rawfile名字。                        |
16| RawFile *OH_ResourceManager_OpenRawFile(const NativeResourceManager *mgr, const char *fileName) | 打开指定rawfile文件。                    |
17| long OH_ResourceManager_GetRawFileSize(RawFile *rawFile)     | 获取rawfile文件大小。                    |
18| int OH_ResourceManager_SeekRawFile(const RawFile *rawFile, long offset, int whence) | 指定rawfile内偏移量。                    |
19| long OH_ResourceManager_GetRawFileOffset(const RawFile *rawFile) | 获取rawfile偏移量。                      |
20| int OH_ResourceManager_ReadRawFile(const RawFile *rawFile, void *buf, size_t length) | 读取rawfile文件内容。                    |
21| int64_t OH_ResourceManager_GetRawFileRemainingLength(const RawFile *rawFile) | 获取rawfile文件剩余长度。                    |
22| void OH_ResourceManager_CloseRawFile(RawFile *rawFile)       | 释放rawfile文件相关资源。                |
23| void OH_ResourceManager_CloseRawDir(RawDir *rawDir)          | 释放rawfile目录相关资源。                |
24| bool OH_ResourceManager_GetRawFileDescriptor(const RawFile *rawFile, RawFileDescriptor &descriptor) | 获取rawfile的fd。                        |
25| bool OH_ResourceManager_ReleaseRawFileDescriptor(const RawFileDescriptor &descriptor) | 释放rawfile的fd。                        |
26| void OH_ResourceManager_ReleaseNativeResourceManager(NativeResourceManager *resMgr) | 释放native resource manager相关资源。    |
27| bool OH_ResourceManager_IsRawDir(const NativeResourceManager *mgr, const char *path) | 判断路径是否是rawfile下的目录    |
28
29
30
31## 函数介绍
32
331. 根据NativeResourceManager实例,使用OH_ResourceManager_OpenRawDir接口获取RawDir实例。
34
35    ```c++
36    RawDir* rawDir = OH_ResourceManager_OpenRawDir(nativeResourceManager, path.c_str());
37    ```
38
392. 根据RawDir实例,使用OH_ResourceManager_GetRawFileCount接口获取对应目录下的rawfile文件总数 。
40
41    ```c++
42    int count = OH_ResourceManager_GetRawFileCount(rawDir);
43    ```
44
453. 根据RawDir实例,使用OH_ResourceManager_GetRawFileName接口获取目录下对应index的rawfile文件名。
46
47    ```c++
48    for (int index = 0; index < count; index++) {
49        std::string fileName = OH_ResourceManager_GetRawFileName(rawDir, index);
50    }
51    ```
52
534. 根据NativeResourceManager实例,使用OH_ResourceManager_OpenRawFile接口获取指定文件名的RawFile实例
54
55    ```c++
56    RawFile* rawFile = OH_ResourceManager_OpenRawFile(nativeResourceManager, fileName.c_str());
57    ```
58
595. 根据RawFile实例,使用OH_ResourceManager_GetRawFileSize接口获取对应rawfile文件大小。
60
61    ```c++
62    long rawFileSize = OH_ResourceManager_GetRawFileSize(rawFile);
63    ```
64
656. 根据RawFile实例,使用OH_ResourceManager_SeekRawFile接口指定rawfile偏移量。
66
67    ```c++
68    int position = OH_ResourceManager_SeekRawFile(rawFile, 10, 0);
69    int position = OH_ResourceManager_SeekRawFile(rawFile, 0 , 1);
70    int position = OH_ResourceManager_SeekRawFile(rawFile, -10, 2);
71    ```
72
737. 根据RawFile实例,使用OH_ResourceManager_GetRawFileOffset接口获取rawfile偏移量。
74
75    ```c++
76    long rawFileOffset = OH_ResourceManager_GetRawFileOffset(rawFile)
77    ```
78
798. 根据RawFile实例,使用OH_ResourceManager_ReadRawFile接口读取rawfile文件内容。
80
81    ```c++
82    std::unique_ptr<char[]> mediaData = std::make_unique<char[]>(rawFileSize);
83    long rawFileOffset = OH_ResourceManager_ReadRawFile(rawFile, mediaData.get(), rawFileSize);
84    ```
85
869. 根据RawFile实例,使用OH_ResourceManager_GetRawFileRemainingLength接口读取rawfile文件的剩余长度。
87
88    ```c++
89    int64_t rawFileRemainingSize = OH_ResourceManager_GetRawFileRemainingLength(rawFile);
90    ```
91
9210. 根据RawFile实例,使用OH_ResourceManager_CloseRawFile接口释放rawfile文件相关资源。
93
94    ```c++
95    OH_ResourceManager_CloseRawFile(rawFile);
96    ```
97
9811. 根据RawDir实例,使用OH_ResourceManager_CloseRawDir接口释放rawfile目录相关资源。
99
100    ```c++
101    OH_ResourceManager_CloseRawDir(rawDir);
102    ```
103
10412. 根据RawFile实例,使用OH_ResourceManager_GetRawFileDescriptor接口获取rawfile的RawFileDescriptor。
105
106    ```c++
107    RawFileDescriptor descriptor;
108    bool result = OH_ResourceManager_GetRawFileDescriptor(rawFile, descriptor);
109    ```
110
11113. 根据RawFileDescriptor实例,使用OH_ResourceManager_ReleaseRawFileDescriptor接口关闭rawfile的fd。
112
113    ```c++
114    OH_ResourceManager_ReleaseRawFileDescriptor(descriptor);
115    ```
116
11714. 根据NativeResourceManager实例,使用OH_ResourceManager_ReleaseNativeResourceManager接口释放native resource manager。
118
119    ```c++
120    OH_ResourceManager_ReleaseNativeResourceManager(nativeResourceManager);
121    ```
122
12314. 根据传入的rawfile路径,使用OH_ResourceManager_IsRawDir接口判断是否是目录。
124
125    ```c++
126    OH_ResourceManager_IsRawDir(nativeResourceManager, path);
127    ```
128
129## 开发步骤
130
131   以ArkTS侧获取rawfile文件列表、rawfile文件内容、rawfile描述符{fd, offset, length}三种调用方式为例。
132
133**1. 创建工程**
134
135![创建C++应用](figures/rawfile1.png)
136
137**2. 添加依赖**
138
139创建完成后,IDE会在工程生成cpp目录,目录有libentry/index.d.tshello.cppCMakeLists.txt等文件。
140
1411. 打开src/main/cpp/CMakeLists.txt,在target_link_libraries依赖中添加资源的librawfile.z.so以及日志依赖libhilog_ndk.z.so142
143    ```c++
144    target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so librawfile.z.so)
145    ```
146
1472. 打开src/main/cpp/types/libentry/index.d.ts文件,此文件声明了应用侧函数getFileList、getRawFileContent、getRawFileDescriptor。
148
149    ```c++
150    import resourceManager from '@ohos.resourceManager';
151    export const getFileList: (resmgr: resourceManager.ResourceManager, path: string) => Array<String>;
152    export const getRawFileContent: (resmgr: resourceManager.ResourceManager, path: string) => Uint8Array;
153    export const getRawFileDescriptor: (resmgr: resourceManager.ResourceManager, path: string) => resourceManager.RawFileDescriptor;
154    export const isRawDir: (resmgr: resourceManager.ResourceManager, path: string) => Boolean;
155    ```
156
157**3. 修改源文件**
158
1591. 打开src/main/cpp/hello.cpp文件,文件Init会对当前方法进行初始化映射,这里定义对外接口为getFileList、getRawFileContent、getRawFileDescriptor,映射C++接口分别为GetFileList、GetRawFileContent、GetRawFileDescriptor。
160
161    ```c++
162    EXTERN_C_START
163    static napi_value Init(napi_env env, napi_value exports)
164    {
165        napi_property_descriptor desc[] = {
166            { "getFileList", nullptr, GetFileList, nullptr, nullptr, nullptr, napi_default, nullptr },
167            { "getRawFileContent", nullptr, GetRawFileContent, nullptr, nullptr, nullptr, napi_default, nullptr },
168            { "getRawFileDescriptor", nullptr, GetRawFileDescriptor, nullptr, nullptr, nullptr, napi_default, nullptr },
169            { "isRawDir", nullptr, IsRawDir, nullptr, nullptr, nullptr, napi_default, nullptr }
170        };
171
172        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
173        return exports;
174    }
175    EXTERN_C_END
176    ```
177
1782. 把src/main/cpp/hello.cpp文件中,增加对应的三个方法,如下所示
179
180    ```c++
181    static napi_value GetFileList(napi_env env, napi_callback_info info)
182    static napi_value GetRawFileContent(napi_env env, napi_callback_info info)
183    static napi_value GetRawFileDescriptor(napi_env env, napi_callback_info info)
184    static napi_value IsRawDir(napi_env env, napi_callback_info info)
185    ```
186
1873. 在hello.cpp文件中获取Js的资源对象,并转为Native的资源对象,即可调用资源的Native接口,获取rawfile列表、rawfile文件内容以及rawfile描述符{fd, offset, length}三种调用方式示例代码如下:
188
189    ```c++
190    #include <rawfile/raw_file.h>
191    #include <rawfile/raw_dir.h>
192    #include <rawfile/raw_file_manager.h>
193
194    // 示例一:获取rawfile文件列表 GetFileList
195    static napi_value GetFileList(napi_env env, napi_callback_info info)
196    {
197        OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, tag, "NDKTest Begin");
198        size_t requireArgc = 3;
199        size_t argc = 2;
200        napi_value argv[2] = { nullptr };
201        // 获取参数信息
202        napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
203
204        // argv[0]即为函数第一个参数Js资源对象,OH_ResourceManager_InitNativeResourceManager转为Native对象。
205        NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, argv[0]);
206
207        // 获取函数argv[1],此为为rawfile相对路径
208        size_t strSize;
209        char strBuf[256];
210        napi_get_value_string_utf8(env, argv[1], strBuf, sizeof(strBuf), &strSize);
211        std::string dirName(strBuf, strSize);
212
213        // 获取对应的rawDir指针对象
214        RawDir* rawDir = OH_ResourceManager_OpenRawDir(mNativeResMgr, dirName.c_str());
215
216        // 获取rawDir下文件及文件夹数量
217        int count = OH_ResourceManager_GetRawFileCount(rawDir);
218
219        // 遍历获取文件名称,并保存
220        std::vector<std::string> tempArray;
221        for(int i = 0; i < count; i++) {
222            std::string filename = OH_ResourceManager_GetRawFileName(rawDir, i);
223            tempArray.emplace_back(filename);
224        }
225
226        napi_value fileList;
227        napi_create_array(env, &fileList);
228        for (size_t i = 0; i < tempArray.size(); i++) {
229            napi_value jsString;
230            napi_create_string_utf8(env, tempArray[i].c_str(), NAPI_AUTO_LENGTH, &jsString);
231            napi_set_element(env, fileList, i, jsString);
232        }
233
234        // 关闭打开的指针对象
235        OH_ResourceManager_CloseRawDir(rawDir);
236        OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr);
237        return fileList;
238    }
239
240    // 示例二:获取rawfile文件内容 GetRawFileContent
241    napi_value CreateJsArrayValue(napi_env env, std::unique_ptr<uint8_t[]> &data, long length)
242    {
243        napi_value buffer;
244        napi_status status = napi_create_external_arraybuffer(env, data.get(), length,
245                [](napi_env env, void *data, void *hint) {
246                    delete[] static_cast<char*>(data);
247                }, nullptr, &buffer);
248        if (status != napi_ok) {
249            OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, tag, "Failed to create external array buffer");
250            return nullptr;
251        }
252        napi_value result = nullptr;
253        status = napi_create_typedarray(env, napi_uint8_array, length, buffer, 0, &result);
254        if (status != napi_ok) {
255            OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, tag, "Failed to create media typed array");
256            return nullptr;
257        }
258        data.release();
259        return result;
260    }
261    static napi_value GetRawFileContent(napi_env env, napi_callback_info info)
262    {
263        OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, tag, "GetFileContent Begin");
264        size_t requireArgc = 3;
265        size_t argc = 2;
266        napi_value argv[2] = { nullptr };
267        // 获取参数信息
268        napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
269
270        // argv[0]即为函数第一个参数Js资源对象,OH_ResourceManager_InitNativeResourceManager转为Native对象。
271        NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, argv[0]);
272        size_t strSize;
273        char strBuf[256];
274        napi_get_value_string_utf8(env, argv[1], strBuf, sizeof(strBuf), &strSize);
275        std::string filename(strBuf, strSize);
276
277        // 获取rawfile指针对象
278        RawFile *rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, filename.c_str());
279        if (rawFile != nullptr) {
280            OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, tag, "OH_ResourceManager_OpenRawFile success");
281        }
282        // 获取rawfile大小并申请内存
283        long len = OH_ResourceManager_GetRawFileSize(rawFile);
284        std::unique_ptr<uint8_t[]> data= std::make_unique<uint8_t[]>(len);
285
286        // 一次性读取rawfile全部内容
287        int res = OH_ResourceManager_ReadRawFile(rawFile, data.get(), len);
288
289        // 多次部分读取rawfile, 每次读取100 Byte。获取全部内容
290        // long offset = 0;
291        // while (OH_ResourceManager_GetRawFileRemainingLength(rawFile) > 0) {
292        //     OH_ResourceManager_ReadRawFile(rawFile, data.get() + offset, 100);
293        //     offset += 100;
294        // }
295
296        // 关闭打开的指针对象
297        OH_ResourceManager_CloseRawFile(rawFile);
298        OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr);
299        // 转为js对象
300        return CreateJsArrayValue(env, data, len);
301    }
302
303    // 示例三:获取rawfile文件描述符 GetRawFileDescriptor
304    napi_value createJsFileDescriptor(napi_env env, RawFileDescriptor &descriptor)
305    {
306        napi_value result;
307        napi_status status = napi_create_object(env, &result);
308        if (status != napi_ok) {
309            return result;
310        }
311
312        napi_value fd;
313        status = napi_create_int32(env, descriptor.fd, &fd);
314        if (status != napi_ok) {
315            return result;
316        }
317        status = napi_set_named_property(env, result, "fd", fd);
318        if (status != napi_ok) {
319            return result;
320        }
321
322        napi_value offset;
323        status = napi_create_int64(env, descriptor.start, &offset);
324        if (status != napi_ok) {
325            return result;
326        }
327        status = napi_set_named_property(env, result, "offset", offset);
328        if (status != napi_ok) {
329            return result;
330        }
331
332        napi_value length;
333        status = napi_create_int64(env, descriptor.length, &length);
334        if (status != napi_ok) {
335            return result;
336        }
337        status = napi_set_named_property(env, result, "length", length);
338        if (status != napi_ok) {
339            return result;
340        }
341        return result;
342    }
343    static napi_value GetRawFileDescriptor(napi_env env, napi_callback_info info)
344    {
345        OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, tag, "NDKTest GetRawFileDescriptor Begin");
346        size_t requireArgc = 3;
347        size_t argc = 2;
348        napi_value argv[2] = { nullptr };
349        // 获取参数信息
350        napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
351        
352        napi_valuetype valueType;
353        napi_typeof(env, argv[0], &valueType);
354        // 获取native的resourceManager对象
355        NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, argv[0]);
356        size_t strSize;
357        char strBuf[256];
358        napi_get_value_string_utf8(env, argv[1], strBuf, sizeof(strBuf), &strSize);
359        std::string filename(strBuf, strSize);
360        // 获取rawfile指针对象
361        RawFile *rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, filename.c_str());
362        if (rawFile != nullptr) {
363            OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, tag, "OH_ResourceManager_OpenRawFile success");
364        }
365        // 获取rawfile的描述符RawFileDescriptor {fd, offset, length}
366        RawFileDescriptor descriptor;
367        OH_ResourceManager_GetRawFileDescriptor(rawFile, descriptor);
368        // 关闭打开的指针对象
369        OH_ResourceManager_CloseRawFile(rawFile);
370        OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr);
371        // 转为js对象
372        return createJsFileDescriptor(env,descriptor);
373    }
374    napi_value CreateJsBool(napi_env env, bool &bValue)
375    {
376        napi_value jsValue = nullptr;
377        if (napi_get_boolean(env, bValue, &jsValue) != napi_ok) {
378            return nullptr;
379        }
380        return jsValue;
381    }
382    static napi_value IsRawDir(napi_env env, napi_callback_info info)
383    {
384        OH_LOG_Print(LOG_APP, LOG_ERROR, GLOBAL_RESMGR, tag, "NDKTest IsRawDir Begin");
385        size_t requireArgc = 3;
386        size_t argc = 2;
387        napi_value argv[2] = { nullptr };
388        // 获取参数信息
389        napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
390
391        napi_valuetype valueType;
392        napi_typeof(env, argv[0], &valueType);
393        // 获取native的resourceManager对象
394        NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, argv[0]);
395
396        napi_valuetype valueType1;
397        napi_typeof(env, argv[1], &valueType);
398        if (valueType1 == napi_undefined || valueType1 == napi_null) {
399            bool temp = false;
400            return CreateJsBool(env, temp);
401        }
402        size_t strSize;
403        char strBuf[256];
404        napi_get_value_string_utf8(env, argv[1], strBuf, sizeof(strBuf), &strSize);
405        std::string filename(strBuf, strSize);
406        // 获取rawfile指针对象
407        bool result = OH_ResourceManager_OpenRawFile(mNativeResMgr, filename.c_str());
408        OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr);
409        return CreateJsBool(env, result);
410    }
411    ```
412
413**4. Js侧调用**
414
4151. 打开src\main\ets\pages\index.ets, 导入"libentry.so";
416
4172. 资源获取包括获取本应用包资源、应用内跨包资源、跨应用包资源。<br>获取本应用包resourceManager对象,通过.context().resourceManager方法。<br>获取应用内跨包resourceManager对象,通过.context().createModuleContext().resourceManager 方法。<br>获取跨应用包resourceManager对象,通过.context.createModuleContext(bundleName:'bundleName name',moduleName:'module name').resourceManager方法,该方法仅支持系统应用使用。<br>Context的更多使用信息请参考[应用上下文Context](../application-models/application-context-stage.md)。
418    
4193. 调用Native接口getFileList即为src/main/cpp/types/libentry/index.d.ts中声明的接口,传入js的资源对象,以及rawfile文件夹的相对路径。
420
421   获取本应用包资源resourceManager对象的示例如下:
422
423    ```js
424    import hilog from '@ohos.hilog';
425    import testNapi from 'libentry.so'  // 导入so
426    @Entry
427    @Component
428    struct Index {
429        @State message: string = 'Hello World'
430        private resmgr = getContext().resourceManager;  // 获取本应用包的资源对象
431        build() {
432            Row() {
433            Column() {
434                Text(this.message)
435                .fontSize(50)
436                .fontWeight(FontWeight.Bold)
437                .onClick(() => {
438                    hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO);
439                    let rawfilelist = testNapi.getFileList(this.resmgr, ""); //传入资源对象,以及访问的rawfile文件夹名称
440                    console.log("rawfilelist" + rawfilelist);
441                    let rawfileContet = testNapi.getRawFileContent(this.resmgr, "rawfile1.txt");
442                    console.log("rawfileContet" + rawfileContet);
443                    let rawfileDescriptor = testNapi.getRawFileDescriptor(this.resmgr, "rawfile1.txt");
444                    console.log("getRawFileDescriptor" + rawfileDescriptor.fd, rawfileDescriptor.offset, rawfileDescriptor.length);
445                    let ret = testNapi.isRawDir(this.resmgr, "rawfile1.txt");
446                })
447            }
448            .width('100%')
449            }
450            .height('100%')
451        }
452    }
453    ```
454
455## 相关实例
456
457针对资源管理Rawfile开发,有以下相关实例可供参考:
458
459- [获取Rawfile资源(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Native/NdkRawfile)
460