目录
1.使用File类操作文件
1.1创建File对象
1.2File类的常用方法
1.3临时文件操作
1.4遍历目录下文件
1.5删除文件及目录
2.使用字节流读写文件
2.1什么是字节流
2.2InputStream读文件
2.3OutputStream写文件
2.4文件复制
2.5字节缓冲流
3.使用字符流读写文件
3.1字符流定义
3.2字符流读文件
3.3字符流写文件
3.4转换流
1.使用File类操作文件
2.使用字节流读写文件
3.使用字符流读写文件
1.使用File类操作文件
1.1创建File对象
创建File对象的构造方法
方法声明 | 功能描述 | File(String pathname) | 通过指定的一个字符串类型的文件路径来创建一个新的File对象 | File(String parent, String child) | 根据指定的一个字符串类型的父路径和一个字符串类型的子路径(包括文件名称)创建一个File对象 | File(File parent, String child) | 根据指定的File类的父路径和字符串类型的子路径(包括文件名称)创建一个File对象 |
?在上表中,所有的构造方法都需要传入文件路径。通常来讲,如果程序只处理一个目录或文件,并且知道该目录或文件的路径,使用第一个构造方法较方便。如果程序处理的是一个公共目录中的若干子目录或文件,那么使用第二个或者第三个构造方法会更方便。
public class test01 {
public static void main(String[] args) {
File f1 = new File("D:\\file\\test01.txt"); // 使用绝对路径构造File对象
File f2 = new File("D:\\file", "test\\test02.txt");
File fileParent = new File("D:\\file");
File f3 = new File(fileParent, "test\\test03.txt");
File f4 = new File("src\\com\\cy\\HelloWorld.java"); // 使用相对路径构造File对象
System.out.println(f1);
System.out.println(f2);
System.out.println(f3);
System.out.println(f4);
}
}
?注意:使用File类的构造方法在创建File对象时,并不会创建对应文件路径的目录或文件,只是指向此文件路径对应的目录或文件。
1.2File类的常用方法
File类提供了一系列方法,用于操作其内部封装的路径指向的文件或者目录。例如,判断文件或目录是否存在,文件的创建与删除等操作。
public static void main(String[] args) throws IOException {
// 创建文件时需要保证文件的父目录存在,否则运行时会抛IOException异常
File file1 = new File("E:\\test01\\demo.txt");
if(file1.exists()){ //判断文件是否存在
file1.delete(); //存在则删除
}else { //不存在则创建文件
System.out.println(file1.createNewFile());
}
}
其他方法与上述案例相似,创建File对象,使用对象名调用方法即可
1.3临时文件操作
在一些特定情况下,程序需要读写一些临时文件,File对象提供了createTempFile()来创建一个临时文件,以及deleteOnExit()在JVM退出时自动删除该文件。
public static void main(String[] args) throws IOException {
// 提供临时文件的前缀和后缀
File f = File.createTempFile("temp", ".txt");
f.deleteOnExit(); // JVM退出时自动删除
System.out.println(f.isFile());
System.out.println(f.getPath());
}
1.4遍历目录下文件
File类的list()方法用于遍历指定目录下的所有文件。
以下案例演示遍历E盘下java文件夹下的文件
public class test04 {
public static void main(String[] args) {
File file = new File("E:\\java");
if (file.isDirectory()) { // 判断File对象对应的目录是否存在
String[] names = file.list(); // 获得目录下的所有文件的文件名
for (String name : names) {
System.out.println(name); // 输出文件名
}
}
}
}
????? 有时候在一个目录下,除了文件,还有子目录,如果想得到所有子目录下的File类型对象,list()方法显然不能满足要求,这时需要使用File类提供的另一个方法listFiles()。listFiles()方法返回一个File对象数组,当对数组中的元素进行遍历时,如果元素中还有子目录需要遍历,则需要使用递归。
public class test05 {
public static void main(String[] args) {
File file = new File("E:\\java");
fileDir(file);
}
public static void fileDir(File dir) {
File[] files = dir.listFiles(); // 获得表示目录下所有文件的数组
for (File file : files) { // 遍历所有的子目录和文件
if (file.isDirectory()) {
fileDir(file); // 如果是目录,递归调用fileDir()
}
System.out.println(file.getAbsolutePath()); // 不是目录则输出文件的绝对路径
}
}
}
1.5删除文件及目录
首先在电脑的E盘中创建一个名称为test的文件夹,然后在文件夹中创建一个txt文本文件,接下来创建一个类,在类中使用delete()方法删除文件。
public class test06 {
public static void main(String[] args) {
File file = new File("E:\\test.txt");
if(file.exists()){
System.out.println(file.delete());
}
}
}
运行结果为true
File类的delete()方法只能删除一个指定的文件或者空文件夹,假如File对象代表目录,并且目录下包含子目录或文件,则File类的delete()方法不允许对这个目录直接删除。在这种情况下,需要通过递归的方式将整个目录以及其中的文件全部删除。删除目录是从虚拟机直接删除而不放入回收站的,文件一旦删除就无法恢复。
import java.io.File;
public class test07 {
public static void main(String[] args) {
File file = new File("E:\\test");
deleteDir(file);
}
public static void deleteDir(File dir){
if(dir.exists()){// 判断传入的File对象是否存在
File[] files = dir.listFiles();
for(File file : files){// 遍历所有的子目录和文件
if(file.isDirectory()){
deleteDir(file);// 如果是目录,递归调用deleteDir()
}else {// 如果是文件,直接删除
file.delete();
}
}// 删除完一个目录里的所有文件后,就删除这个目录
dir.delete();
}
}
}
2.使用字节流读写文件
2.1什么是字节流
??????? 在程序的开发中,我们经常会需要处理设备之间的数据传输,而计算机中,无论是文本、图片、音频还是视频,所有文件都是以二进制( 字节)形式存在的。而对于字节的输入输出IO流提供了一系列的流,统称为字节流,字节流是程序中最常用的流,根据数据的传输方向可将其分为字节输入流和字节输出流。
?????? 在JDK中,提供了两个抽象类InputStream和OutputStream,它们是字节流的顶级父类,所有的字节输入流都继承自InputStream,所有的字节输出流都继承自OutputStream。
InputStream的常用方法
在上面表格中,第一个read()方法是从输入流中逐个读入字节,而第二个和第三个read()方法则将若干字节以字节数组的形式一次性读入,从而提高读数据的效率。在进行IO流操作时,当前IO流会占用一定的内存,由于系统资源宝贵,因此,在IO操作结束后,应该调用close()方法关闭流,从而释放当前IO流所占的系统资源。
InputStream是一个抽象类,如果使用此类,则首先必须通过子类实例化对象。FileInputStream是InputStream的子类,它是操作文件的字节输入流,专?用于读取文件数据。
public class test08 {
public static void main(String[] args) throws IOException {
// 创建一个文件字节输入流读取E盘下的test.txt文件(123456789)
FileInputStream in = null;
try {
in = new FileInputStream("E:\\test.txt");
int b = 0;// 定义一个int类型的变量b,记住每次读取的一个字节
while (true){
// read(): 从输入流读取一个8位的字节,把它转换为0~255之间的整数,并返回这一整数
b = in.read();
if(b==-1){// 如果读取的字节为-1,跳出while循环
break;
}
System.out.println((char) b);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(in != null){
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
文件不存在时控制台的报错信息对于上述异常错误,会有一个潜在的问题,如果读取过程中发生了IO异常,InputStream流就无法正常关闭,资源也无法及时释放。对于这种问题我们可以使用try...finally来保证InputStream在无论是否发生IO错误的时候都能够正确关闭。
2.3OutputStream写文件
OutputStream的常用方法
上述表格列举了OutputStream类的五个常用方法。前三个是重载的write()方法,都是用于向输出流写入字节。其中,第一个方法逐个写入字节,后两个方法是将若干个字节以字节数组的形式一次性写入,从而提高写数据的效率。flush()方法用来将当前输出流缓冲区(通常是字节数组)中的数据强制写入目标设备,此过程称为刷新。close()方法是用来关闭流并释放与当前IO流相关的系统资源。
OutputStream是一个抽象类,如果使用此类,则首先必须通过子类实例化对象。FileOutputStream是OutputStream的子类,它是操作文件的字节输出流,专?用于把数据写入文件。
public class test09 {
public static void main(String[] args) throws IOException {
OutputStream out = new FileOutputStream("E:\\test.txt");
String str = "hello";
byte[] b = str.getBytes();
for (int i = 0; i < b.length; i++) {
out.write(b[i]);
}
out.flush();
out.close();
}
}
?
?程序运行之后会在E盘下创建一个test.txt文件,然后写入数据。如果通过FileOutputStream向一个已经存在的文件写入数据,那么该文件的数据会先被清空然后写入写的数据。
若是希望再已经存在的文件内容之后添加新的数据,则使用FileOutputStream的构造函FileOutputStream(String fileName, boolean append)来创建文件输出流对象,并把append参数的值设置为true。
public class test10 {
public static void main(String[] args) throws IOException {
OutputStream out = new FileOutputStream("E:\\test.txt",true);
String str = "world";
byte[] b = str.getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < b.length; i++) {
out.write(b[i]);
}
out.flush();
out.close();
}
}
?
由于IO流在进行数据读写操作时会出现异常,为了代码的简洁,在上面的程序中使用了throws关键字将异常抛出。然而一旦遇到IO异常,IO流的close()方法将无法得到执行,流对象所占用的系统资源将得不到释放。因此,为了保证IO流的close()方法必须执行,通常将关闭流的操作写在finally代码块中。
2.4文件复制
InputStream和OutputStream组合使用实现文件的复制.
public class test11 {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream("E:\\test.txt");
OutputStream out = new FileOutputStream("E:\\test02.txt");
int len;//记录每次读取的字节
long beginTime = System.currentTimeMillis();
while((len = in.read())!= -1){// 读取一个字节并判断是否读到文件末尾
out.write(len);
}
long endTime = System.currentTimeMillis();
System.out.println("复制时间:"+(endTime-beginTime));
in.close();
out.close();
}
}
?上述实现的文件拷?是一个字节一个字节的读写,需要频繁的操作文件,效率非常低。
可以通过一次性读取多个字节的数据,并保存在字节数组中,然后将字节数组中的数据一次性写入文件以提高读写效率
public class test12 {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream("E:\\test.txt");
OutputStream out = new FileOutputStream("E:\\test02.txt");
byte[] buff = new byte[1024];//定义一个字节数组,作为缓冲区
int len;//记录读取读取如缓冲区的字节数
while((len = in.read(buff)) != -1){
out.write(buff,0,len);// 从第一个字节开始,向文件写入len个字节
}
in.close();
out.close();
}
}
?在拷?过程中,使用while循环语句逐渐实现字节文件的拷?,每循环一次,就从文件读取若干字节填充字节数组,并通过变量len记住读入数组的字节数,然后从数组的第一个字节开始,将len个字节依次写入文件。循环往复,当len值为-1时,说明已经读到了文件的末尾,循环会结束,整个拷?过程也就结束了,最终程序会将整个文件拷?到目标文件中。
2.5字节缓冲流
public class test13 {
public static void main(String[] args) throws IOException {
// 创建一个带缓冲区的输入流
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("E:\\test.txt"));
// 创建一个带缓冲区的输出流
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("E:\\test02.txt"));
int len;
while((len = bis.read()) !=-1){
bos.write(len);
}
bis.close();
bos.close();
}
}
???????? 创建了BufferedInputStream和BufferedOutputStream两个缓冲流对象,这两个流内部都定义 了一个大小为8192的字节数组,然后调用read()或者write()方法读写数据时,首先将读写的数据存入定义好的字节数组,然后将字节数组的数据一次性读写到文件中。这种方式对数据进行了缓冲,从而有效地提高了数据的读写效率。
3.使用字符流读写文件
3.1字符流定义
??????? 如果希望在程序中操作字符,那么就要使用字符流,同字节流一样,字符流也有两个抽象的顶级父类,分别是Reader和Writer。其中Reader是字符输入流,用于从某个源设备读取字符。Writer是字符输出流,用于向某个目标设备写入字符。Reader和Writer作为字符流的顶级父类,也有许多子类。
??????? 字符流的继承关系与字节流的继承关系有些类似,很多子类都是成对(输入流和输出流)出现的,其中FileReader和FileWriter用于读写文件,BufferedReader和BufferedWriter是具有缓冲功能的流,使用它们可以提高读写效率。
3.2字符流读文件
使用FileReader读取文件
public class test14 {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("E:\\test.txt");
int ch;
while ((ch = reader.read())!=-1){
System.out.println((char)ch);
}
reader.close();
}
}
?字符输入流的read()方法返回的是int类型的值,如果想获得字符就需要进行强制类型转换,如程序 中就将变量ch转为char类型再打印。
3.3字符流写文件
使用FileWriter写文件
public class test15 {
public static void main(String[] args) throws IOException {
FileWriter writer = new FileWriter("E:\\test03.txt");
String str = "点点赞,谢谢";
writer.write(str);
writer.close();
}
}
FileWriter同FileOutputStream一样,如果指定的文件不存在,就会先创建文件,再写入数据,如果文件存在,则会首先清空文件中的内容,再进行写入。如果想在文件末尾追加数据,同样需要调用重载的构造方法,现将程序中的代码进行如下修改:
FileWriter writer = new FileWriter("E:\\test03.txt",true);
?使用字符流复制文件与字节流基本一致,这里不做过多赘述
3.4转换流
前面提到IO流可分为字节流和字符流,有时字节流和字符流之间也需要进行转换。在JDK中提供了两个类可以将字节流转换为字符流,它们分别是InputStreamReader和OutputStreamWriter。 ???????? InputStreamReader是Reader的子类,它可以将一个字节输入流转换成字符输入流,方便直接读取字符。 ???????? OutputStreamWriter是Writer的子类,它可以将一个字节输出流转换成字符输出流,方便直接写入字符。
public class test16 {
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream("test.txt");
// 将字节流输入转换成字符输入流
InputStreamReader inr = new InputStreamReader(in);
// 赋予字符流对象缓冲区
BufferedReader br = new BufferedReader(inr);
FileOutputStream out = new FileOutputStream("E:\\test04.txt");
// 将字节输出流转换成字符输出流
OutputStreamWriter outw = new OutputStreamWriter(out);
// 赋予字符输出流对象缓冲区
BufferedWriter bw = new BufferedWriter(outw);
String line;
while ((line = br.readLine()) != null){// 判断是否读到文件末尾
bw.write(line);
}
br.close();
bw.close();
}
}
?上述代码实现了字节流和字符流之间的转换,将字节流转换为字符流,从而实现直接对字符的读写。需要注意的是,在使用转换流时,只能针对操作文本文件的字节流进行转换,如果字节流操作的是一张图片,此时转换为字符流就会造成数据丢失。
如果觉得有用,请点点赞谢谢。
|