Skip to content

1 File类

1.1 基本介绍

File类代表系统中的文件对象(文件或目录),位于java.io包下。

存储介质上的文件或目录在Java程序中都是用File类的实例来表示。

通过File类,可以实现对系统中文件或目录的操作,类似我们在操作系统中借助鼠标、快捷键等对文件或目录进行增删改的操作。

img

1.2 通过File类操作文件或目录

img

File类中常用方法

方法名称说明
boolean exists( )判断文件或目录是否存在
boolean isFile( )判断是否是文件
boolean isDirectory( )判断是否是目录
String getPath( )返回此对象表示的文件的相对路径名
String getAbsolutePath( )返回此对象表示的文件的绝对路径名
String getName( )返回此对象表示的文件或目录的名称
boolean delete( )删除此对象指定的文件或目录,如果是目录,必须为空才能删除
boolean createNewFile( )创建名称的空文件,不创建文件夹
public boolean mkdir()创建此路径名指定的目录
long length()返回文件的长度,单位为字节, 如果文件不存在,则返回 0L
public String[] list()返回目录中的文件和目录的字符串数组
java
public class App1 {
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        // windows 以盘符开始的路径 绝对路径
        //File file = new File("D:\\a.txt");
        File file = new File("D:/a.txt");
            
        //判断是否文件
        System.out.println(file.isFile());
        //判断是否是文件夹
        System.out.println(file.isDirectory());
        //得到文件或文件夹名称
        System.out.println(file.getName());
        //得到路径
        System.out.println(file.getPath());
        //得到绝对路径
        System.out.println(file.getAbsolutePath());
        //得到上一级路径
        System.out.println(file.getParent());
        //获取最后修改的时间,相对1970年开始的毫秒数
        System.out.println(file.lastModified());
    }
    
}
java
public class App2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

        File file = new File("D:/a.txt");
        //判断文件是否存在
        if(!file.exists()){

            // 创建文件,如果文件已经存在,返回false
            boolean ret = file.createNewFile();
            if (ret) {
                System.out.println("创建文件成功");
            } else {
                System.out.println("创建文件失败");
            }
        }else{
            System.out.println("文件已存在");
        }
        //删除文件
		file.delete();
        
		File file2 = new File("D:/test/text");
		
		if(!file2.exists()){
			// 创建路径
			// 如果路径中包含不存在的目录,创建失败
			boolean ret = file2.mkdir();
			System.out.println(ret);
			// 如果路径中包含不存在的目录,会一同创建
			ret = file2.mkdirs();
			System.out.println(ret);
		}else{
			System.out.println("文件夹已存在");
		}
		
		//删除目录,非空目录不能直接删除
		file2.delete();
		
		File f = new File("D:\\");
		//只会遍历一级目录,返回的是文件夹中的文件和子目录的名字
		String[] fileNames = f.list();
		for (String name : fileNames) {
			System.out.println(name);
		}
		//返回文件夹中的文件或目录的File对象数组
		File[] files = f.listFiles();
		for (File f1 : files) {
			System.out.println(f1);
		}
		
	}

}

2 IO流

I/O:Input/Output,输入/输出。

stream:流,数据流,是数据传输、通信的通道

Java应用程序中,“流”是基本的传输数据的方式。JDK提供了各种“流”来操作数据

img

img

2.1 基本介绍

2.1.1 流的分类

按流向分:

输入流:从数据源到程序中的流

输出流:从程序到数据源的流

img

img

按数据传输单位分:

字节流:以字节为单位传输数据的流

可以操作文本文件(.txt、.java等)、二进制文件(图片、音视频文件等)

字符流:以字符为单位传输数据的流

操作文本文件

2.1.2 Java中的流

JDK提供的流类位于java.io包中,主要继承自以下四种抽象父类

字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

img

我们需要关注的:

img

2.2 字节流

2.2.1 InputStream抽象类

输入流

方法
public abstract int read() throws IOException从输入流中读取数据的下一个字节,返回读到的字节值,若到达流的末尾,返回-1
public int read(byte[] b) throws IOException从输入流中读取数据到缓冲区数组b中,返回实际读到的字节总数
public int read(byte[] b, int off, int len) throws IOException读取 len 个字节的数据,并从数组b的off位置开始写入到该数组中
public void close() throws IOException关闭此输入流并释放与此流关联的所有系统资源

