Java——第六章(异常处理和文件IO流操作)—(续)

本文详细介绍Java中文件和文件夹的基本操作,包括创建、删除、读取和写入等内容,并介绍了如何使用流进行高效的文件处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说到文件和文件夹,大家肯定很不陌生,文件就是有着后缀名和文件名加起来的东西,而文件夹就是存放文件或者接


着存放下一个文件夹。


在java中,有一个文件类,File,一个File 对象对应着一个实体文件  或者是提供实体文件的路径(也就是文件


夹),那么,java中文件或文件夹的操作有什么呢?


先讲文件,必然要提到文件的创建与删除:


文件的创建:


1、先创建一个File的对象file,file对应着一个文件,常用构造方法,


eg: File file = new File("E:/a/b/a.txt");

2、调用对象的 .creatNewFile()方法创建对象。


eg:


if( file.creatNewFile())     

System.out.println("文件创建成功!");

else

 {  System.out.println("文件创建失败!");}


该方法返回的是boolean类型,创建成功返回true,失败为false。


文件的删除: 


调用文件对象的delete方法。同样是布尔类型,删除成功返回true。    eg:  file.delete();


文件夹的创建与删除和文件的创建删除几乎没什么区别。


文件夹的创建:


1、创建File对象,对应一个文件夹路径。eg:  File file = new File("E:/a/b/c/");


2、创建文件夹有2种方式,对象的mkdir()方法和mkdirs()方法。


第一种方法是单层创建,什么意思呢,就是当上级路径不存在时,将不允许创建指定文件夹,上面例子中,如果a或


者b文件夹不存在,就无法创建他下面的子文件夹c。不能够


跨越a和b文件夹创建c文件夹。  eg: file.mkdir()将报错。


当然,第二种自然就是多层创建了,可以不用考虑是否存在上级目录,直接创建指定的文件夹。 


eg: file.mkdirs()将创建成功文件夹。


在这里要提到一个很多同学有疑问的问题,关于路径中用 / 还是 \ ,平时文件或文件夹的路径是用\来表示路径级


别,因为java中的转义字符就是\  ,所以如果再用\  ,java会将这


个当转义字符来用,达不到我们想要的效果,所以可以用两个\\来表示路径,或者可以用一个/来表示。


而\\只是在windows中可以,其他系统不一定适用,所以为了避免麻烦,


用一个/比较方便,简单点。


文件经常用到一些操作,那么我们详细看一下有些什么方法:


1、 .listFiles()  扫描文件夹中的所有东西(文件或文件夹),包含路径,返回文件对象的数组。


import java.io.File;

public class FileListtest {

	public static void main(String[] args) {
		//获取父级路径
		File dir= new File("G:/a/b/");
		//得到路径下的文件或文件夹
		File files[] = dir.listFiles();
		for (int i = 0; i < files.length; i++) {
			System.out.println(files[i]);
		}
	}

}

执行结果:





其中,有后缀名的为文件,c为文件夹。


有些同学可能会有这样的疑问,能不能扫描指定格式的文件。既然我这么说啦,,当然是有的,让我们看看怎么实


现:


首先,需要listFiles(FilenameFilter filter)方法中传入一个过滤器filter,过滤器的作用就是筛选出指定的文


件,但是FilenameFilter却是一个接口,所以我们还需要创建一个实现类来实现接口,重写接口中抽象方法accept。


实现类代码:

import java.io.File;
import java.io.FilenameFilter;

public class FileName implements FilenameFilter {
	//dir为当前文件的父目录,name为文件的名字。
	@Override
	public boolean accept(File dir, String name) {
		// TODO Auto-generated method stub
		return name.endsWith(".avi");
	}

}

这样就可以筛选出后缀名为avi的文件的过滤器。接下来用主方法测试一下:


import java.io.File;
import java.io.FilenameFilter;

public class delete2 {
	//利用扫描指定后缀名的文件List删除指定后缀名的文件。
	
