## 解析大文件xml发生内存溢出（Out of Memory）

由于ArkTS侧提供的XML解析接口暂不支持流式解析模式，建议通过Native工程调用第三方C/C++库来实现。推荐使用**libxml2**库，该库具有成熟稳定、性能优越的特点，能够支持SAX等流式解析方式，有效降低内存占用。

具体实施步骤如下：

1. **创建Native工程**：在HarmonyOS项目中创建C++模块。
2. **集成libxml2**：下载并配置libxml2库源码或预编译库，在CMakeLists.txt中进行引用。
3. **编写解析代码**：使用libxml2提供的API实现流式解析逻辑。
4. **XML对象处理**：当XML文件大小超过100MB时，建议在Native侧处理。

关于如何在ArkTS侧引用编译生成的三方so库，请参考文档：[如何在ArkTS侧引用其他三方so库](https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs/faqs-ndk-21)。

libxml2库支持的回调函数主要如下所示：

展开

| 回调函数指针 | 触发时机 | 用途 |
| --- | --- | --- |
| startDocument | 文档开始时 | 初始化环境，分配资源。 |
| endDocument | 文档结束时 | 释放资源，打印统计信息。 |
| startElement | 读到开始标签（如<tag>） | 获取标签名及其属性。 |
| endElement | 读到结束标签（如</tag>） | 处理标签结束逻辑，如出栈。 |
| characters | 读到标签间的文本内容 | 处理文本数据（注意可能被多次调用）。 |

代码示例：

收起

自动换行

深色代码主题

复制

```
1. // 用户自定义数据
2. ParseContext context;

4. // 初始化SAX Handler结构体
5. xmlSAXHandler SAXHandler = { 0 };

7. // 绑定回调函数，用于在解析过程中处理XML数据
8. SAXHandler.startDocument = startDocument;
9. SAXHandler.endDocument = endDocument;
10. SAXHandler.startElement = startElement;
11. SAXHandler.endElement = endElement;
12. SAXHandler.characters = characters;

14. // 解析文件
15. // 用户自定义数据指针
16. int ret = xmlSAXUserParseFile(&SAXHandler, &context, xmlFileName);

18. if (ret != 0) {
19. printf("Failed to parse XML file.\n");
20. return 1;
21. }

23. // 清理libxml2全局状态
24. xmlCleanupParser();
```

## 定时器被误删除

由于定时器ID为进程共享，是从0开始的，开发者误操作容易导致定时器被删除。

例如以下场景：

收起

自动换行

深色代码主题

复制

```
1. export class testClass {
2. // 初始值设置为0
3. private timeoutId: number = 0;
4. private intervalId: number = 0;

6. // 在某些情况下没有调用setTimeout设置定时器就调用了clearAnimation函数删除了定时器，就会导致timeoutId为0的定时器被删除
7. clearAnimation(): void {
8. clearInterval(this.intervalId);
9. clearTimeout(this.timeoutId);
10. }
11. }
```

可以通过以下方法快速定位：

重写globalThis.clearTimeout函数，实现在调用clearTimeout函数时打印调用栈，快速定位定时器是在哪里被删除的。

调用顺序为先调用clearTimeout.ts文件中的test()函数，再调用TimerTest.ets文件中testClass类的clearAnimation()函数。

示例代码：

收起

自动换行

深色代码主题

复制

```
1. // 自定义TS文件clearTimeout.ts

3. // test函数需要在程序调用clearTimeout函数之前调用
4. export function test() {
5. // 完全兼容原始 clearTimeout 类型
6. const origClear = globalThis.clearTimeout;
7. globalThis.clearTimeout = (...args: any[]) => {
8. const timeoutId = args[0];

10. // 检查所有可能的 timerId = 0 的情况
11. if (timeoutId === 0 || timeoutId === "0") {
12. console.info("清除 timerId = 0 !", new Error().stack);
13. // 触发断点
14. debugger;
15. }

17. // 使用 apply 确保正确传递所有参数
18. return origClear.apply(this, args);
19. }
20. }
```

收起

自动换行

深色代码主题

复制

```
1. // 自定义ets文件TimerTest.ets

3. export class testClass {
4. // 初始值设置为0
5. private timeoutId: number = 0;
6. private intervalId: number = 0;

8. // 在某些情况下没有调用setTimeout设置定时器就调用了clearAnimation函数删除了定时器，就会导致timeoutId为0的定时器被删除
9. clearAnimation(): void {
10. clearInterval(this.intervalId);
11. clearTimeout(this.timeoutId);
12. }
13. }
```

收起

自动换行

深色代码主题

复制

```
1. import { test } from './clearTimeout';
2. import { testClass } from './TimerTest';

4. @Entry
5. @Component
6. struct Index {
7. @State message: string = 'Hello World';

9. build() {
10. Row() {
11. Column() {
12. Text(this.message)
13. .fontSize(50)
14. .fontWeight(FontWeight.Bold)
15. .onClick(() => {
16. test();
17. let testCase = new testClass();
18. testCase.clearAnimation();
19. this.message = 'success';
20. })
21. }
22. .width('100%')
23. }
24. .height('100%')
25. }
26. }
```