Java 从入门到进阶之路(二十九)
在之前的文章我们已经可以对本地对文件和目录进行新建和删除等操作,接下来我们来对文件内对具体内容进行操作。
如下代码,我们实现了一个基本的文件写入:
/**
* java.io.RandomAccessFile
* 用来读写文件数据
* RAF是基于指针进行读写的,即RAF总是在指针指向的位置读写字节,
* 并且读写后指针会自动向后移动
* RAF既可以读取文件数据也可以向文件中写入数据
*
* @author wjt
*/
public class RandomAccessFileDemo1 {
public static void main(String[] args) throws IOException {
/**
* RandomAccessFile(String path, String mode)
* RandomAccessFile(File file, String mode)
* 第二个参数为模式:常用对有 r:只读模式 rw:读写模式
*/
RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
/**
* void write(int d)
* 写出给定的int值对应的2进制的低八位
* 00000000 00000000 00000000 00000001
*/
raf.write(1); //
System.out.println("写出完毕!");
raf.close(); }
}
在上面的代码中我们可以看出文件的读写想要到 RandomAccessFile,这里需要注意的是要抛出异常,否则编译器会报错,同时我们用到了它的一个 write() 方法来进行文件写入,接收的是一个2进制的低八位数值,假如我们写入 raf.write(97),那么就会被准化为小写字母 a。
既然能读,那就能写,接下来我们将上面写入的 1 再读取出来
/**
* 读取文件数据
*
* @author wjt
*/
public class RandomAccessFileDemo2 {
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile("raf.txt", "r");
/**
* int read()
* 读取一个字节,并以10进制的int型返回
* 若返回值为-1,则表示读取到了文件的末尾
*/
int d = raf.read();
System.out.println(d); //
raf.close();
}
}
接下来我们再来看一下如何对文件进行复制
/**
* 复制文件
*
* @author wjt
*/
public class RandomAccessFileDemo3 {
public static void main(String[] args) throws IOException {
/**
* 创建一个RAF读取原文件,
* 再创建一个RAF向目标文件中写出,
* 顺序从原文件中读取每一个字节并
* 写入到目标文件中即可
*/
// 原文件,在原文件中随便写一些内容
RandomAccessFile src = new RandomAccessFile("raf.txt", "r");
// 目标文件
RandomAccessFile desc = new RandomAccessFile("raf1.txt", "rw");
// 用来保存读取到每个字节
int d = -1;
long start = System.currentTimeMillis();
while ((d = src.read()) != -1) {
desc.write(d);
}
long end = System.currentTimeMillis();
System.out.println("复制完毕!耗时:" + (end - start) + "ms"); // 复制完毕!耗时:2ms
}
}
通过上面的代码我们可以实现文件的复制,但是这样复制是比较耗时的,不如在电脑上直接复制粘贴来的快。因为这是一个从硬盘读取到内存中再写到硬盘的过程,频繁的一个字节一个字节的读取频繁地调用这个过程,所以会很慢。
如果我们不是一个字节一个字节读写,而是一组一组的读写就会提升效率,如下:
/**
* 若向提高读写效率,
* 可以通过提高每次读写的数据量来减少读写次数达到
*
* @author wjt
*/
public class RandomAccessFileDemo4 {
public static void main(String[] args) throws IOException {
RandomAccessFile src = new RandomAccessFile("raf.txt", "r");
RandomAccessFile desc = new RandomAccessFile("raf1.txt", "rw");
/**
* int read(byte[] data)
* 一次性尝试读取给定的字节数组总长度的字节量并存入到该数组中,
* 返回值为实际读取到的字节量,
* 若返回值为-1,则表示本次没有读取到任何数据(文件末尾)
*/
// 10K
byte[] buf = new byte[1024 * 10];
// 用来保存读取到每个字节
int len = -1;
long start = System.currentTimeMillis();
while ((len = src.read(buf)) != -1) {
/**
* void write(buf)
* 一次性将给定的字节数组中的所有数据写入
* void write(byte[] d, int start, int end)
* 将所给定数组中从小表start处开始的len个字节一次性写出
*/
desc.write(buf, 0, len);
}
long end = System.currentTimeMillis();
System.out.println("复制完毕!耗时:" + (end - start) + "ms"); // 复制完毕!耗时:1ms
}
}
在上面的代码中,我们定义了一个 byte 数组来每次读写 10K 的方式进行批量复制,会发现时间变短了,需要注意的是 write() 方法需要使用重载的方法,因为最后一次可能会写入多余的数组len。
我们知道 write() 方法其实写入的是数据的低八位,那我们想要写入不同的数据类型该怎么写呢?如下代码:
/**
* RAF还提供了方便读写基本类型数据的方法
*
* @author wjt
*/
public class RandomAccessFileDemo5 {
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
/**
* 向文件中写入一个int最大值
* Integer.MAX_VALUE 的二进制位
* 011111111 11111111 11111111 11111111
* 文件写入为二进制的低八位,如果我们直接写入的话
* 其实写入的是低八位的 11111111,显然是错误的
* 我们可以通过位移的方式连续写四次来进行写入操作
*/
int max = Integer.MAX_VALUE; raf.write(max >>> 24); //
raf.write(max >>> 16); //
raf.write(max >>> 8); //
raf.write(max); // 11111111 // RAF 其实提供了更方便的方法来进行不同类型数据的写入
raf.writeInt(max);
raf.writeDouble(11.11);
raf.writeLong(1234L);
raf.close();
}
}
从上面的代码中我们可以通过位移的方式按顺序每次写入一个int值的八位,写四次正好是一个int值的四个字节,当然我们我们也可以用提供好的 writeInt() 方法来直接写入,其底层代码远离其实也是用到了位移的思想,如下源码:
Java 从入门到进阶之路(二十九)的更多相关文章
- Java 从入门到进阶之路(十九)
在之前的文章我们介绍了一下 Java 中的Object,本章我们来看一下 Java 中的包装类. 在 Java 中有八个基本类型:byte,short,int,long,float,double,ch ...
- Java 从入门到进阶之路(十二)
在之前的文章我们介绍了一下 Java 类的重写及与重载的区别,本章我们来看一下 Java 类的 private,static,final. 我们在之前引入 Java 类概念的时候是通过商场收银台来引入 ...
- Java 从入门到进阶之路(十八)
在之前的文章我们介绍了一下 Java 中的正则表达式,本章我们来看一下 Java 中的 Object. 在日常生活中,任何事物我们都可以看做是一个对象,在编程中是同样的道理,在 Java 编程中其实更 ...
- Java 从入门到进阶之路(十)
之前的文章我们介绍了一下 Java 中的引用型数组类型,接下来我们再来看一下 Java 中的继承. 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继 ...
- Java 从入门到进阶之路(十五)
在之前的文章我们介绍了一下 Java 中的接口,本章我们来看一下 Java 中类的多态. 在日常生活中,很多意思并不是我们想要的意思,如下: 1.领导:“你这是什么意思?” 小明:“没什么意思,意思意 ...
- Java 从入门到进阶之路(十四)
在之前的文章我们介绍了一下 Java 中的抽象类和抽象方法,本章我们来看一下 Java 中的接口. 在日常生活中,我们会接触到很多类似接口的问题,比如 USB 接口,我们在电脑上插鼠标,键盘,U盘的时 ...
- Java 从入门到进阶之路(十六)
在之前的文章我们介绍了一下 Java 中类的多态,本章我们来看一下 Java 中类的内部类. 在 Java 中,内部类分为成员内部类和匿名内部类. 我们先来看一下成员内部类: 1.类中套类,外面的叫外 ...
- Java 从入门到进阶之路(二十)
在之前的文章我们介绍了一下 Java 中的包装类,本章我们来看一下 Java 中的日期操作. 在我们日常编程中,日期使我们非常常用的一个操作,比如读写日期,输出日志等,那接下来我们就看一下 Java ...
- Java 从入门到进阶之路(二十三)
在之前的文章我们介绍了一下 Java 中的 集合框架中的Collection 的迭代器 Iterator,本章我们来看一下 Java 集合框架中的Collection 的泛型. 在讲泛型之前我们先来 ...
- Java 从入门到进阶之路(二)
之前的文章我们介绍了一下用 IDEA 编辑器创建一个 Java 项目并输出 HelloWorld,本章我们来看一下 Java 中的变量和基本数据类型. 在这之前我们先来看一下 Java 中的关键字,这 ...
随机推荐
- Java中线程的操作状态
start() 线程开始运行 sleep() 当前线程暂停休息 括号里面是多长时间以毫秒为单位 wait() 当前线程等待 notify() 线程wait后用这个方法唤醒 notifyAll() 把所 ...
- Java实现埃拉托色尼筛选法
1 问题描述 Compute the Greatest Common Divisor of Two Integers using Sieve of Eratosthenes. 翻译:使用埃拉托色尼筛选 ...
- Java实现找零问题
1 问题描述 现需找零金额为n,则最少需要用多少面值为d1 < d2 < d3 < - < dm的硬币?(PS:假设这m种面值d1 < d2 < d3 < - ...
- java代码(8) ---guava字符串工具
guava字符串工具 一.Joiner 根据指定的分隔符把字符串连接在一起,MapJoiner执行相同的操作,但是针对Map的key和value 分析源码可知:该类构造方法被private修饰,无法直 ...
- Mac 制作 Linux 启动盘
本文原始地址:https://sitoi.cn/posts/28583.html 前期准备 一个 Mac 电脑 一个 U 盘(8GB 以上) 下载好 Linux 系统镜像(iso 文件) 具体步骤 挂 ...
- 数据结构&算法
20个最常用.最基础数据结构与算法: 10个数据结构:数组.链表.栈.队列.散列表.二叉树.堆.跳表.图.Trie 树. 10个 算法 :递归.排序.二分查找.搜索.哈希.贪心.分治.回溯. ...
- .NET Core SDKs installed: No SDKs were found.
问题描述 今天vs2019创建了asp.net core项目,发现无法加载项目.尝试打开之前的.net core项目项目,同样无法加载项目. 打开cmd,输入 dotnet ,提示 .NET Core ...
- 制作sentinel docker镜像
在sentinel官方下载jar包即可运行,但是在部署的时候一个一个的启动jar包很不方便,制作成镜像方便部署和管理. 1)直接运行 # 修改端口号,默认是8080 java -jar sentine ...
- @loj - 3043@「ZJOI2019」线段树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 九条可怜是一个喜欢数据结构的女孩子,在常见的数据结构中,可怜最喜 ...
- MySQL数据库基础知识复习
现在是2020年寒假,这也是新年写的第一篇博客,用了十几天的时间自学了数据库基础部分,想总结一下得失同时并通过写博客来复习前面学的知识点. 个人: 1.本来是计划一周学完基础部分的178p但没能完成这 ...