	public static void main(String[] args) {
		//获取父目录dir
		File dir = new File("G:/a/b/");
		
		//创建实现类FileName实现FilenameFilter接口,创建filter过滤器。
		FilenameFilter filter= new FileName();//多态,父类留有子类的引用
		
		File[] files = dir.listFiles(filter);
		
		for (int i = 0; i < files.length; i++) {
			System.out.println(files[i].getName());
		}
		
	}

}

运行结果:





2、 . list扫描文件夹中东西的名字,返回字符串数组的对象。


之前第一种方法扫描所以文件或文件夹中同样可以实现这种方法,可以直接显示文件或文件夹而不显示路径,


只需在files[i]后面加.getName()即可显示东西的名字。


import java.io.File;

public class FileListtest {

	public static void main(String[] args) {
		//获取父级路径
		File dir= new File("G:/a/b/");
		//得到路径下的文件或文件夹
		String[] files = dir.list();
		for (int i = 0; i < files.length; i++) {
			System.out.println(files[i]);
		}
	}

}

运行结果:




3、createTempFile(String prefix, String suffix, File directory) 创建临时文件。

参数:

prefix :前缀名。suffix  :后缀名。directory: 路径。该方法是用static修饰,所以可以直接用类名调用,


File.createTempFile();


每次创建的临时文件均不同,每一时刻都在变。


File.createTempFile("aaa", ".tep", new File("G:/a/b/"));   前缀名aaa与后缀名.tep之间会有系统随机生成


的数字,不固定,生成在文件夹b下面。


4、 ..getPath()获取相对路径和 .getAbsolutePath()获取绝对路径


import java.io.File;

public class FileListtest {

	public static void main(String[] args) {
		//获取文件路径
		File file= new File("G:/a/b/1.txt");
		System.out.println(file.getAbsolutePath());
		System.out.println(file.getPath());
	}

}

运行结果:




因为指定了路径为G盘,其实相对路径是对于整个项目下的路径。所以两个相同了,可以在盘符那用.来测试一下。


4、getParentFile()获取当前文件的父级目录,返回File类型。


举个例子。File dir= new File("G:/a/b/");  File file= new File("G:/a/b/1.txt");


dir就是file的父级目录.   实际上 dir=file.getParentFile();


5、 ..isFile()和..isDirectory()判断file是文件还是目录,返回类型是布尔。


如果 File file= new File("G:/a/b/1.txt");  System.out.println(file.isFile()); 输出的是true。


File dir= new File("G:/a/b/"); System.out.println(file.isFile());  输出的是false。



讲完文件的一些基本操作,下面会提到一个名字,叫流,而且在文件的读取,写入当中起很重要的作用。


流,好比水流,相当于一个管道,用来运输文件字节或字符,连接两个目的地池。只靠两个目的地是无法建立连接


的,流就是他们之间的桥梁。


通过插管道,将一个池子与外界连接,从文件中通过管道流出来,读取内容,这个管道称读流,用来读取文件内容。


通过插管道,将一个池子与外界连接,从管道流入文件中,写入内容,这个管道称写流,用来把数据写入到文件当


中。


不管读流还是写流,有两种传输形式,一种是字节流,一种是字符流。


字节流常用来下载,如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好


点,防止出现中文乱码,因为中文是占用2个字节,字母,数字是一个字节,将中文2个字节拆开,难免会遇到乱码问


题,所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储


存这些字节到磁盘。


先看字节流,字节流的读流是通过FileInputStream的对象将管道插入到文件的对象当中,通过调用read方法读出内


容。

eg:


File file = new File("G:/a/b/c/1.txt");//  创建文件对象file

FileInputStream fis = new FileInputStream(file);


read这里介绍两种方法来读取内容,read()、read(byte[] b),一种通过单个字节读取,每次读取一个字节,每


执行一次读一个。另一种是通过byte数组读取。


将读取的字节放入字节数组中,通过数组打印输出。返回读到的个数,若为空,读到-1。读到的内容均为Ascll码


值,打印时需要强转为char类型可看到打印的单个内容。


代码:


import java.io.File;
import java.io.FileInputStream;

public class du {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		File file = new File("G:/a/b/1.txt");
		FileInputStream fis = new FileInputStream(file);
		int a=fis.read();
		System.out.println((char)a);
		System.out.println((char)fis.read());
		fis.close();
		
	}

}

