val start = System.currentTimeMillis()
RandomAccessFile("D:\\hello.mp4", "r").use { input ->
RandomAccessFile("D:\\hello_copy.mp4", "rw").use { output ->
val buf = ByteArray(8192)
var length: Int
while (input.read(buf).also { length = it } != -1) {
output.write(buf, 0, length)
}
}
}
println("复制完成,用时:${System.currentTimeMillis() - start}")
运行效果如下:
复制完成,用时:288
经过多次运行,发现经常到跑到300以下,所以RandomAccessFile的效率还是非常高的,似乎比FileInputStream
和FileOutputStream
的效率还要高一点点。
但是在写文件的时候需要注意,如果使用的读写模式为:“rws”,如下:
RandomAccessFile("D:\\hello.mp4", "r").use { input ->
RandomAccessFile("D:\\hello_copy.mp4", "rws").use { output ->
。。。
}
}
运行效果如下:
复制完成,用时:3148
可以看到,读写模式加了s之后效率非常的低,比原来慢10倍都不止。对于s参数,官方文档说明如下:
public RandomAccessFile(File file, String mode) throws FileNotFoundException
创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。将创建一个新的 FileDescriptor 对象来表示此文件的连接。
mode 参数指定用以打开文件的访问模式。允许的值及其含意为:
| 值 | 含义 |
| :-: | :-- |
| “r” | 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。 |
| “rw” | 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。 |
| “rws” | 打开以便读取和写入,对于 “rw”,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。 |
| “rwd” | 打开以便读取和写入,对于 “rw”,还要求对文件内容的每个更新都同步写入到底层存储设备。 |
“rws” 和 “rwd” 模式的工作方式极其类似 FileChannel 类的 force(boolean) 方法,分别传递 true 和 false 参数,除非它们始终应用于每个 I/O 操作,并因此通常更为高效。如果该文件位于本地存储设备上,那么当返回此类的一个方法的调用时,可以保证由该调用对此文件所做的所有更改均被写入该设备。这对确保在系统崩溃时不会丢失重要信息特别有用。如果该文件不在本地设备上,则无法提供这样的保证。
“rwd” 模式可用于减少执行的 I/O 操作数量。使用 “rwd” 仅要求更新要写入存储的文件的内容;使用 “rws” 要求更新要写入的文件内容及其元数据,这通常要求至少一个以上的低级别 I/O 操作。
如果存在安全管理器,则使用 file 参数的路径名作为其参数调用它的 checkRead 方法,以查看是否允许对该文件进行读取访问。如果该模式允许写入,那么还使用该路径参数调用该安全管理器的 checkWrite 方法,以查看是否允许对该文件进行写入访问。
当我们需要非常即时的写入内容的时候,就需要使用"rws"模式,因为"rw"模式会使用buffer,只有buffer满的时候,或者调用close()函数的时候才真正写到文件,而使用"rws"则不使用buffer,可以即时写到文件,因为不使用buffer,所以效率就低下。这是网上的说法,根据我的实验,我发现即使写一个字节,也是可以即时写出去的,说明没有使用Buffer,示例代码如下:
val start = System.currentTimeMillis()
val file = File("D:\\test\\test.txt")
val output = RandomAccessFile(file, "rw")
val input = RandomAccessFile(file, "r")
output.write(65)
println("读取一个字节:${input.read()}")
Thread.sleep(1000 * 30)
output.close()
input.close()
println("写入完成,用时:${System.currentTimeMillis() - start}")
运行结果如下:
读取一个字节:65
可以看到,写入一个字节后,立马读就能读取到写入文件的字节内容,而且我们只写了一个字节,说明RandomAccessFile
没有使用Buffer,即使是1个字节也立马写入到文件了,而且我打开文件看也是能看到字母“A”的(A的ASCCI码为65),而此RandomAccessFile
对象也还没有关闭呢。这也有可能是在Windows平台没有Buffer,万一Linux平台有呢?于是跑到我的Android手机上再试一次,把代码改一下,放到Activity中运行,如下:
thread {
val start = System.currentTimeMillis()
val file = File(filesDir,"test.txt")
val output = RandomAccessFile(file, "rw")
val input = RandomAccessFile(file, "r")
output.write(65)
println("读取一个字节:${input.read()}")
output.close()
input.close()
Thread.sleep(1000 * 30)
println("写入完成,用时:${System.currentTimeMillis() - start}")
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
最后
我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了5、6年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。
其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。
不断奔跑,你就知道学习的意义所在!
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
!
[外链图片转存中…(img-tX8CPFnt-1712865387616)]
[外链图片转存中…(img-JS9i6hwe-1712865387616)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-GT7fDHBg-1712865387616)]