鸿蒙开发实例|分布式文件服务

简介: 鸿蒙开发实例|分布式文件服务

Harmony OS应用数据管理不仅支持单设备的各种结构化数据的持久化,还支持跨设备之间数据的同步、共享及搜索功能,因此,开发者基于Harmony OS应用数据管理功能,能实现应用程序数据在不同终端设备之间的无缝衔接,从而保证用户在跨设备使用数据时所用数据的一致性。

在正式讲解HarmonyOS中的分布式文件服务之前,先简单介绍一下相关概念。


01、分布式文件系统(Distributed File System,DFS)


通过计算机网络将分布在不同地点的节点相连,利用网络进行节点间的通信和数据传输,从而将固定于某个地点的某个文件系统,扩展到任意多个地点/文件系统,众多的节点组成的文件系统网络即为分布式系统。简单来讲,DFS为分布在网络上任意位置的资源提供一个逻辑上的树形文件系统结构,从而使用户访问分布在网络上的共享文件更加简便。分布式文件系统的突出优点就是可以屏蔽文件系统的物理位置,人们在使用分布式文件系统时,无须关心数据是存储在哪个节点上或者是从哪个节点获取的,而只需像使用本地文件系统一样管理和存储文件系统中的数据。


此外,分布式文件系统还包括以下特点:

冗余性: 分布式文件系统可以提供冗余备份,当系统中某些节点出错时,整体文件服务不会停止,还能继续为用户提供服务,具有较高的容错性。

安全性: 分布式文件系统的安全性离不开其冗余性,当出现故障的节点存储的数据损坏时可以由其他节点进行数据恢复。此外,在分布式文件系统中,大量数据被分散到不同的节点上进行存储,数据丢失的风险大大减小。

扩展性: 分布式文件系统可以通过网络连接将大量的计算机连接到一起,任何计算机只需经过简单的配置就可以加入分布式文件系统中。


02、分布式文件


分布式文件是指依赖于分布式文件系统并分散存储在多个用户设备上的文件,应用间的分布式文件目录互相隔离,不同应用的文件不能互相访问。


03、文件元数据


文件元数据是用于描述文件特征的数据,包含文件名、文件大小、创建、访问、修改时间等信息。


在HarmonyOS中,分布式文件服务支持用户设备中的应用程序在同一账号下多设备之间进行文件共享。即应用程序可以屏蔽文件具体的存储位置,在多个设备之间无障碍访问文件。HarmonyOS中分布式文件服务的运作机制如图1所示。

image.png

■ 图1 Harmony OS中分布式文件服务的运作机制


从图1可以看出,在HarmonyOS中,分布式文件服务采用无中心节点的设计,每个设备都存储一份全量的文件元数据和本设备上产生的分布式文件,元数据在多台设备间互相同步,当应用需要访问分布式文件时,分布式文件服务首先查询本设备上的文件元数据,获取文件所在的存储设备,然后对存储设备上的分布式文件服务发起文件访问请求,将文件内容读取到本地。


实际上,在HarmonyOS中实现分布式文件服务前,需要满足以下条件:

(1) 应用程序如需使用分布式文件服务完整功能,需要申请分布式数据管理权限,具体地,申请ohos.permission.DISTRIBUTED_DATASYNC权限,从而允许不同设备间的数据交换。

(2) 要实现分布式共享文件,则多个设备需登录同一个华为账号,打开蓝牙设备,连接同一个WLAN 局域网。

(3) 存在多设备并写的场景,为了避免冲突,开发者需要对文件加锁保护,保证文件独享。非持锁情况下,并发写冲突时,后一次会覆盖前一次。

(4) 应用访问分布式文件时,文件所在设备不能离线,否则文件不能访问。

(5) 当网络情况较差时,访问存储在远端的分布式文件可能会长时间得不到响应甚至响应失败,因此需要应用考虑到对这种场景的处理。

(6) 当两台设备有同名文件时,如果元数据进行同步则会产生冲突,分布式文件服务会根据时间戳将文件按创建的先后顺序重命名,因此,为避免此类场景出现,应用在文件名上可以进行相应设备区分,例如,deviceID+时间戳。


下面通过一个实例学习如何在HarmonyOS中具体实现多设备间的文件共享。实例实现了在两个手机设备上进行分布式时间读写的功能,即在手机A 上单击写入Button,将当前时间写入分布式文档。在手机B上单击读取Button,可以从分布式文档中获取手机A 中写入的时间,反之亦然。需要注意的是,两个手机设备需要登录同一个华为账号,故需要开启多设备协同权限。


首先,创建Phone设备下的Java模板新项目,打开项目目录下的MainAbilitySclice.java文件,在onStart()方法中声明布局,代码如下:


DirectionalLayout directionLayout= new DirectionalLayout(this);
directionLayout.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
directionLayout.setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);
directionLayout.setOrientation(Component.VERTICAL);
directionLayout.setPadding(32, 32, 32, 32);

在布局中添加Text组件用以显示提示信息及读取到的时间,代码如下:


Text text= new Text(this);
text.setText("初始文本"); //设置初始显示文本
text.setTextSize(50);
DirectionalLayout.LayoutConfig layoutConfig = newDirectionalLayout.LayoutConfig (ComponentContainer.LayoutConfig.MATCH_CONTENT,ComponentContainer.LayoutConfig.MATCH_CONTENT);
layoutConfig.alignment = LayoutAlignment.HORIZONTAL_CENTER;
text.setLayoutConfig(layoutConfig);
directionLayout.addComponent(text);

在本例中两个设备通过各自的Button组件实现时间的读写,因此,需要添加两个Button组件,首先添加写入时间的Button组件,代码如下:


//实现写入功能的Button,用来读取当前时间,并写入分布式文档中
Button button1 = new Button(this);
layoutConfig.setMargins(0, 50,0,0);
button1.setLayoutConfig(layoutConfig);
button1.setText("写入现在时间");
button1.setTextSize(50);
ShapeElement background1 = new ShapeElement();
background1.setRgbColor(new RgbColor(0xFF51A8DD));
background1.setCornerRadius(25);
button1.setBackground(background1);
button1.setPadding(10, 10, 10, 10);
button1.setClickedListener(new Component.ClickedListener() {
      @Override
      public void onClick(Component Component) {
           goWrite(text); //单击Button,实现写入功能
      }
});
directionLayout.addComponent(button1);


添加读取时间的Button组件,代码如下:


//实现读取功能的Button,从分布式文档中读取已经写入的时间
Button button2 = new Button(this);
layoutConfig.setMargins(0, 50,0,0);
button2.setLayoutConfig(layoutConfig);
button2.setText("读取上一个时间");
button2.setTextSize(50);
ShapeElement background2 = new ShapeElement();
background2.setRgbColor(new RgbColor(0xFF5100DD));
background2.setCornerRadius(25);
button2.setBackground(background1);
button2.setPadding(10, 10, 10, 10);
button2.setClickedListener(new Component.ClickedListener() {
      @Override
//单击Button,实现读取功能
      public void onClick(Component Component) {
           goRead(text);
      }
});
directionLayout.addComponent(button2);


写入功能是由goWrite()方法实现的,分析其实现过程,代码如下:


//goWrite():写入button1的onClick事件执行的方法
private void goWrite(Text text) {
     String sharedFileName = sharedFileName(this); //获取分布式文件路径
     SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     String str=simpleDateFormat.format(new Date().getTime()); //获取时间戳并转换成标准形式
//将时间写入分布式文件
     try{
          FileWriter fileWriter = new FileWriter(sharedFileName,false);
          fileWriter.write(str);
          fileWriter.close();
     } catch (IOException e) {
            e.printStackTrace();
     }
     text.setText("写入的时间:"+str); text.invalidate();
}

读取功能是由goRead()方法实现的,其实现过程代码如下:


//goRead():读取button2的onClick事件执行的方法
private void goRead(Text text) {
     String sharedFileName = sharedFileName(this); //获取分布式文件路径
  //读取分布式文件中的数据,若读到则输出,若没读到则输出没读到
     try{
            FileReader fileReader = new FileReader(sharedFileName);
            BufferedReader br = new BufferedReader(fileReader);
            String b = br.readLine();
            text.setText("读取到的上一个写入的时间:"+b);
            text.invalidate();
            fileReader.close();
        } catch (IOException e) {
            e.printStackTrace();
            text.setText("没读到");
            text.invalidate();
        }
}


二者都是通过shareFileName()方法获取分布式文件路径的,代码如下:


File distDir = context.getDistributedDir(); //获取分布式文件目录
     //在分布式文件目录下新建一个名为note.txt的文件,读写都在这个文件中进行
     String filePath = distDir+File.separator+"note.txt";
     return filePath; //返回新建文件的路径
}

需要说明的是,利用Context.getDistributedDir()接口可以获取属于自己的分布式目录,然后通过libc或JDK 接口,可以在该目录下创建、删除、读写文件或目录。本例中在所获取的分布式目录下创建了一个读写文件note.txt。


基于两个手机设备进行验证,在开始功能验证之前,两个手机需要登录同一个华为账号,并且需要开启多设备协同权限且开启多设备协同连接。具体的设置过程可参考前面对多设备协同权限设置的介绍。


设置完成后进行功能验证。首先,在未写入的情况下直接进行读取,读取结果如图2所示,未写入的情况下读取内容为空。

image.png

■ 图2 未写入情况下直接进行读取


由Phone A 写入当前时间,Phone B读取当前时间,读写效果如图3所示。

image.png


■ 图3 Phone A写入当前时间,Phone B读取A写入的时间


由Phone B 写入当前时间,Phone A 进行读取时,读写效果如图4 所示。

image.png

■ 图4 Phone B写入当前时间,Phone A读取B写入的时间


至此,分布式文件服务功能成功实现。