2.2.2 FileInputStream

该类是字节输入流InputStream的常用实现类。

构造方法如下:

方法
public FileInputStream(File file)根据一个file实例来创建FileInputStream对象
public FileInputStream(String name)根据文件名称来创建FileInputStream对象

操作流程:

img

1)一次读取一个字节的数据:

java
public class App {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		// 输入字节流
		FileInputStream fileInputStream = null;
		try {
			// 1 创建输入流的对象
			fileInputStream = new FileInputStream("D:/a.txt");
			
			// 2 进行操作      read() 一次读取一个字节 返回值为-1 表示读取结束
			/*
			 * int info = fileInputStream.read(); System.out.println(info); // 将ascii码强转为字符
			 * System.out.println((char)info);
			 * 
			 * info = fileInputStream.read(); System.out.println((char)info);
			 */
//			int info = -1;
//			while((info = fileInputStream.read()) != -1) {
//				System.out.println((char)info);
//			}
			
			int info = fileInputStream.read();
			while(info != -1) {
				System.out.println((char)info);
				info = fileInputStream.read();
			}
			
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if(fileInputStream != null) {
				try {
					// 3 关闭流对象
					fileInputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		
	}

}

2)将数据读到字节数组中:

java
public class App2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		FileInputStream inputStream = null;
		
		try {
			inputStream = new FileInputStream("D:/a.txt");
			
			byte[] buff = new byte[1024];
			// 将数据读到字节数组里,read(byte[]) 返回值表示读取的字节的长度
			int length = inputStream.read(buff);
			System.out.println(length);
			
			// 将字节数组转为字符串
			// 第一个参数:待转换的字节数组;第二个参数:起始位置;第三个参数:转换的长度
			String info = new String(buff, 0, length);
			System.out.println(info);
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				inputStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

2.2.3 OutputStream抽象类

输出流,OutputStream常用方法

方法
public abstract void write(int b) throws IOException将指定的字节写入此输出流
public void write(byte[] b) throws IOException将 b.length 个字节从指定的 byte 数组写入此输出流
public void write(byte[] b, int off, int len) throws IOException将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流
public void flush() throws IOException刷新此输出流并强制写出所有缓冲的输出字节
pulbic void close() throws IOException关闭此输出流并释放与此流有关的所有系统资源(含刷新操作)

2.2.4 FileOutputStream

该类是字节输出流OutputStream的常用实现类。构造方法如下:

方法
public FileOutputStream(File file)根据一个file实例来创建FileOutputStream对象
public FileOutputStream(File file, boolean append)根据一个file实例来创建输出流对象,指定是否可追加
public FileOutputStream(String name)根据文件名称来创建FileOutputStream对象
public FileOutputStream(String name, boolean append)根据一个file实例来创建输出流对象,指定是否可追加

操作步骤:

img

1)基本用法

java
public class App {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		
		FileOutputStream outputStream  = null;
		
		try {
			// 默认是覆盖写,将原来的内容删除,重新写入
			// outputStream = new FileOutputStream("D:/b.txt");
			// 第二个参数,表示是否采用追加写的方式 
			outputStream = new FileOutputStream("D:/b.txt", true);
			// write参数表示的一个字节数据
			outputStream.write('a');
			outputStream.write(97);
			
			String s = "hahaha今天天气不错";
			// String中的getBytes() 将字符串转换为字节数组
			outputStream.write(s.getBytes());
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				outputStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}

2)文件拷贝

java
public class FileCopy {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 读取文件
		FileInputStream inputStream = null;
		// 写入文件
		FileOutputStream outputStream = null;
		