ps:1.txt中文件内容为:

123asasd564
asdklljfldjfsldfad2


运行结果:



更常用的是第二种通过byte数组来读,将读到的内容放入数组中,通过字符串String可以将所有内容读出。


这里要注意一点,数组的大小可以自己定,如果定义的小了,一次性没读完,下次读的时候将覆盖数组前面位置的


值。


例如定义了byte数组的大小为10,一行有12个字节,第一次读到10个结束后,下次再读的时候将把第11,12个字节的


内容覆盖byte[0],和byte[1]中,


所以经常为保证每次读的都是新的字节,调用String中的一个方法,String(byte[] b, int offset, int length),将


数组b中的字节,每次从offset位置开始,读length个。


代码:

import java.io.File;
import java.io.FileInputStream;

public class du {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		File file = new File("G:/a/b/1.txt");
		FileInputStream fis = new FileInputStream(file);
		
		byte[]b = new byte[1024];
		int len;
		while((len=fis.read(b))!=-1)
		{
			System.out.println(new String(b,0,len));
		}
		fis.close();
	}

}

运行结果:





注意,若一次没读完,第二次读的时候将从下标为0的位置开始覆盖之前数组中的内容。


字节的写流FileOutputStream用来给写入的文件插管道,将文件内容写入文件中,用代码来演示写流的各种方法。


代码:


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class xie {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		File file = new File("G:/a/b/5.txt");
		
		FileOutputStream fos = new FileOutputStream(file);
		//1、每次写入一个字节
		fos.write(97);//,97为Ascll码值 对应 a
		
		//2、将字符串转为字节数组写入
		String s = "你好啊,世界!";
		
		fos.write(s.getBytes());
		
		//3、将上次的2.txt内容写到5.txt中
		
		File file1 = new File("G:/a/b/1.txt");
		FileInputStream fis = new FileInputStream(file1);
		byte b[] = new byte[1024];
		int len;
		while((len = fis.read(b))!=-1)
		{
			fos.write(b,0,len);
		}
		
		fos.close();fis.close();
	}

}

注意: file的写入文件对象可以不存在,系统自动创建,但读的文件不可以。


电脑中本没有5.txt文件,看看运行结果。


运行结果:




其实大家可能发现了,输入中文也可以正常显示,既然字节流就可以用,,为什么要有字符流?


其实,用字节流可能会出现乱码,不是一定,下面看这个例子:


代码:

import java.io.File;
import java.io.FileInputStream;

public class du {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		File file = new File("G:/a/b/4.txt");
		FileInputStream fis = new FileInputStream(file);
		
		byte[]b = new byte[1024];
		int len;
		while((len=fis.read(b))!=-1)
		{
			System.out.println(new String(b,0,len));
		}
		
	}

}


运行结果:




这个好像看着没什么问题,那么我要把byte数组大小改为40呢?或者更小呢?然后加点字母数字等?咱们再看看结


果:




我在每行的第一个字前面加了一个字母,大家可以看到,已经完全乱码,这是因为汉字每次占2个字节,而字母是一


个字节,一次读40个字节大小,难免会把汉字两个字节给截


成两部分,读取的时候就会出现乱码,另一半没读完整。


如果是字符流 ,就不会出现中文乱码问题!


同样,字符流也分读流和写流,分别作为插入文件的管道。和字节流几乎没什么太大区别。


如果将要读的字符放入开辟的字符数组中,返回读到的字符个数。,若为空,读到-1.


注意,若一次没读完,第二次读的时候将从下标为0的位置开始覆盖之前数组中的内容。


代码:


import java.io.File;
import java.io.FileReader;

public class du {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		File file = new File("G:/a/b/4.txt");
		FileReader fr = new FileReader(file);
		//1、read()  一次读一个字符
//		int i=fr.read();
//		System.out.println((char)i);
//		System.out.println((char)fr.read());
		
		//2、read(char []b)
		
		char []b = new char[1024];
		int len;
		while ((len=fr.read(b))!=-1)
		{
			System.out.println(new String(b,0,len));
		}
		
		
	}

}