目录
打赏
0
0
0
0
1035
分享
相关文章
|
28天前
|
鸿蒙开发:资讯项目实战之项目初始化搭建
目前来说,我们的资讯项目只是往前迈了很小的一步,仅仅实现了项目创建,步虽小,但概念性的知识很多,这也是这个项目的初衷,让大家不仅仅可以掌握日常的技术开发,也能让大家理解实际的项目开发知识。
鸿蒙开发:资讯项目实战之项目初始化搭建
鸿蒙开发:基于最新API,如何实现组件化运行
手动只是让大家了解切换的原理,在实际开发中,可不推荐手动,下篇文章,我们将通过脚本或者插件,快速实现组件化模块之间的切换,实现独立运行,敬请期待!
鸿蒙开发:基于最新API,如何实现组件化运行
鸿蒙5开发宝藏案例分享---优化应用时延问题
鸿蒙性能优化指南来了!从UI渲染到数据库操作,6大实战案例助你提升应用流畅度。布局层级优化、数据加载并发、数据库查询提速、相机资源延迟释放、手势识别灵敏调整及转场动画精调,全面覆盖性能痛点。附赠性能自检清单,帮助开发者高效定位问题,让应用运行如飞!来自华为官方文档的精华内容,建议收藏并反复研读,共同探讨更多优化技巧。
鸿蒙5开发宝藏案例分享---Swiper组件性能优化实战
本文分享了鸿蒙系统中Swiper组件的性能优化技巧,包括:1) 使用`LazyForEach`替代`ForEach`实现懒加载,显著降低内存占用;2) 通过`cachedCount`精准控制缓存数量,平衡流畅度与内存消耗;3) 利用`onAnimationStart`在抛滑时提前加载资源,提升构建效率;4) 添加`@Reusable`装饰器复用组件实例,减少创建开销。实际应用后,图库页帧率从45fps提升至58fps,效果显著。适合处理复杂列表或轮播场景,欢迎交流经验!
鸿蒙5开发宝藏案例分享---Web开发优化案例分享
本文深入解读鸿蒙官方文档中的 `ArkWeb` 性能优化技巧,从预启动进程到预渲染,涵盖预下载、预连接、预取POST等八大优化策略。通过代码示例详解如何提升Web页面加载速度,助你打造流畅的HarmonyOS应用体验。内容实用,按需选用,让H5页面快到飞起!
鸿蒙5开发宝藏案例分享---优化应用包体积大小问题
本文分享了鸿蒙应用包体积优化的实用技巧,包括SO库压缩、HSP动态共享包、OHPM依赖冲突解决、按需加载和扫描工具定位优化点等方法。通过具体配置示例和实战经验,如启用`compressNativeLibs`、使用共享资源包、强制统一依赖版本以及动态导入功能模块,帮助开发者显著减少包体积,提升用户体验。文中还提供了图标优化、资源混淆和无用代码剔除等补充建议,助力打造更轻量的鸿蒙应用。
鸿蒙5开发宝藏案例分享---Grid性能优化案例
本文深入探讨了鸿蒙系统中Grid组件性能优化的实战技巧,针对Grid加载慢、滚动卡顿的问题,提出用GridLayoutOptions替代columnStart/columnEnd的方法。通过预定义不规则项索引,将位置计算复杂度从O(n)降至O(1),大幅提升性能(如scrollToIndex耗时从447ms降至12ms)。文章结合代码示例与Profiler数据分析,总结最佳实践,帮助开发者优化应用流畅度。
鸿蒙5开发宝藏案例分享---瀑布流优化实战分享
本文基于鸿蒙官方瀑布流优化案例,分享了瀑布流性能优化的实战经验。分析了导致卡顿的三大原因:一次性渲染、动态高度与组件重建,并提供了四大优化方案——懒加载+缓存池、组件复用、动态预加载及固定高度计算。通过实测对比,优化后内存占用降低至98MB,滑动FPS提升至60帧。最后总结避坑指南,帮助开发者解决图片加载、布局嵌套和视频处理等常见问题,实现流畅体验。
鸿蒙5开发宝藏案例分享---长列表性能优化解析
鸿蒙长列表性能优化全揭秘!通过五大实战技巧(LazyForEach懒加载、cachedCount缓存、Prefetcher动态预加载、@Reusable组件复用及布局优化),有效解决卡顿、白块和高内存问题。万条数据测试显示,首屏加载提速77%,滑动零丢帧,内存占用降低86%。针对不同数据量场景提供避坑指南,助你开发流畅的HarmonyOS应用!
鸿蒙5开发宝藏案例分享---冷启动优化案例分享
本文揭秘鸿蒙应用冷启动优化技巧,基于官方文档实战案例,助你效率翻倍!冷启动指应用从无进程状态新建,超1100ms易卡顿。文中拆解冷启动全流程为5阶段,并分享6大优化方案:异步处理耗时任务、启动图标分辨率优化、按需导入模块、网络请求前置、避免嵌套导出及首页数据缓存。同时提供避坑指南与总结,强调异步优先、延迟加载和本地缓存三大法则,优化后冷启动速度提升300%以上。附详细代码解析,助力性能优化!
AI助理
登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问

你好,我是AI助理

可以解答问题、推荐解决方案等