		try {
			inputStream = new FileInputStream("D:/123.png");
			outputStream = new FileOutputStream("D:/456.png");
			
			// 存放读取的数据,长度不能太大
			byte[] buff = new byte[1024];
			// 读取的长度
			int length = -1;
			while((length = inputStream.read(buff)) != -1) {
				outputStream.write(buff, 0, length);
			}
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				inputStream.close();
				outputStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}

2.3 字符流

2.3.1 Reader抽象类

字符输入流,用于向程序中输入数据,且数据的单位为字符。

主要方法:

int read( )

int read(char[] c)

read(char[] c,int off,int len)

void close( )

2.3.2 FileReader

构造方法

FileReader(File file)

FileReader(String fileName)

java
public class FileReaderApp {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		FileReader fileReader = null;
		try {
			// 如果编码格式不一致,会有乱码问题。
			// 解决方案:使用InputStreamReader;或者想办法保持编码一致
			fileReader = new FileReader("D:/a.txt");
			int read = fileReader.read();
			System.out.println((char)read);
			
			char[] buff = new char[1024];
			int length = fileReader.read(buff);
			System.out.println(new String(buff, 0, length));
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				fileReader.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}

2.3.3 BufferedReader

字符缓冲输入流

缓冲流中定义了一个缓冲数组,类似我们讲FileInputStream时,定义的自己数组,

使用缓冲数组后,整体的读取/写入效率提升很大

所有的缓冲流都没有任何的读取、写入文件能力,都需要借助对应的输入流和输出流来提供对应的能力。

在创建缓冲流流对象时,需要传入对应的输入流对象和输 出流对象。

缓冲流底层只是提供了一个默认大小的缓冲数组,用于提高效率

构造方法

BufferedReader(Reader in)

增加了 String readLine() ,用于读取一行数据,如果文件结束,返回null

java
public class BufferedReaderApp {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		FileReader fileReader = null;
		BufferedReader bufferedReader = null;
		try {
			fileReader = new FileReader("b.txt");
			// 参数是Reader对象
			bufferedReader = new BufferedReader(fileReader);
			// 读取一行数据
			String info = bufferedReader.readLine();
			System.out.println(info);
			
			// readLine返回null,表示读取结束
			while((info = bufferedReader.readLine()) != null) {
				System.out.println(info);
			}
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				bufferedReader.close();
				fileReader.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

2.3.4 Writer抽象类

字符输出流,用于程序向外输出数据,且数据的单位为字符

主要方法:

void write(int c)

void write(char[] carr)

void write(char[] carr, int off, int len)

void write(String str)

void flush() / close()

2.3.5 FileWriter

构造方法

FileWriter(File file)

FileWriter(File file, boolean append)

FileWriter(String fileName)

FileWriter(String fileName, boolean append)

java
public class FileWriterApp {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		FileWriter fileWriter = null;
		try {
			fileWriter = new FileWriter("c.txt", true);
			fileWriter.write("又翻车了");
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				fileWriter.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}

2.3.6 BufferedWriter

字符缓冲输出流:该类为字符输出流Writer的缓冲流。

构造方法:

BufferedReader(Writer out)

增加了void newLine() ,用于换行

java
public class BufferedWriterApp {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		FileWriter fileWriter = null;
		// 效率相对高
		BufferedWriter bufferedWriter = null;
		try {
			fileWriter = new FileWriter("c.txt");
			bufferedWriter = new BufferedWriter(fileWriter);
			
			// 写到缓冲区里。如果缓冲区满了;调用flush();流close() 都会将数据写入文件
			bufferedWriter.write("hahahahah");
			
			// 刷新缓冲区,将数据写入文件
			bufferedWriter.flush();
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				// 关闭流的时候,如果缓冲区中有数据,将数据写入文件
				bufferedWriter.close();
				fileWriter.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}

2.4 转换流 (了解)

转换流用于字节流和字符流之间的转换。

JDK中的IO流,分为字节流、字符流。如果需要进行二者之间的转换,可以使用转换流。

img

2.4.1 InputStreamReader:

Reader的子类,将输入的字节流变为字符流,即:将一个字节流的输入对象变为字符流的输入对象

InputStreamReaderI是字节流通向字符流的桥梁,需要和InputStream“套接”

java
public class InputStreamReaderApp {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		FileInputStream fileInputStream = null;
		InputStreamReader inputStreamReader = null;
		try {
			
			fileInputStream = new FileInputStream("a.txt");
			// 转换流 ,类似字节流和字符流之前的桥梁
			inputStreamReader = new InputStreamReader(fileInputStream);
			
			// 一次读取一个字符,返回值表示读取的字符
			int read = inputStreamReader.read();
			System.out.println((char)read);
			
			char[] buff = new char[1024];
			// 返回值表示读取的字符的长度(个数)
			int length = inputStreamReader.read(buff);
			System.out.println(new String(buff, 0, length));
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				// 流对象之间如果有调用关系,一般建议后创建的先close
				inputStreamReader.close();
				fileInputStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}

通过转换流可以解决编码不一致的问题

java
public class InputStreamReaderApp2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		FileInputStream fileInputStream = null;
		InputStreamReader inputStreamReader = null;
		try {
			
			fileInputStream = new FileInputStream("utf8.txt");
			// 默认eclipse用的gbk编码,一个中文字符占2个字节,如果读的文件是其他编码,比如utf-8,中文字符占3个字节
			// 编码格式不一致,转换的时候,引起乱码问题
			// inputStreamReader = new InputStreamReader(fileInputStream);
			
			// 第二个参数,表示按照指定的格式转换字节流,解决乱码问题
			inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
			
			// 一次读取一个字符,返回值表示读取的字符
			int read = inputStreamReader.read();
			System.out.println((char)read);
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				// 流对象之间如果有调用关系,一般建议后创建的先close
				inputStreamReader.close();
				fileInputStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}

2.4.2 OutputStreamWriter:

Writer的子类,将输出的字符流变为字节流,即:将一个字符流的输出对象变为字节流的输出对象

OutputStreamWriter是字符流通向字节流的桥梁,需要和OutputStream“套接”

java
public class OutputStreamWriterApp {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		OutputStream outputStream = null;
		OutputStreamWriter outputStreamWriter = null;
		try {
			outputStream = new FileOutputStream("c.txt");
			outputStreamWriter = new OutputStreamWriter(outputStream);
			// 参数可以是字符串 write 覆盖写
			outputStreamWriter.write("hello world你好世界");
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				outputStreamWriter.close();
				outputStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

2.5 对象流 (了解)

2.5.1 序列化、反序列化

序列化:把对象转换为字节序列的过程称为对象的序列化

反序列化:把字节序列恢复为对象的过程称为对象的反序列化

img

JDK提供ObjectOutputStream和ObjectInputStream类,用于对象的序列化、反序列化

ObjectOutputStream:保存对象状态到文件,序列化

ObjectInputStream:读取对象二进制文件到内存,反序列化

2.5.2 ObjectOutputStream

构造方法

public ObjectOutputStream(OutputStream out)

public ObjectInputStream(InputStream in)

注意:

能被序列化的对象所对应的类必须实现java.io.Serializable接口

读入的顺序必须和写出的顺序一致

transient(暂态的)关键字:修饰成员变量时,该成员变量将不被序列化,读取的值为null

java
//序列化的类,必须实现Serializable接口,该接口中没有任何方法
//序列化类中的成员变量如果是引用类型,必须支持序列化
public class Dog implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	
	//如果某个成员不需要序列化,可以使用transient修饰
	
	public Dog(String name, int age){
		this.name = name;
		this.age = age;
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return this.name + " " + this.age + " " + this.toy;
	}
}
java
public class Demo {

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		// TODO Auto-generated method stub
		writeObject();
	}
	
	private static void writeObject() throws IOException{
		
		//参数为字节输出流
		ObjectOutputStream oo = new ObjectOutputStream(
				new FileOutputStream("D:/o.txt"));
		
		Dog dog = new Dog("wangcai", 5);
		oo.writeObject(dog);
		
		oo.close();
	}

}

2.5.3 ObjectInputStream

java
public class Demo {

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		// TODO Auto-generated method stub
		readObject();
	}
	
	private static void readObject() throws IOException, ClassNotFoundException{
		ObjectInputStream oi = new ObjectInputStream(
				new FileInputStream("D:/o.txt"));
		
		Dog dog = (Dog)oi.readObject();
		
		System.out.println(dog);
		
		oi.close();
	}

}