目录
背景
Java的核心库Java.io提供了全面的IO接口,包括文件读写、标准设备输出等。Java中IO是以流为基础进行输入/输出的,所有数据被串行写入输出流,或者从输入流读入。
1.1File类
简述
File类是一个与流无关的类,可以进行创建或删除文件等常用操作。
常见的构造方法
public File(String pathname) pathname ———— 路径名字符串
实例化File类时,必须设置好路径,即向File类的构造方法中传递一个文件路径。例如:,如果要操作D盘中的IODemo.java文件,必须吧pathname写成“d:\\IODemo.java”,其中"\\"表示目录的分隔符。
Java的File类定义了两个常量使程序可以在任意操作系统中使用:
- pathSeqarator: 与系统有关的路径分隔符字符串
- separator:与系统有关的默认名称分隔符字符串
File类操作文件常用方法
/**
* @author asus
*/
public class FileDemo01 {
public static void main(String[] args) {
System.out.println("路径分隔符:" + File.separator);
//使用路径分隔符创建文件
File file = new File("E:" + File.separator + "xiaoyuan1.txt");
if (file.exists()){
file.delete();
} else {
try {
file.createNewFile();
} catch (Exception e) {
System.out.println("创建文件失败!");
}
}
}
}
执行结果如下:
上面文件是我手动创建的。
上面的示例演示了创建和删除文件的方法,建议在操作文件时一定要使用File.separator表示分隔符。使开发的程序在任何操作系统中都能使用。
File类对文件夹的操作
public class FileDemo02 {
public static void main(String[] args) {
File fdir = new File("E:" + File.separator + "xiaoyuan2");
//创建文件夹
fdir.mkdirs();
//列出指定目录的全部内容(目录和文件)
//返回一个字符串数组
String[] str = fdir.list();
for (int i = 0; i< str.length; i++){
System.out.println(str[i]);
}
System.out.println("常用的方法是:listFiles()列出完整的路径");
//列出全部文件
File[] files = fdir.listFiles();
for (int i = 0; i < files.length; i++) {
System.out.println(files[i]);
}
//判断是否是目录
if (fdir.isDirectory()) {
System.out.println(fdir.getPath() + "路径是目录");
} else {
System.out.println(fdir.getPath() + "路径不是目录");
}
}
}
执行结果如下:
上述代码中创建路径和文件操作实例化File类一样,是利用mkdir()方法完成创建文件夹的。
当文件目录是WeGame时,结果输出如下:
1.2RandomAccessFile类
简述
File类只对文件本身进行操作,而如果要对文件内容进行操作,就应该使用RandomAccessFile类。此类属于随机读取类,即可以随机读取一个文件中指定位置的数据。既不是输入流的子类,也不是输出流的子类。
常见的构造方法
1.public RandomAccessFile(String file, String mode)
name: 和系统相关的文件名
mode: 对文件的访问权限,可以是r、rw、rws或rwd
2.public RandomAccessFile(String file, String mode)
name: 一个File类的对象
mode: 对文件的访问权限,可以是r、rw、rws或rwd
利用构造方法显示文件本身源代码示例
/**
* @author asus
*/
public class RandomAccessFileDemo01 {
public static void main(String[] args) {
File f = new File("E:" + File.separator + "xiaoyuan.txt");
RandomAccessFile raf = null;
//创建随机访问文件为读写
try {
raf = new RandomAccessFile(f,"rw");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//定义循环变量
long filePoint = 0;
long fileLength = 0;
try {
fileLength = raf.length();
} catch (IOException e) {
e.printStackTrace();
}
while (filePoint < fileLength) {
String str = null;
try {
//从文件按行读取
str = raf.readLine();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(str);
try {
filePoint = raf.getFilePointer();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
演示E盘存在"xiaoyuan.txt",创建int数组,把int型数组写入到文件"xiaoyuan.txt"中,然后倒序读出这些数据。
/**
* @author asus
*/
public class RandomAccessFileDemo02 {
public static void main(String[] args) {
//创建数组
int[] score = {66,70,88,60,99};
//创建随机访问文件为读写,同时处理文件不存在的异常
RandomAccessFile xiaoyuan = null;
try {
xiaoyuan = new RandomAccessFile("E: " + File.separator + "xiaoyuan.txt", "rw");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
for (int i = 0; i < score.length;i++) {
try {
xiaoyuan.writeInt(score[i]);
} catch (IOException e) {
e.printStackTrace();
}
}
for (int i = score.length - 1; i >= 0; i--) {
//整型占4个字节
try {
xiaoyuan.seek(i*4);
} catch (IOException e) {
e.printStackTrace();
}
try {
System.out.print(xiaoyuan.readInt()+"\t");
} catch (IOException e) {
e.printStackTrace();
}
}
try {
xiaoyuan.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
执行结果为:
注:虽然随机读写流可以实现对文件内容的操作,但是过于复杂。一般情况下,操作文件内容往往使用字节流或字符流。
1.3字节流与字符流
简述
流(Stream)是一组有序的数据序列。根据操作的类型,分为输入流和输出流两种。在程序中,所有数据流都是以流的方式进行传输和保存的。程序需要数据时,就是用输入流读取数据,程序需要将一些数据保存起来时,就使用输出流。
流的操作主要有字节流和字符流两大类,两类都有输入和输出操作。在字节流中输入数据使用的是InputStream类,输出数据使用的是OutputStream类。在字符流中输入数据使用的是Reader类,输出数据使用的是Writer类。
字节流
字节流主要操作byte类型数据。以byte数组为准,主要操作类是InputStream和OutputStream。
1.字节输出流: OutputStream类
OutputStream类是一个抽象类,如果使用此类,就必须通过子类实例化对象。如果要操作的对象是一个文件,就可以使用FileOutputStream类,通过向上转型实现实例化。
向文件中写入字符串示例
/**
* @author asus
*/
public class OutputStreamDemo {
public static void main(String[] args) {
File f = new File("E:" + File.separator + "xiaoyuan.txt");
//实例化--子类实例化父类
OutputStream out = null;
try {
out = new FileOutputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String str = "xiaoyuan.blog.csdn.net";
byte[] b = str.getBytes();
for (int i = 0; i < b.length;i++) {
try {
out.write(b[i]);
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭输出流
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
执行结果为:
上面程序用两种方式将所有字节写入到文件中,但如果重新运行程序,就会覆盖文件中已有的内容。如果想要在原文件中追加内容,就使用下面的构造方法
public FileOutputStream(File fiile,boolean append)
2.字节输入流:InputStream类
InputStream类可以把内容从文件中读取出来。InputStream类本身也是一个抽象类,必须依靠其子类实例化对象,对文件操作的子类为FileInputStream。
示例对文件的读取方式
public class InputStreamDemo {
public static void main(String[] args) {
File f = new File("E:" + File.separator + "xiaoyuan.txt");
InputStream in = null;
try {
in = new FileInputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte[] b = new byte[1024];
int len = 0;
try {
len = in.read(b);
} catch (IOException e) {
e.printStackTrace();
}
//循环把每一个字节一个个写入到文件中
for (int i = 0; i < len; i++) {
try {
b[i] = (byte)in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(new String(b,0,len));
}
}
字符流
简述
Java中的一个字符占两个字节。Java提供了两个专门操作字符流的类:Reader和Writer。这两个类是字符流的抽象类,定义了字符流读取和写入的基本方法,各个子类会依其特点实现或覆盖这些方法。
1.字符输出流:Writer类
Writer类对文件操作的子类是FileWriter类。
示例Writer类向文件中写入数据的方法
/**
* @author asus
*/
public class WriterDemo {
public static void main(String[] args) {
//找到文件
File f = new File("E:" + File.separator + "xiaoyuan.txt");
Writer out = null;
try {
out = new FileWriter(f,true);
} catch (IOException e) {
e.printStackTrace();
}
String str = "xiaoyuan.blog.csdn.net";
try {
out.write(str);
} catch (IOException e) {
e.printStackTrace();
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
执行结果为:
2.字符输入流: Reader类
Reader类对文件操作的子类是FileReader类
示例Reader类从文件中读取数据
/**
* @author asus
*/
public class ReaderDemo {
public static void main(String[] args) {
File f = new File("E:" + File.separator + "xiaoyuan.txt");
Reader reader = null;
try {
reader = new FileReader(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//定义变量记录读取的数据个数
int len = 0;
//所有的内容读到此数组中
char[] c = new char[1024];
int temp = 0;
//将每次读取的内容给temp,temp的值等于-1时,文件读完
while (true) {
try {
if (!((temp = reader.read()) != -1)) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
c[len] = (char)temp;
len++;
}
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("内容为:" + new String(c,0,len));
}
}
执行结果为:
字节流和字符流的区别
简述
字节流和字符流在操作上非常类似,二者除了代码不同之外,最大的差别是操作是否使用缓冲区(可理解为一段特殊的内存)。字节流在操作时不使用缓冲区,是文件本身直接操作的,而字符流在操作时使用缓冲区,即先通过缓冲区再操作文件。
修改WriterDemo.java文件如下:
/**
* @author asus
*/
public class WriterDemo {
public static void main(String[] args) {
//找到文件
File f = new File("E:" + File.separator + "xiaoyuan.txt");
Writer out = null;
try {
out = new FileWriter(f,true);
} catch (IOException e) {
e.printStackTrace();
}
String str = "xiaoyuan.blog.csdn.net";
try {
out.write(str);
} catch (IOException e) {
e.printStackTrace();
}
try {
out.flush(); //刷新缓冲区
} catch (IOException e) {
e.printStackTrace();
}
}
}
最后一步关闭输出流换成了刷新输出流,如果不关闭输出流,就需要刷新缓冲区才能在文件中看到内容。因为所有文件在硬盘或在传输时都是以字节的方式进行的,而字符只有在内存中才会形成,所以在开发中字节流使用比较广泛。