在之前的文章我们已经可以对本地对文件和目录进行新建和删除等操作,接下来我们来对文件内对具体内容进行操作。

如下代码,我们实现了一个基本的文件写入:

 /**
* 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 从入门到进阶之路(二十九)的更多相关文章

  1. Java 从入门到进阶之路(十九)

    在之前的文章我们介绍了一下 Java 中的Object,本章我们来看一下 Java 中的包装类. 在 Java 中有八个基本类型:byte,short,int,long,float,double,ch ...

  2. Java 从入门到进阶之路(十二)

    在之前的文章我们介绍了一下 Java 类的重写及与重载的区别,本章我们来看一下 Java 类的 private,static,final. 我们在之前引入 Java 类概念的时候是通过商场收银台来引入 ...

  3. Java 从入门到进阶之路(十八)

    在之前的文章我们介绍了一下 Java 中的正则表达式,本章我们来看一下 Java 中的 Object. 在日常生活中,任何事物我们都可以看做是一个对象,在编程中是同样的道理,在 Java 编程中其实更 ...

  4. Java 从入门到进阶之路(十)

    之前的文章我们介绍了一下 Java 中的引用型数组类型,接下来我们再来看一下 Java 中的继承. 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继 ...

  5. Java 从入门到进阶之路(十五)

    在之前的文章我们介绍了一下 Java 中的接口,本章我们来看一下 Java 中类的多态. 在日常生活中,很多意思并不是我们想要的意思,如下: 1.领导:“你这是什么意思?” 小明:“没什么意思,意思意 ...

  6. Java 从入门到进阶之路(十四)

    在之前的文章我们介绍了一下 Java 中的抽象类和抽象方法,本章我们来看一下 Java 中的接口. 在日常生活中,我们会接触到很多类似接口的问题,比如 USB 接口,我们在电脑上插鼠标,键盘,U盘的时 ...

  7. Java 从入门到进阶之路(十六)

    在之前的文章我们介绍了一下 Java 中类的多态,本章我们来看一下 Java 中类的内部类. 在 Java 中,内部类分为成员内部类和匿名内部类. 我们先来看一下成员内部类: 1.类中套类,外面的叫外 ...

  8. Java 从入门到进阶之路(二十)

    在之前的文章我们介绍了一下 Java 中的包装类,本章我们来看一下 Java 中的日期操作. 在我们日常编程中,日期使我们非常常用的一个操作,比如读写日期,输出日志等,那接下来我们就看一下 Java ...

  9. Java 从入门到进阶之路(二十三)

    在之前的文章我们介绍了一下 Java 中的  集合框架中的Collection 的迭代器 Iterator,本章我们来看一下 Java 集合框架中的Collection 的泛型. 在讲泛型之前我们先来 ...

  10. Java 从入门到进阶之路(二)

    之前的文章我们介绍了一下用 IDEA 编辑器创建一个 Java 项目并输出 HelloWorld,本章我们来看一下 Java 中的变量和基本数据类型. 在这之前我们先来看一下 Java 中的关键字,这 ...

随机推荐

  1. Java实现 蓝桥杯VIP 算法训练 Hankson的趣味题

    问题描述 Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫Hankson.现 在,刚刚放学回家的Hankson 正在思考一个有趣的问题. 今天在课堂上,老师讲解了如 ...

  2. CSDN如何获得2020技术圈认证(新徽章哦)

    打开CSDN APP 然后登陆上就可以了 把这些看完了就可以了

  3. java实现 洛谷 P1464 Function

    import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.S ...

  4. STM32串口打印的那些知识

    常规打印方法 在STM32的应用中,我们常常对printf进行重定向的方式来把打印信息printf到我们的串口助手.在MDK环境中,我们常常使用MicroLIB+fputc的方式实现串口打印功能,即: ...

  5. harbor私有仓库安装

    准备环境 centos7.4 docker-ce 19.03.8 docker-compose version 1.18.0 harbor 版本: 1.7.5   一.安装dokcer # 安装依赖包 ...

  6. 一篇关于Android M以后权限介绍的不错的文章

    文章地址:http://www.jianshu.com/p/e1ab1a179fbb/

  7. Jupyter的搭建

    在家实在无聊,伏案沉思良久,忽然灵机一动,何不写写Python?然而电脑上的软件早已人是物非,Pycharm已然不复存在.但是又不想装软件找激活码,于是,只好建个Jupyter先凑合一下. 1. 安装 ...

  8. JavaScript常用项目(更新至19.11.17)

    目录 项目一:鼠标拖动方块 项目二:网页显示键入字母 项目三:实现滚播图 项目四:   本地数据记事本 项目一:鼠标拖动方块 代码: <!DOCTYPE html> <html> ...

  9. TensorFlow从0到1之TensorFlow实现多元线性回归(16)

    在 TensorFlow 实现简单线性回归的基础上,可通过在权重和占位符的声明中稍作修改来对相同的数据进行多元线性回归. 在多元线性回归的情况下,由于每个特征具有不同的值范围,归一化变得至关重要.这里 ...

  10. TensorFlow从0到1之TensorFlow损失函数(12)

    正如前面所讨论的,在回归中定义了损失函数或目标函数,其目的是找到使损失最小化的系数.本节将介绍如何在 TensorFlow 中定义损失函数,并根据问题选择合适的损失函数. 声明一个损失函数需要将系数定 ...