说到文件和文件夹,大家肯定很不陌生,文件就是有着后缀名和文件名加起来的东西,而文件夹就是存放文件或者接
着存放下一个文件夹。
在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时,先缓冲流,再是写流。
每次最后关流是先关读流,仍是缓冲流到文件流。
接下来会有项目案例来练习一下…………