File类即可描述真实文件,也可描述文件夹(目录)
File类是java.io包中唯一一个与文件本身操作(创建、删除、取得信息)有关,与文件内容无关的程序类
File类的常用构造方法:
public File(String pathname); //pathname:文件的绝对路径
public File(String parent,String child);//parent:文件的父路径 child:文件的子路径
public boolean createNewFile() throws IOException
import java.io.File;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
//取得File对象,此处的路径为绝对路径
File file = new File("C:\\Users\\79024\\Desktop\\java.txt");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public boolean delete();
import java.io.File;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
//取得File对象
File file = new File("C:\\Users\\79024\\Desktop\\java.txt");
//判断文件是否存在 此方法也可判断文件夹是否存在
if(file.exists())
{
file.delete();
}else{
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
路径分隔符:File.separator
用于替换路径中的\
import java.io.File;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
//取得File对象
File file = new File("C:"+File.separator+"Users"+
File.separator+"79024"+File.separator+
"Desktop"+ File.separator+"java.txt");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public String getParent();
public File getParentFile();
无论有多少级父目录都会一次性创建public boolean mkdirs();
import java.io.File;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
//取得File对象
File file = new File("C:"+File.separator+"Users"+
File.separator+"79024"+File.separator+
"Desktop"+ File.separator+
"www"+File.separator+"java"+File.separator+"java.txt");
//取得父路径对象
File parentFile = file.getParentFile();
//如果父路经不存在 -- 创建父路径
//父文件即C:\Users\79024\Desktop\www\java
if(!parentFile.exists()){
//无论有多少级父目录都一次性创建
parentFile.mkdirs();
}
//如果文件存在 删除
if(file.exists()){
file.delete();
}else{
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public boolean isFile(); //判断路径是否是文件
public long length();//取得文件大小
public long lastModified();//取得最后修改日期
import java.io.File;
import java.util.Date;
public class Test {
public static void main(String[] args) {
//取得File对象
File file = new File("C:" + File.separator + "Users" +
File.separator + "79024" + File.separator +
"Desktop" + File.separator + "happy.png");
//如果路径存在 且 路径是一个文件
//输出文件的大小(字节)以及最后的修改时间(1970年开始的时间戳)
if(file.exists()&&file.isFile()){
System.out.println(file.length());
System.out.println(file.lastModified());
//最后的修改时间以能看懂的形式显示
System.out.println(new Date(file.lastModified()));
}
}
}
对目录的操作:
public boolean isDirectory();//判断路径是否是目录
public File[] listFile();//列举一个目录的全部组成
import java.io.File;
public class Test {
public static void main(String[] args) {
//取得File对象
File file = new File("C:" + File.separator + "Users" +
File.separator + "79024" + File.separator +
"Desktop");
//如果路径存在且路径是一个目录
//列举该目录下的文件和目录
if(file.exists()&&file.isDirectory()){
//只展开一层
File[] files = file.listFiles();
for(File file1:files){
System.out.println(file1);
}
}
}
}
如果目录的全部组成下还有目录递归展示:
import java.io.File;
public class Test {
public static void main(String[] args) {
//取得File对象
File file = new File("C:" + File.separator + "Users" +
File.separator + "79024" + File.separator +
"Desktop");
listAllFiles(file);
}
public static void listAllFiles(File file){
/**
* 如果路径存在且路径是一个文件直接输出
*/
if(file.exists()&&file.isFile()){
System.out.println(file);
}else{
//此时file对象为目录
File[] files = file.listFiles();
for(File file1:files){
listAllFiles(file1);
}
}
}
}
IO相关处理属于阻塞式耗时操作。一般放在子线程中进行
import java.io.File;
public class Test {
public static void main(String[] args) {
System.out.println("主线程开始");
new Thread(()->{
//取得File对象
File file = new File("C:" + File.separator + "Users" +
File.separator + "79024" + File.separator +
"Desktop");
System.out.println("遍历文件开始...");
long start = System.currentTimeMillis();
listAllFiles(file);
long end = System.currentTimeMillis();
System.out.println("遍历文件结束,共耗时"+(end-start));
}).start();
System.out.println("主线程结束");
}
public static void listAllFiles(File file){
/**
* 如果路径存在且路径是一个文件直接输出
*/
if(file.exists()&&file.isFile()){
System.out.println(file);
}else{
//此时file对象为目录
File[] files = file.listFiles();
for(File file1:files){
listAllFiles(file1);
}
}
}
}
流的分类:
无论是字节流还是字符流,操作流程几乎一样,以文件操作为例:
1.取得File对象
2.取得File对象的输入、输出流
3.进行数据的读取或写入
4.关闭流(close)
IO操作属于资源处理,所有资源处理(IO、数据库、网络)使用后都必须关闭
//抽象类
public abstract class OutputStream implements Closeable, Flushable
Closeable:public void close() throws IOException;
Flushable:void flush() throws IOException;
public void write(byte[] b)throws IOException; //将指定的字节数组全部输出
public void write(byte[] b,int offset,int len)throws IOException;//将部分字节数组输出
public abstract void write(int b)throws IOException;//输出单个字节
要进行文件内容的输出:使用FileOutputStream子类
public FileOutputStream(File file) throws FileNotFoundException //文件内容的覆盖
public FileOutputStream(File file, boolean append)throws FileNotFoundException //文件内容的追加
当使用FileOutoutStream进行文件内容输出时,只要文件的父路径存在,FileOutputStream会自动创建文件
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException {
//1.取得File对象
File file = new File("C:"+File.separator+"Users"+File.separator+
"79024"+File.separator+"Desktop"+File.separator+"java.txt");
//---------------------------------------------------------- 以下内容可写可不写
//如果文件不存在 则创建
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
//--------------------------------------------------------------
//2.取得File的输出 文件内容的追加
OutputStream out = new FileOutputStream(file,true);
//3.进行数据的输出
String msg ="好好学习\n";
out.write(msg.getBytes());
//4.关闭流
out.close();
}
}
public abstract class InputStream implements Closeable
Closeable:public void close() throws IOException;
public int read(byte b[]) throws IOException; //读取数据到字节数组b中
1.返回b的长度:当被读取的数据大小>字节数组大小 返回字节数组大小
2.返回一个大于0的数但是小于b长度: 被读取的数据大小<字节数组大小 返回真正读取的个数
3.返回-1: 数据读取完毕
可以将被读取的数据看作稀饭,将字节数组的大小看作勺子
public abstract int read() throws IOException;//读取单个字节
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException {
//1.取得File对象
File file = new File("C:"+File.separator+"Users"+File.separator+
"79024"+File.separator+"Desktop"+File.separator+"java.txt");
//2.取得输入流
InputStream in = new FileInputStream(file);
//3.进行数据的写入 将数据写入data数组中
byte[] data = new byte[1024];
int result = in.read(data);
System.out.println(result);
//将字节数组转为字符串
System.out.println(new String(data,0,result));
//4.关闭流
in.close();
}
}
无论是字节输出流还是字符输出流都是write方法,但是字符输出流多了一个传入String对象的方法public void write(String str) throws IOException
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException {
//1.取得File对象
File file = new File("C:" + File.separator + "Users" + File.separator +
"79024" + File.separator + "Desktop" + File.separator + "java.txt");
//2.取得输出流
Writer writer = new FileWriter(file,true);
//3.写入数据
String str = "好好学习";
writer.write(str);
//4.关闭流
writer.close();
}
}
Reader类中没有方法可以直接读取字符串,只能通过字符数组来读取public int read(char b[]) throws IOException; //读取数据到字符数组b中
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException {
//1.取得File对象
File file = new File("C:" + File.separator + "Users" + File.separator +
"79024" + File.separator + "Desktop" + File.separator + "java.txt");
//2.取得输出流
Reader reader = new FileReader(file);
//3.数据写入
char[] data = new char[1024];
int result = reader.read(data);
System.out.println(result);
System.out.println(new String(data,0,result));
//4.关闭流
reader.close();
}
}
从实际开发来讲,字节流优先考虑,只有处理中文时才会考虑字符流
所有字符流操作,无论是写入还是输出,数据都先保存在缓存中,如果不关闭流,则数据不会写入或者读出
字节流–>字符流
转换流用于将底层的字节流转为字符流供子类w使用
OutputStreamWriter:字节输出流--->字符输出流
InputStreamReader:字节输入流--->字节输出流
import java.io.*;
public class Test{
public static void main(String[] args) throws IOException {
//1.取得文件对象
File file = new File("C:"+File.separator+"Users"+File.separator+
"79024"+File.separator+"Desktop"+File.separator+"java.txt");
//2.取得文件的输出流
OutputStream outputStream = new FileOutputStream(file);
//字节流--->字符流
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
//3.进行数据的输出
outputStreamWriter.write("好好学习");
//4.关闭流
outputStreamWriter.close();
}
}
import java.io.*;
public class Test{
public static void main(String[] args) throws IOException {
String sourceFilePath = "C:\\Users\\79024\\Desktop\\哈.png";
String destFilePath="C:\\Users\\79024\\Desktop\\嘿.png";
System.out.println( copyFile(sourceFilePath,destFilePath));
}
/**
* 文件拷贝
* @param sourceFilePath
* @param destFilePath
* @return
*/
public static boolean copyFile(String sourceFilePath,String destFilePath) throws IOException {
//1.取得File对象
File sourceFile = new File(sourceFilePath);
File destFile = new File(destFilePath);
//2.取得输入输出流
/**
* 由于是将源文件拷贝到目标文件中
* 即需要先将源文件中的数据输入到缓冲区中 ,然后将数据输出到目标文件
* 所以源文件对应字节输入流
* 目标文件对应字节输出流
*/
InputStream in = new FileInputStream(sourceFile);
OutputStream out = new FileOutputStream(destFile);
//3.数据的输入、输出
long start = System.currentTimeMillis();
int len = 0;
/**
* in.read() 读取单个字节 该方法有返回值
* 返回值==-1即数据读取完毕
* write(len)输出单个字节
*/
while ((len = in.read()) != -1) {
out.write(len);
}
long end = System.currentTimeMillis();
System.out.println("文件拷贝耗时:" + (end - start) + "毫秒");
in.close();
out.close();
return true;
}
}
由于一个字节一个字节的读取太过于耗时,所以修改输入方式,即增加缓冲区:
import java.io.*;
public class Test{
public static void main(String[] args) throws IOException {
String sourceFilePath = "C:\\Users\\79024\\Desktop\\哈.png";
String destFilePath="C:\\Users\\79024\\Desktop\\嘿.png";
System.out.println( copyFile(sourceFilePath,destFilePath));
}
/**
* 文件拷贝
* @param sourceFilePath
* @param destFilePath
* @return
*/
public static boolean copyFile(String sourceFilePath,String destFilePath) throws IOException {
//1.取得File对象
File sourceFile = new File(sourceFilePath);
File destFile = new File(destFilePath);
//2.取得输入输出流
/**
* 由于是将源文件拷贝到目标文件中
* 即需要先将源文件中的数据输入到缓冲区中 ,然后将数据输出到目标文件
* 所以源文件对应字节输入流
* 目标文件对应字节输出流
*/
InputStream in = new FileInputStream(sourceFile);
OutputStream out = new FileOutputStream(destFile);
//3.数据的输入、输出
long start = System.currentTimeMillis();
int len = 0;
/**
* in.read() 读取单个字节 该方法有返回值
* 返回值==-1即数据读取完毕
* write(len)输出单个字节
*/
byte[] data = new byte[1024];
while ((len = in.read(data)) != -1) {
out.write(data,0,len);
}
long end = System.currentTimeMillis();
System.out.println("文件拷贝耗时:" + (end - start) + "毫秒");
in.close();
out.close();
return true;
}
}