java文件操作主要封装在Java.io.File
中,而文件读写一般采用的是流的方式,Java流封装在 java.io
包中。Java中流可以理解为一个有序的字符序列,从一端导向到另一端。建立了一个流就好似在两个容器中建立了一个通道,数据就可以从一个容器流到另一个容器
Java文件操作使用 java.io.File
类进行。该类中常见方法和属性有:
:
Windows中采用 ;
c:\windows\
采用的分隔符为 \
, 而Linux中 /root
路径下的 分隔符为 /
为了达到跨平台的效果,在写路径时一般不会写死,而是使用上述几个静态变量来进行字符串的拼接
构造方法有:
常见方法:
下面是一个遍历目录中文件的例子
public static void ResverFile(String path){
File f = new File(path);
ResverFile_Core(f);
}
public static void ResverFile_Core(File f){
//System.out.println("开始遍历目录:" + f.getAbsolutePath());
File[] subFile = f.listFiles();
for(File sub : subFile){
if(sub.isDirectory()){
if(".".equals(sub.getName()) || "..".equals(sub.getName())){
continue;
}
ResverFile_Core(sub);
}else{
System.out.println(sub.getAbsolutePath());
}
}
}
上述代码根据传入的路径,递归遍历路径下所有文件。
从 JDK文档中可以看到 list 和listFiles方法都可以传入一个FileFilter 或者FilenameFilter 的过滤器, 查看一下这两个过滤器:
public interface FilenameFilter{
boolean accept(File dir, String name);
}
public interface FileFilter{
boolean accept(File pathname);
}
上述接口都是用来进行过滤的,FilenameFilter 会传入一个目录的File对象和对应文件的名称,我们在实现时可以根据这两个值来判断文件是否是需要遍历的,如果返回true则结果会包含在返回的数组中,false则会舍去结果
将上述的代码做一些改变,该成遍历所有.java 的文件
public static void ResverFile(String path){
File f = new File(path);
ResverFile_Core(f);
}
public static void ResverFile_Core(File f){
//System.out.println("开始遍历目录:" + f.getAbsolutePath());
File[] subFile = f.listFiles(pathname->pathname.isDirectory() || pathname.getName().toLowerCase().endsWith(".java"));
for(File sub : subFile){
if(sub.isDirectory()){
if(".".equals(sub.getName()) || "..".equals(sub.getName())){
continue;
}
ResverFile_Core(sub);
}else{
System.out.println(sub.getAbsolutePath());
}
}
}
Java将所有IO操作都封装在了 java.io
包中,java中流分为字符流(Reader、Writer)和字节流(InputStream、OutputStream), 它们的结构如下:
在读写任意文件时都可以使用字节流进行,文件字节流是 FileInputStream和FileOutputStream
//可以使用路径作为构造方式
//FileInputStream fi = new FileInputStream("c:/test.dat");
//可以使用File对象进行构造
FileInputStream fi = new FileInputStream(new File("c:/test.dat"));
int i = fi.read();
byte[] buffer = new byte[1024];
while(fi.read(buffer) > 0 ){
//do something
}
fi.close();
下面是一个copy文件的例子
public static void CopyFile() throws IOException{
FileInputStream fis = new FileInputStream("e:\\党的先进性学习.avi");
FileOutputStream fos = new FileOutputStream("党的先进性副本学习.avi");
int len = 0;
byte[] buff = new byte[1024];
long start = System.currentTimeMillis();
while((len = fis.read(buff)) > 0){
fos.write(buff, 0, len);
}
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start));
fos.close();
fis.close();
}
一般在读写文本文件时,为了读取到字符串,使用的是文件的字符流进行读写。文件字节流是FileReader和FileWriter
FileReader fr = new FileReader(new File("c:/test.dat"));
char[] buffer = new char[]
while(fr.read(buffer) > 0 ){
//do something
}
fr.close();
下面是一个拷贝文本文件的例子
public static void CopyFile() throws IOException{
FileReader fr = new FileInputStream("e:\\党的先进性学习.txt");
FileWriter fw = new FileOutputStream("党的先进性副本学习.txt");
int len = 0;
char[] buff = new char[1024];
long start = System.currentTimeMillis();
while((len = fr.read(buff)) > 0){
fw.write(buff, 0, len);
}
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start));
fr.close();
fw.close();
}
IO流不仅能够读写磁盘文件,在Linux的哲学中,一切皆文件。根据这点IO流是可以读写任意设备的。比如控制台;
之前在读取控制台输入的时候使用的是Scanner,这里也可以使用InputStream或者InputStreamReader。Java中定义了用于控制台输入输出的InputStream 和 OutputStream 对象: System.in 和 System.out
//多次读取单个字符
char c;
InputStreamReader isr = new InputStreamReader(System.in);
System.out.println("输入字符, 按下 'q' 键退出。");
// 读取字符
do {
c = (char) isr.read();
System.out.println(c);
} while (c != 'q');
isr.close();
//读取字符串
// 使用 System.in 创建 BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
System.out.println("Enter lines of text.");
System.out.println("Enter 'end' to quit.");
do {
str = br.readLine();
System.out.println(str);
} while (!str.equals("end"));
br.close();
控制台的写入与读取类似
OutputStreamWriter ow = new OutputStreamWriter(System.out);
char[] buffer = new char{'a', 'b', 'c'};
ow.write(buffer);
ow.flush();
ow.close();
由于write函数的功能有限,所以在打印时经常使用的是 System.out.println
函数。
在操作系统中提到内存的速度是超过磁盘的,在使用流进行读写操作时,CPU向磁盘下达了读写命令后会长时间等待,影响程序效率。而缓冲流在调用write和read方法时并没有真正的进行IO操作。而是将数据缓存在一个缓冲中,当缓冲满后或者显式调用flush 后一次性进行读写操作,从而减少了IO操作的次数,提高了效率。
常用的缓冲流有下面几个
分别对应字节流和字符流的缓冲流。它们需要传入对应的Stream 或者Reader对象。
下面是一个使用缓冲流进行文件拷贝的例子,与上面不使用缓冲流的拷贝进行对比,当文件越大,效率提升越明显
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\test.avi"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("test.avi"));
int len = 0;
byte[] buff = new byte[1024];
long start = System.currentTimeMillis();
while((len = bis.read(buff)) > 0){
bos.write(buff, 0, len);
}
long end = System.currentTimeMillis();
System.out.println("耗时:" + (end - start));
bos.close();
bis.close();