对文件File的操作
//通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例。
File(String pathname)
public String getAbsolutePath();//返回抽象路径名的绝对路径名字符串。
public boolean mkdirs();//创建此抽象路径名指定的目录,包括创建必需但不存在的父目录。
public boolean mkdir()//创建此抽象路径名指定的目录。
//返回一个抽象路径名数组,这些路径名表示此抽象路径名所表示目录中的文件。
public File[] listFiles()
// 删除此抽象路径名表示的文件或目录。
public boolean delete()
//测试此抽象路径名表示的文件是否是一个目录。
public boolean isDirectory()
//测试此抽象路径名表示的文件或目录是否存在。
public boolean exists()
用mkdir()创建文件实例
public static void main(String[] args) {
String path = "abcd\\sdf\\nkunoi\\a"; //给出创建文件的路径
//在E盘下面创建文件,将文件路径添加为文件
File file = new File("E:\\" + path);
//file.exists();判断当前目录是否存在
if(file.exists()) {
//file.mkdirs();先判断当前目录下是否存在路径文件,
//存在返回false,不存在,生产路径文件返回true
file.mkdirs()
}
}
E盘下面生成的路径;
需要注意的是
// file.mkdirs(); 可以创建多级目录(文件夹),父目录不一定存在。
//即可以生成abcd\\sdf\\nkunoi\\a 的所有目录
// file.mkdir();只能创建一级目录(文件夹),且父目录必须存在,否则创建失败。
//如果要创建sdf目录,那么abcd目录必须存在。nkunoi目录也一样,sdf目录必须存在
递归扫描目录下的所有文件
如果我们要扫描当前目录下的所有文件,可以递归一级一级的扫描
代码如下:
package com.dxc.about_dir.test;
import java.io.File;
import java.io.FileFilter;
public class TestForDir {
public static void scanDir(File curDir) {
curDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
//检查这个对象是否是文件
//是文件,则输出这个目录
System.out.println("目录:" + pathname);
//递归扫描该目录下的文件
scanDir(pathname);
return false;
}
//不是目录文件,并且判断该文件是否以".java"结尾
if (pathname.getName().endsWith(".java")) {
System.out.println("取得绝对路径:" +
pathname.getAbsolutePath());//取得绝对路径
System.out.println("取得相对路径:" +
pathname.getPath());//取得相对路径
}
return false;
}
});
}
public static void main(String[] args) {
File file = new File(".");
scanDir(file);
}
}
这是我当前目录下的文件
这是通过代码扫描的结果
对文件的流(Stream)、和IO操作
Java 流(Stream)、文件(File)和IO
Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。
Java.io 包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。
一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。
但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
读文件
FileInputStream(path);
该流用于从文件读取数据,它的对象可以用关键字 new 来创建。
- public void close() throws IOException{}
关闭此文件输入流并释放与此流有关的所有系统资源。抛出IOException异常。 - protected void finalize()throws IOException {}
这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出IOException异常。 - public int read(int r)throws IOException{}
这个方法从 InputStream 对象读取指定字节的数据。返回为整数值。返回下一字节数据,如果已经到结尾则返回-1。 - public int read(byte[] r) throws IOException{}
这个方法从输入流读取r.length长度的字节。返回读取的字节数。如果是文件结尾则返回-1。 - public int available() throws IOException{}
返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取的字节数。返回一个整数值。
我在上面创建的abcd\sdf\nkunoi\a目录下面,建一个txt文件
将此txt文件读出的代码为
package com.dxc.about_io.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class TestForFileIO {
public static void main(String[] args) {
FileInputStream fis;
try {
//该流用于从文件中读取数据
fis = new FileInputStream(
"E:\\abcd\\sdf\\nkunoi\\a\\b\\c\\1111.txt");
//从fis流中读取第一个字节
int value = fis.read();
while (value != -1) {
System.out.print((char) value);//输出读取的字节
value = fis.read();//举行读取字节,到结尾返回-1,循环结束
}
fis.close();//关闭文件
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
输出为
写文件
FileOutputStream
该类用来创建一个文件并向文件中写数据。
如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。
- public void close() throws IOException{}
关闭此文件输入流并释放与此流有关的所有系统资源。抛出IOException异常。 - protected void finalize()throws IOException {}
这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出IOException异常。 - public void write(int w)throws IOException{}
这个方法把指定的字节写到输出流中。 - public void write(byte[] w)
把指定数组中w.length长度的字节写到OutputStream中。
对文件的读写操作代码示例
将下面这个文件读出来,再写入另外一个目录下。即我们常说的复制操作。
有168mb还是挺大的
下面分别用三种代码实例,表现代码复制的各种优缺点
代码一:一个字节一个字节复制
//下面代码将ABSOLUTE_ROOT 目录下的targetFile 复制写出,再写入到targetFilePath 目录下
public static void main(String[] args) {
String targetFile = "dxc.mp4";//我的目标文件
String targetFilePath = "D:\\a\\";//写入的目录
String ABSOLUTE_ROOT = "E:\\abcd\\sdf\\nkunoi\\a\\b\\c\\";//目标文件的目录
File inFile = new File(ABSOLUTE_ROOT + targetFile);//打开目标文件
File outFile = new File(targetFilePath + targetFile);//打开写入文件
long startTime = System.currentTimeMillis();//开始复制的时间
try {
//该流用于从文件中读取数据
FileInputStream fis = new FileInputStream(inFile);
//该流用于从文件中读取数据
FileOutputStream fos = new FileOutputStream(outFile );
int value = fis.read();//从fis流读入一个字节
while(value != -1) {
fos.write(value);//将读入的value值写入fos流
value = fis.read();//读下一个字节
}
fis.close();//关闭文件
fos.close();//关闭文件
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();//复制结束
endTime -= startTime;//复制用时
System.out.println(endTime/1000 + "秒" +endTime%1000 + "毫秒");
}
此时CPU使用情况
整个程序运行时间
可以看到总共使用了十一分钟多才运行完整个程序。
再D:\a目录下复制的视频文件
代码二:直接读所有字节,再写出;
public static void main(String[] args) {
String targetFile = "dxc.mp4";
String targetFilePath = "D:\\a\\";
File inFile = new File("E:\\abcd\\sdf\\nkunoi\\a\\b\\c\\" + targetFile);
File outFile = new File(targetFilePath + targetFile);
long startTime = System.currentTimeMillis();
try {
FileInputStream fis = new FileInputStream(inFile);
FileOutputStream fos = new FileOutputStream(outFile );
long fileSize = inFile.length();//得到文件的大小
byte[] buffer = new byte[(int) fileSize];//申请文件大小的空间,
fis.read(buffer);//将文件写入byte[]里面;
fos.write(buffer); //将文件写出
fis.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
endTime -= startTime;
System.out.println(endTime/1000 + "秒" +endTime%1000 + "毫秒");
}
运行时间:
时间由十一分钟变到了466毫秒。速度提示非常的快
/
因为我们申请了足够大的空间,所有对内存的使用是很严重的,可以明显的看到,有个很大的跳变。如果写入的文件足够大,那么对内存的使用就直接爆炸了,所有这种方法我们也不可取。
有没有更好的方法,更快一点,并且对内存使用更温柔一点。
我们可以一次读出一点输了的文件,然后写入;再读出一定的字节,再写入;直到读完结束。
比如我们有十八个字节,我们可以一次读写四个字节;四次之后再读写两个字节,就可以结束了。
代码三:
public static void main(String[] args) {
final int BUFFER_SIZE = 1 << 16;//数组大小
String targetFile = "dxc.mp4";
String targetFilePath = "D:\\a\\";
File inFile = new File("E:\\abcd\\sdf\\nkunoi\\a\\b\\c\\" + targetFile);
File outFile = new File(targetFilePath + targetFile);
long startTime = System.currentTimeMillis();
try {
FileInputStream fis = new FileInputStream(inFile);
FileOutputStream fos = new FileOutputStream(outFile);
int fileSize = (int) inFile.length();
byte[] buffer = new byte[BUFFER_SIZE];//申请一定的空间
int readLen;
while (fileSize > 0) {
//先判断文件剩余大小,有没有数组大小大
//大于数组大小,就可以读写数组大小的长度;
//小于数组大小,就可以直接读写文件长度。
readLen = fileSize >= BUFFER_SIZE ? BUFFER_SIZE : fileSize;
//读写readLen大小的文件
readLen = fis.read(buffer, 0, readLen);
//文件总大小,减去已经读过的大小
fileSize -= readLen;
//写出文件
fos.write(buffer, 0, readLen);
}
fis.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
endTime -= startTime;
System.out.println(endTime/1000 + "秒" +endTime%1000 + "毫秒");
}
可以看下读写dxc.mp4用时大小
只用了102毫秒,可以说是非常快了
而且内存使用也很小
再读写文件这块,我们应该知到:不要一字节一字节的读写,太慢,也不能直接一下全读写完成,对内存使用太暴力。但我们可以设定大小,让它每次读写一定的长度,既能提高速率,也能避免对内存的暴力使用