运行结果:




这种方式就不要考虑中文乱码问题。数组大小改也不会出现乱码。


关于字符流的写流,有多种方式。

1、write(int b)
2、write(char c[])
3、write(char c[],int offset,int len)
4、write(String str)
5、write(String str,int offset,int len)


代码:


import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;

public class xie {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		File file = new File("G:/a/b/6.txt");
		FileWriter fw = new FileWriter(file);
		//1、每次写一个字符
		fw.write(97);
		
		//2、char数组进行写入
		String s = "你好啊,世界。";
		char c[] = s.toCharArray();
		fw.write(c);
		//3、直接传入字符串
		
		fw.write(s);
		
		//边读边写,将4.txt的内容写到6.txt
		
		
		File file1 = new File("G:/a/b/7.txt");
		FileReader fr = new FileReader(new File("G:/a/b/4.txt"));
		FileWriter fw1 = new FileWriter(file1);
		char c1[] = new char[1024];
		int len;
		String str=new String(c1);
		
		while((len = fr.read(c1))!=-1)
		{
			//4、write(char c[],int offset,int len)
			fw1.write(c1,0,len);
			//5、write(String str,int offset,int len)
			fw1.write(new String(c1),0,len );
		}
		
		fw.flush();
		fw1.flush();
		fr.close();
		fw.close();
		fw1.close();
	}

}

运行结果:






因为第4、5种方法写入结果相同,所以出现两次相同的内容。


无论输入还是输出流,在用完之后需要关闭流,.close()方法。

输出流中在每次写入后建议flush(),确保字节或字符全部写入,相当于冲马桶,刷干净。有时候明明写入东西打


开却什么都没有,就是因为没有flush。



说到这里,又会引发出一个问题,在管道中如果一次性写入或者读出的数据过大,会不会将管道冲开,这个是有可能


的,所以会再给一个管道加固一下,这个就是


高级缓冲流,高级缓冲流也会有读BufferedReader(Reader in)、和写BufferedWriter(Writer out)。


高级缓冲流缓冲的是流是字符,  没有面对文件 , 面对的是管道,相当于在管道外壁加宽。


高级缓冲流中主要方法是读一行内容和写一行内容。


将1.doc内容写到4.doc中。


代码:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;

public class Demo11 {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		File fromfile = new File("g:/a/b/c/1.doc");
		File tofile = new File("G:/a/b/c/4.doc");
		FileReader fr = new FileReader(fromfile);
		BufferedReader br = new BufferedReader(fr);
		FileWriter fw = new FileWriter(tofile,true);
		BufferedWriter bw = new BufferedWriter(fw);
		//缓冲没有后面加true一说,只是针对管道,和文件不挂钩。
		
		String str ="";
		while((str=br.readLine())!=null)
		{
			bw.write(str);
			bw.newLine();
			bw.flush();
			fw.flush();
		}
		br.close();
		fr.close();
		bw.close();
		fw.close();
	}

}

如果每次希望在写入文件中追加内容而不是覆盖内容,可以在写流后面的文件对象后加一个true的条件。


也有些时候需要将字节流转换成字符流,例如从网上下载的字节流文件,转换成字符流文件可以实现字节流转字符


流:


代码:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;

public class Demo15 {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		/*
		 */
		File file = new File("g:/a/b/c/1.doc");
		File file1 = new File("g:/a/b/c/5.doc");
		FileInputStream fis = new FileInputStream(file);
		InputStreamReader isr = new InputStreamReader(fis);
		BufferedReader br = new BufferedReader(isr);
		FileWriter fw = new FileWriter(file1);
		BufferedWriter bw = new BufferedWriter(fw);
		String s = "";
		while((s=br.readLine())!=null)
		{
			bw.write(s);
			bw.newLine();
			bw.flush();
			fw.flush();
		}
		br.close();
		fis.close();
		bw.close();
		fw.close();
				
	}

}


注意: 每次写流时,flush时,先缓冲流,再是写流。

每次最后关流是先关读流,仍是缓冲流到文件流。


接下来会有项目案例来练习一下…………









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值