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实现 蓝桥杯VIP 算法提高 字符串比较
算法提高 字符串比较 时间限制:1.0s 内存限制:512.0MB 独立实现标准字符串库的strcmp函数,即字符串比较函数,从键盘输入两个字符串,按字典序比较大小,前者大于后者输出1,前者小于后者输 ...
- Java实现 LeetCode 80 删除排序数组中的重复项 II(二)
80. 删除排序数组中的重复项 II 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O ...
- Arrays.binarySearch和Collections.binarySearch的详细用法
概述 binarysearch为在指定数组中查找指定值得索引值,该值在范围内找得到则返回该值的索引值,找不到则返回该值的插入位置,如果该值大于指定范围最大值则返回-(maxlength+1),而: i ...
- Linux 源码包服务的管理
源码包安装服务的启动 使用绝对路径,调用启动脚本来启动.不同源码包的启动脚本不同,可以查看源码包的安装说明,查看启动脚本的方法 /usr/local/apache2/bin/apachectl sta ...
- 用户和用户组管理-影子文件shadow
ll /etc/shadow 由于shadow文件的权限,所以,只有root可以读 vi /etc/shadow 一共有九列信息: 第一列表示用户名:第二列表示经过加密之后的密码,如果密码是!!或者* ...
- python IDE pycharm的安装与使用
Python开发最牛逼的IDE——pycharm (其实其它的工具,例如eclipse也可以写,只不过比较麻烦,需要安装很多的插件,所以说pycharm是最牛逼的) pycharm,下载专业版的,不要 ...
- Centos7 安装 redis6 的部分问题总结
首先把redis.tar.gz 解压到你想要的路径 检查一下安装环境: yum -y install gcc yum -y install epel-release 执行 make 和 make in ...
- 【Java】利用反射执行Spring容器Bean指定的方法,支持多种参数自动调用
目录 使用情景 目的 实现方式 前提: 思路 核心类 测试方法 源码分享 使用情景 将定时任务录入数据库(这样做的好处是定时任务可视化,也可以动态修改各个任务的执行时间),通过反射执行对应的方法: 配 ...
- Java——选择、冒泡排序、折半查找
//选择排序对数据进行升序排序 public static void selectSortArray(int[] arr){ for(int i = 0; i<arr.length-1;i++) ...
- DML_Data Modification_MERGE
DML_8-Data Modification_MERGE (将Source表合并到Target) 语法:MERGE INTO 目标表USING 源表WHEN MATCHED AND ...