File类的使用
java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关
File类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)
File能新建、删除、重命名文件和目录,但File不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流(IO流)。后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的”终点“。
想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个 File对象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。
File对象可以作为参数传递给流的构造器
常用构造器
-
public File(String pathname)
以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。
- 绝对路径:是一个固定的路径,从盘符开始
- 相对路径:是相对于某个位置开始
-
public File(String parent,String child)
以parent为父路径,child为子路径创建File对象。
-
public File(File parent,String child)
根据一个父File对象和子文件路径创建File对象
路径分隔符
-
路径中的每级目录之间用一个路径分隔符隔开。
-
路径分隔符和系统有关:
- windows和DOS系统默认使用“”来表示
- UNIX和URL使用“/”来表示
-
Java程序支持跨平台运行,因此路径分隔符要慎用
-
为了解决这个隐患,File类提供了一个常量:
public static final String separator。根据操作系统,动态的提供分隔符。
-
举例:
File file1 = new File("E:\Develop\test.txt");
File file2 = new File("E:"+File.separator+"Develop"+File.separator + "test.txt");
File file3 = new File("E:/Develop");
说明:
在IDEA中:
如果开发使用JUnit中的单元测试方法测试,相对路径即为当前Module下。
如果使用main()测试,相对路径即为当前的Project下。
在Eclipse中:
无论使用单元测试方法还是使用main()测试,相对路径都是当前的Project下。
常用方法
File类的获取功能
- public String getAbsolutePath():获取绝对路径
- public String getPath():获取路径
- public String getName():获取名称
- public String getParent():获取上层文件目录路径。若无,返回null
- public long length():获取文件长度(即:字节数)。不能获取目录的长度。
- public long lastModified():获取最后一次的修改时间,毫秒值
- public String[ ] list():获取指定目录下的所有文件或者文件目录的名称数组
- public File[ ] listFiles():获取指定目录下的所有文件或者文件目录的File数组
File类的重命名功能
- public boolean renameTo(File dest):把文件重命名为指定的文件路径
@Test
public void test(){
File file1 = new File("test.txt");
File file2 = new File("E:\Develop\testing.txt");
boollean renameTo = file1.renameTO(file2);
System.out.println(renameTo);
}
要想保证返回true,需要file1在硬盘中存在,且file2在硬盘中不存在。
File类的判断功能
- public boolean isDirectory():判断是否是文件目录
- public boolean isFile():判断是否是文件
- public boolean exists():判断是否存在
- public boolean canRead():判断是否可读
- public boolean canWrite() :判断是否可写
- public boolean isHidden():判断是否隐藏
File类的创建功能
- public boolean createNewFile():创建文件。若文件存在,则不创建,返回false
@Test
public void test() throws IOException {
File file = new File("test.txt");
if(!file.exists()){
file.createNewFile();
System.out.println("创建成功!");
}else{
boolean delete = file.delete();
if(delete){
System.out.println("删除成功!");
}else{
System.out.println("删除失败!");
}
}
}
- public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。如果此文件目录的上层目录不存在,也不创建。
- public boolean mkdirs():创建文件目录。如果上层文件目录不存在,一并创建
@Test
public void test() throws IOException {
//文件目录的创建
File file = new File("E:\Developer\Test");
boolean mkdir = file.mkdir();
if (mkdir) {
System.out.println("Test创建成功!");
file.delete();
}else{
System.out.println("Test创建失败!");
}
File file1 = new File("E:\Developer\test");
boolean mkdirs = file1.mkdirs();
if(mkdirs){
System.out.println("test创建成功!");
file1.delete();
}else{
System.out.println("Test创建失败!");
}
file = new File("E:\Developer");
file.delete();
}
注意事项:如果你创建文件或者文件目录没有与盘付路径,那么,默认在项目路径下。
File类的删除功能
- public boolean delete():删除文件或者文件夹
删除注意事项:
Java中的删除不走回收站。
要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录
IO流
Java IO原理
I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于 处理设备之间的数据传输 。如读/写文件,网络通讯等。
Java程序中,对于数据的输入/输出操作以 “流(stream)” 的方式进行。
java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过 标准的方法 输入或输出数据。
- 输入input: 读取外部数据(磁盘、光盘等存储设备的数据到程序(内存)中。
- 输出output: 将程序(内存)数据输出到磁盘、光盘等存储设备中。
流的分类
- 按操作 数据单位 不同分为:字节流(8 bit)(非文本数据),字符流(16 bit)
- 按数据流的 流向 不同分为:输入流,输出流
- 按流的 角色 的不同分为:节点流,处理流(效率比节点流高)
| (抽象基类) | 字节流 | 字符流 |
|---|---|---|
| 输入流 | lnputStream | Reader |
| 输出流 | OutputStream | Writer |
- Java的IO流共涉及40多个类,实际上非常规则,都是从如下4个抽象基类派生的。
- 由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。
IO流体系
文件的简单读入操作(字符流)
@Test
public void testFileReader(){
FileReader fileReader = null;
try {//异常的处理,为了保证流资源一定可以执行关闭操作,需要使用try-catch-finally处理
//1.实例化File类的对象,指明要操作的文件
File file = new File("test.txt");//读入的文件一定要存在,否则就会报FileNotFoundException。
//2.提供具体的流
fileReader = new FileReader(file);
//3.数据的读入
//read():返回读入的一个字符,如果达到文件末尾,则返回-1
int data;
while((data = fileReader.read())!=-1){
System.out.print((char)data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.流的关闭操作
try {
if(fileReader != null) //防止文件未被读入而导致的空指针异常
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
升级Read
//read(char[] cbuf):返回每次读入cbuf数组中的字符的个数,如果达到文件末尾,返回-1。
char[] cbuf = new char[5];
int len;
while ((len = fileReader.read(cbuf)) != -1) {
System.out.print(cbuf);
}
文件的简单写出操作(字符流)
@Test
public void testFileWriter(){
FileWriter fileWriter = null;//输出操作,对应的File可以不存在,并不会报异常。
try {
//1.提供File类的对象,指明写出的文件
File file = new File("Testing.txt");//Java忽略大小写
//2.提供FileWriter的对象,用于数据的写出
fileWriter = new FileWriter(file);
// File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。
// File对应的硬盘中的文件如果存在:
// 如果流使用的构造器是,FileWriter(file,false)/FileWriter(file):对原有文件的覆盖
// 如果流使用的构造器是,FileWriter(file,true):不会对原有文件覆盖,而是在原有文件基础上追加内容
//3.写出的操作
fileWriter.write("There is white moonlight in my heart,\nand there are no stars in my eyes");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.流资源的关闭
try {
if(fileWriter!=null)
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件的读入与写出操作(字符流)
@Test
public void testFileReaderFileWriter(){
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
//1.创建File类的对象,指明读入和写出的文件
File srcFile = new File("Testing.txt");
File destFile = new File("hello.txt");
//2.创建输入流和输出流的对象
fileReader = new FileReader(srcFile);
fileWriter = new FileWriter(destFile);
//3.数据的读入和写出操作
char []cbuf = new char[5];
int len;//记录每次读入到cbuf数组中的字符的个数
while((len = fileReader.read(cbuf))!=-1){
//每次写出len个字符
fileWriter.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流资源
try {
if(fileWriter != null)
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fileWriter != null)
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节流的文件读写
@Test
public void testFileInputStream(){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
File srcfile = new File("1667620425430.png");
File destfile = new File("view.png");
fileInputStream = new FileInputStream(srcfile);
fileOutputStream = new FileOutputStream(destfile);
byte[] buffer = new byte[100000];
int len;//记录每次读取的字节个数
while ((len = fileInputStream.read(buffer))!=-1){
fileOutputStream.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fileInputStream != null)
fileInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
if (fileInputStream != null)
fileInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
文件的复制操作(节点流)
public static void copyFile(String srcPath, String destPath){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
File srcfile = new File(srcPath);
File destfile = new File(destPath);
fileInputStream = new FileInputStream(srcfile);
fileOutputStream = new FileOutputStream(destfile);
byte[] buffer = new byte[1024];
int len;
while ((len = fileInputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null)
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fileInputStream != null)
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testFileCopy(){
String src = "Testing.txt";
String dest = "test.txt";
long start = System.currentTimeMillis();
copyFile(src,dest);
long end = System.currentTimeMillis();
System.out.println("复制操作花费的时间为:"+(end-start));
}
文本文件的复制(缓冲流)
@Test
public void copyBufferedReaderBufferedWriter(){
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
bufferedReader = new BufferedReader(new FileReader(new File("test.txt")));
bufferedWriter = new BufferedWriter(new FileWriter(new File("Testing.txt")));
char[] buffer = new char[1024];
int len;
while ((len = bufferedReader.read(buffer))!=-1){
bufferedWriter.write(buffer,0,len);
// bufferedWriter.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(bufferedWriter != null)
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(bufferedReader != null)
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
非文本文件的复制(缓冲流)
@Test
public void copyBufferedStream(String srcFile,String destFile){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
//1.造文件
File srcFile = new File(srcFile);
File destFile = new File(destFile);
//2.造流
//2.1造节点流
fileInputStream = new FileInputStream(srcFile);
fileOutputStream = new FileOutputStream(destFile);
//2.2造缓冲流
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
//3.复制的细节:读取、写入
byte[] buffer = new byte[1024];
int len;
while((len = bufferedInputStream.read(buffer))!=-1){
bufferedOutputStream.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.资源的关闭:先关闭外层的流,再关闭内层的流
try {
if (bufferedOutputStream != null)
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bufferedInputStream != null)
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
//说明:关闭外层流的同时,内层流也会自动关闭
try {
if(fileOutputStream!= null)
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fileInputStream != null)
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
提高速度的原因:内部提供一个缓冲区
转换流(属于字符流)
InputStreamReader:将一个字节的输入流转换为字符的输入流
OutputStreamWriter:将一个字符的输出流转换为字节的输出流
代码实现
@Test
public void testInputStreamReaderOutputStreamWriter(){
InputStreamReader inputStream = null;
OutputStreamWriter outputStream = null;
try {
FileInputStream fileInputStream = new FileInputStream("test.txt");
FileOutputStream fileOutputStream = new FileOutputStream("test_gdk.txt");
inputStream = new InputStreamReader(fileInputStream,"utf-8");
outputStream = new OutputStreamWriter(fileOutputStream,"GBK");
char [] buffer = new char[1024];
int len;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(inputStream != null)
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(outputStream != null)
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件编码
编码表的由来
计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。就将各个国家的文字用数字来表示,并一 一对应,形成一张表。这就是编码表。
常见的编码表
-
ASCIl: 美国标准信息交换码。
√用一个字节的7位可以表示。
-
lSO8859-1: 拉丁码表。欧洲码表
√用一个字节的8位表示。
-
GB2312: 中国的中文编码表。最多两个字节编码所有字符
-
GBK: 中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
-
Unicode: 国际标准码,融合了目前人类使用的所有字符 字符码。所有的文字都用两个字节来表示。
-
UTF-8: 变长的编码方式,可用1 - 4个字节来表示一个字符。
其他流
标准的输入、输出流
System.in:标准的输入流,默认从键盘输入
System.out:标准的输出流,默认从控制台输出
package OtherStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class OtherStreamTest {
/**
*通过键盘输入字符串,将其中的小写字母转换为大写字母,程序在输入"e"或"exit"时终止(不分大小写)
*@Version: 1.0
*
*/
public static void main (String[] args) {
test();
}
public static void test(){
BufferedReader bufferedReader = null;
try {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
bufferedReader = new BufferedReader(inputStreamReader);
while(true){
System.out.println("请输入字符串:");
String data = bufferedReader.readLine();
if("e".equalsIgnoreCase(data)||"exit".equalsIgnoreCase(data)){
System.out.println("程序结束");
break;
}
String upperCase = data.toUpperCase();
System.out.println(upperCase);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(bufferedReader != null)
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
打印流
-
实现将 基本数据类型 的数据格式转化为 字符串 输出
-
打印流: PrintStream 和 PrintWriter
- 提供了一系列重载的print()和println()方法,用于多种数据类型的输出
- PrintStream和PrintWriter的输出不会抛出IOException异常
- PrintStream和PrintWriter有自动flush功能
- PrintStream打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用PrintWriter类。
- System.out返回的是PrintStream的实例
@Test
public void testPrintStream () {
PrintStream printStream = null;
try {
FileOutputStream outputStream = new FileOutputStream(new File("test.txt"));
printStream = new PrintStream(outputStream,true);
if(printStream!=null){
System.setOut(printStream);
}
for(int i=0;i<=255;i++){
System.out.print((char)i);
if(i%10==0){
System.out.println();//每10个换行
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
if(printStream!=null)
printStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
数据流
为了方便地操作Java语言的基本数据类型和String的数据,可以使用数据流。
-
数据流有两个类:(用于读取和写出基本数据类型、String类的数据)
- DatalnputStream和DataOutputStream
- 分别“套接”在InputStream和OutputStream子类的流上
DatalnputStream中的方法
-
boolean readBoolean()
-
byte readByte()
-
char readChar()
-
float readFloat()
-
double readDouble()
-
short readShort()
-
long readLong()
-
int readlnt()
-
String readUTF()
-
void readFully(byte[ ] b)
-
DataOutputStream中的方法
- 将上述的方法的read改为相应的write即可。
作用:用于读取或写出基本数据类型的变量或字符串
说明: 数据流所写出到文件中的数据信息,并非是直接能看到的(会出现乱码),必须使用数据流的写入操作按顺序正确写入至内存的变量中,并进行输出操作,才能正常显示。
@Test
public void testDataReaderWriter(){
/**
*
* 将基本数据类型和字符串写出并存储到文件中
*
*/
DataOutputStream out = null;
try {
out = new DataOutputStream(new FileOutputStream("data.txt"));
out.writeUTF("何鑫");
out.flush();//将内存中的数据到文件中
out.writeInt(18);
out.flush();//将内存中的数据到文件中
out.writeBoolean(true);
out.flush();//将内存中的数据到文件中
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(out != null)
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
* 将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。读取不同类型的数据的顺序要与当初写入文件时,保存的数据顺序一致!
*
*/
DataInputStream in = null;
try {
in = new DataInputStream(new FileInputStream("data.txt"));
String s = in.readUTF();
int i = in.readInt();
boolean isMale = in.readBoolean();
System.out.println("name:"+s+"\t"+"age:"+i+"\t"+"isMale:"+isMale);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(in != null)
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
对象流
ObjectInputStream和OjbectOutputSteam
- 用于存储和读取基本数据类型 数据或对象 的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
- 序列化:用ObjectOutputStream类保存 基本类型数据或对象的机制
- 反序列化:用ObjectInputStream类读取 基本类型数据或对象的机制
ObjectOutputStream和ObjectInputStream不能序列化 static 和 transient 修饰的成员变量
对象的序列化
-
对象序列化机制 允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
-
序列化的好处在于可将任何实现了Serializable接口的对象转化为 字节数据 ,使其在保存和传输时可被还原
-
序列化是RMI (Remote Method lnvoke --远程方法调用)过程的参数和返回值都必须实现的机制,而RMI是JavaEE的基础。因此序列化机制是JavaEE平台的基础
-
如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一。否则,会抛出NotSerializableException异常
- Serializable
- Externalizable
-
凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
- private static final long serialVersionUlD;
- serialVersionUID用来表明类的不同放本同的兼谷性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序列化时是否兼容。
-
如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUJID可能发生变化。 故建议,显式声明。
-
简单来说,Java的序列化机制是迎过在运仃的判断尖的Seelo个一证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的 serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)
package ObjectInputOutputStream;
import org.junit.Test;
import java.io.*;
import java.util.Objects;
public class ObjectInputOutputStreamTest {
/**
* 序列化过程:将内存中的java对象保存在磁盘中或者通过网络传输出去,使用ObjectOutputStream实现
*
*/
@Test
public void testObjectOutputInputStream(){
ObjectOutputStream objectOutputStream = null;
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream("object.data"));
objectOutputStream.writeObject(new String("Love Is Gone,but I love you"));
objectOutputStream.flush();//刷新操作
objectOutputStream.writeObject(new Person("WLM",18));
objectOutputStream.flush();//刷新操作
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(objectOutputStream != null)
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
* 反序列化:将磁盘文件中的对象还原为内存中的java对象,使用ObjectInputStream来实现
*
*/
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("object.data"));
Object object = ois.readObject();
System.out.println(object);
Person person = (Person)ois.readObject();
System.out.println(person);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if(ois != null)
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Person implements Serializable{//Serializable为标识接口
public static final long serialVersionUID = 4098451642L;
private String name;
private int age;
public Person (String name, int age) {
this.name = name;
this.age = age;
}
public Person () {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
System.out.println("Person equals()......");
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
随机存取文件流(RandomAccessFile类)
RandomAccessFile声明在java.io包下,但直接继承于java.lang.Object类。并且它实现了Datalnput、DataOutput这两个接口,也就意味着这个类既可以读也可以写。
RandomAccessFile类支持“随机访问”的方式,程序可以直接跳到文件的任意地方来读、写文件
- 支持只访问文件的部分内容
- 可以向已存在的文件后追加内容
RandomAccessFile对象包含一个记录指针,用以标示当前读写处的位置。
RandomAccessFile类对象可以自由移动记录指针:
- long getFilePointer(): 获取文件记录指针的当前位置
- void seek(long pos): 将文件记录指针定位到pos位置
构造器
- public RandomAccessFile(File file, String mode)
- public RandomAccessFile(String name, String mode)
创建RandomAccessFile类实例需要指定一个mode参数,该参数指定RandomAccessFile的访问模式:
- r:以只读方式打开
- rw:打开以便读取和写入
- rwd:打开以便读取和写入;同步文件内容的更新
- rws:打开以便读取和写入;同步文件内容和元数据的更新
如果模式为只读r。则不会创建文件,而是会去读取一个已经存在的文件,如果读取的文件不存在则会出现异常。如果模式为rw读写。如果文件不存在则会去创建文件,如果存在则不会创建。
当RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。如果写出到的文件存在,则会对原有文件进行覆盖(默认情况:从头覆盖)
package RandomAccessFile;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* RandomAccessFile的使用,直接继承于java.lang.Object类,实现了DataInput和DataOutput接口。既可以作为一个输入流,又可以作为一个输出流
*/
public class RandomAccessFileTest {
@Test
public void testRandomAccessFile(){
RandomAccessFile testFile = null;
RandomAccessFile testFileWrite = null;
try {
testFile = new RandomAccessFile(new File("1667620425430.png"),"r");
testFileWrite = new RandomAccessFile(new File("1667620425430.png"),"rw");
byte[] buffer = new byte[1024];
int len;
while((len = testFile.read(buffer))!=-1){
testFileWrite.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(testFile != null)
testFile.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(testFileWrite != null)
testFileWrite.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void test(){
RandomAccessFile testFile = null;
try {
testFile = new RandomAccessFile("test.txt","rw");
// testFile.seek(0);//将指针调到角标为0的位置
testFile.write("Love Is Gone,but I like you!".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(testFile != null)
testFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testInsertFile(){
/**
*
* 使用RandomAccessFile实现数据的插入效果
*
*/
RandomAccessFile testFile = null;
try {
testFile = new RandomAccessFile("test.txt","rw");
testFile.seek(5);
//保存指针5后面的所有数据到StringBuilder中
StringBuilder builder = new StringBuilder((int) new File("test.txt").length());
byte[] buffer = new byte[1024];
int len;
while((len = testFile.read(buffer))!=-1){
builder.append(new String(buffer,0,len));
}
//调回指针,写入“WLM”
testFile.seek(28);
testFile.write("WLM ".getBytes());
//将StringBuilder中的数据写入文件中
testFile.write(builder.toString().getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(testFile != null)
testFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}