本章主要介绍两块内容,一个是读写文件的数据,另一个是文件(文件夹)的复制,昨天我主要给大家介绍了File类一些简单的操作方法,包括创建文件、介绍和学习了File文件的构造以及File类的获取和判断功能。
之前我们学的File类都是简单的一些操作,我们想在文件上写数据和读数据,那么怎么操作呢?今天聊的这个话题就是解决可以在文件上进行读写文件的数据,接下来,我将介绍一个类,叫做:RandomAccessFile,这个类是基于指针形式读写文件数据的。首先,我们来看该类的写入文件数据:
RandomAccessFile有两种创建模式:
1. r:只读模式,仅对文件数据进行读取操作;
2. rw:可以对文件数据进行读写操作。
写数据,我们可以调用RandomAccessFile类的write()方法,可以向文件进行文件的写操作。
RandomAccessFile的第一个参数可以传入空字符串(文件路径),也可以传入file对象,接下来我们来演示写文件的数据:
package cn.edu.jit.raf;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* java.io.RandomAccessFile
* 该类是基于指针形式读写文件数据的。
* @author Rocky
*/
public class RandomAccessFileDemo1 {
public static void main(String[] args) throws IOException {
//创建RandomAccessFile对象,为读写rw的形式。
RandomAccessFile raf = new RandomAccessFile("raf.dat","rw");
/*
* void write(it d)
* 该方法向文件中写入1个字节,写的是当前int值对象的2进制的"低八位"
* vvvvvvvv
* 00000000 00000000 00000000 00000001
*/
raf.write(257);
System.out.println("写出完毕!");
raf.close();
}
}
其次,我们再来看该类的读取数据文件:
读取数据,我们可以调用RandomAccessFile类的read()方法,可以读取文件中的数据。
int read():读取一个字节,并将该字节以10进制形式返回,若该int值为-1.则表示读取到了文件末尾。
下面来演示一下读取文件中的数据:
package cn.edu.jit.raf;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo2 {
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile("raf.dat","rw");
/**
* int read()
* 读取一个字节,并将该字节以10进制形式返回
* 若该int值为-1.则表示读取到了文件末尾
*/
int d = raf.read();
System.out.println(d);
raf.close();
}
}
以上主要介绍了RandomAccessFile类对文件进行读写操作,接下来,我将给小伙伴们继续介绍本文的另一块内容:文件的复制。接下来,我们来看一段代码演示
package cn.edu.jit.copy;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 复制文件
* @author Rocky
*/
public class CopyDemo1 {
public static void main(String[] args) throws IOException {
RandomAccessFile src = new RandomAccessFile("photo.jpg","r");
RandomAccessFile desc = new RandomAccessFile("photo_copy.jpg","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");
src.close();
desc.close();
}
}
首先呢,我们分别创建了两个RandomAccessFile对象,一个以读的形式,一个以读写的形式,作为复制的目标文件。下面做了一个循环,复制文件也就是要读取该文件所有的字节,我们说调用read()方法,如果文件读取到了-1,那就说明该文件已经读到了末尾就不再读了,结束循环,将它给写出了,我们就完成了这样的一个复制功能,最后,分别将流的两个对象给关闭,释放资源。
那么我们说这样复制文件的方式其实效率并不是很高,如果文件的大小教大呢?岂不是要很长的时间,那么,我们该如何提高效率呢?
若想提高读写效率,要提高每次读写的数据量,来减少读写次数,从而提高读写效率。我们可以采用批量读取数据的方法来复制文件:
int read(byte[] data):参数传递为byte数组,返回值为int类型,这样的好处是:
1.一次性尝试读取给定的字节数组长度的字节量;2.并存入到该数组中,而返回值为实际读取的字节量;3.若返回为-1,则表示读取到了文件末尾。看下面程序代码:
package cn.edu.jit.copy;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 若想提高读写效率,要提高每次读写的数据量
* 来减少读写次数,从而提高读写效率
* @author Rocky
*/
public class CopyDemo2 {
public static void main(String[] args) throws IOException {
RandomAccessFile src = new RandomAccessFile("jm.mp4","r");
RandomAccessFile desc = new RandomAccessFile("jm_read.mp4","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(byte[] data)
* 一次性将给定的字节数组中的所有字节写出
*
* void write(byte[] data,int start,int len)
* 将给定字节数组从下标为start处开始的连续len个字节一次性写出
*/
desc.write(buf,0,len);
}
long end = System.currentTimeMillis();
System.out.println("复制完毕!耗时:"+(end-start)+"ms");
src.close();
desc.close();
}
}
我们还可以通过使用文件流对文件进行复制操作,RandomAccessFile与流对文件的读写操作是不同的:
1.RandomAccessFile是基于指针进行读写的,所以可以随意的读写任何位置,但是流不行,流只能向后读写,不能回头;
2.RandomAccessFile即可以读又可以写,但是流要根据方向用输入流读用输出流写;
3.RandomAccessFile可以将文件任何位置的数据覆盖,但是流不行,流要么将所有数据覆盖重新写,要么只能在文件末尾追加写。
看如下程序:
package cn.edu.jit.copy;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 使用文件流对文件进行复制操作
*
* RandomAccessFile与流对文件的读写操作是不同的。
* 1、 RAF是基于指针进行读写的,所以可以随意的读写任何位置,
* 但是流不行,流只能向后读写,不能回头;
* 2、 RAF即可以读又可以写,但是流要根据方向用输入流读用输出流写;
* 3、 RAF可以将文件任何位置的数据覆盖,但是流不行,流要么将所有数据
* 覆盖重新写,要么只能在文件末尾追加写。
* @author Rocky
*/
public class CopyDemo3 {
public static void main(String[] args) throws IOException {
//文件流IO对文件进行复制操作
FileInputStream fis = new FileInputStream("raf.bat");
FileOutputStream fos = new FileOutputStream("raf_copy.bat");
int data = -1;
long start = System.currentTimeMillis();
byte[] buf = new byte[1024*10];
while((data=fis.read(buf))!=-1){
fos.write(buf,0,data);
}
long end = System.currentTimeMillis();
System.out.println("复制完毕!耗时:"+(end-start)+"ms");
//流使用完毕后要及时关闭来释放资源
fis.close();
fos.close();
}
}
接下来,我将介绍一种名词叫“缓冲流”,缓冲流是一对高级流,使用它们可以提高读写效率,从而进行高效率的文件复制。下面通过一组案例来演示缓冲流的使用:
package cn.edu.jit.copy;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 缓冲流
* 是一对高级流,使用它们可以提高读写效率
* @author Rocky
*/
public class CopyDemo4 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("music.mp3");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("music_copy.mp3");
BufferedOutputStream bos = new BufferedOutputStream(fos);
long start = System.currentTimeMillis();
int d = -1;
//**使用缓冲输入流的read()方法读取一个字节时,实际上缓冲流内部有一个字节数组,
//**它会一次性读取若干字节填满字节数组,然后将第一个字节返回,当再次调用read()
//**读取第二个字节时,缓冲流字节将字节数组第二个字节返回,而不是再去读取了,直到
//**字节数组中所有字节都已经读取完毕后,才会再次读取一组字节回来,所以缓冲流还是
//*通过提高每次读写的数据量减少读写次数提高的读写效率。
while((d=bis.read()) != -1) {
bos.write(d);
}
long end = System.currentTimeMillis();
System.out.println("复制完毕!耗时:"+(end-start)+"ms");
bis.close();
bos.close();
}
}
我们发现,文件复制的方法有很多很多,我们可以用普通的采用文件的读取复制方法,可以使用文件流,高级流等。因此,我们在实际的开发中,要根据实际的需求来进行项目的开发,从而提高开发效率!今天对File类的补充就介绍到这,看到的朋友看到文章有不足之处欢迎及时联系我,给我留言,谢谢!
Rocky 2017年2月14日