目录
1.File类
文件和目录路径名的抽象表示
一个File类的对象,表示计算机硬盘上的一个文件和目录
1.1 File的构造方法
- File f = new File("E:/test.txt");
- File f1 = new File("E:","学习哦");
- File pf = new File("E:");
- File cf = new File(pf,"学习哦");
1.2 File的常用方法
import java.io.IOException;
public class FileDemo1 {
public static void main(String[] args) {
// 一个File类的对象
File f = new File("E:/test.txt");
// File类的常用方法:
System.out.println(f.canRead());//读 true
System.out.println(f.canWrite());//写 true
System.out.println(f.getPath());//绝对路径 E:\test.txt
System.out.println(f.getName());//文件名 test.txt
System.out.println(f.getParent());//父级 E:\
System.out.println(f.length());//长度(以字节为单位) 79
System.out.println(f.isFile());//文件是否存在 true
System.out.println(f.isDirectory());//是否为目录 false
System.out.println(f.isAbsolute());//是否为绝对路径 true
System.out.println(f.isHidden());//是否为隐藏 false
System.out.println(f.exists());//是否存在 true
System.out.println(f.lastModified());//最后一次修改时间 1639734309196
try {
System.out.println(f.createNewFile());//创建新的文件 false
} catch (IOException e) {
e.printStackTrace();
}
//删除文件
f.delete();
}
}
1.3 文件夹的常用方法
- f.mkdir();//创建文件夹(单级)
- f.mkdirs();//创建多级文件夹
- f.delete();//删除多级文件夹时,一次只能删除一级目录且目录为空
附加: 遍历文件夹目录
方法一
import java.io.File;
public class FilePractice {
public static void Directory(File f){
String[] fs = f.list();
for (String fileName : fs) {
System.out.print(fileName + ",");
}
}
public static void show(File f){
File[] fs = f.listFiles();
for (File fileName : fs) {
if(fileName.isDirectory()){
Directory(fileName);
System.out.println();
}else{
System.out.println(fileName);
}
}
}
public static void main(String[] args) {
File f = new File("E:\\学习哦");
show(f);
}
}
方法二(这个更加简便)
import java.io.File;
public class FilePractice {
public static void getAllFile(File f) {
System.out.println(f);
File[] fi = f.listFiles();
for (File fs : fi) {
if (fs.isDirectory()) {
getAllFile(fs);
} else {
System.out.println(fs);
}
}
}
public static void main(String[] args) {
File f = new File("E:\\学习哦");
getAllFile(f);
}
}
2. 输入与输出概念
I ——> input 输入 把电脑硬盘上的文件(数据)读入到程序中(进行读操作)
O ——> output 输出 把程序中的数据写到目标地址中(进行写操作)
例图:
3. 字节流与字符流
字节流:每次读取数据时是以字节为单位读写
字节输入流:InputStream的子类 (例:FileInputStream)
字节输出流:OutputStream的子类(例:FileOutputStream)
字符流:每次以字符为单位进行读写操作
字符入流 Reader的子类(例:FileReader)
字符出流 Writer的子类(例:FileWrite)
3. 1 IO流的常用方法
● InputStream的基本方法
创建字节输入流对象,接入到指定的文件上,如果找不到文件,抛出异常(throws FileNotFoundException)
FileInputStream in = new FileInputStream("D:/test.txt") ;
读取一个字节并以整数的形式返回(0~255), 如果返回-1已到输入流 的末尾。
int read() throws IOException
读取一系列字节并存储到一个数组buffer, 返回实际读取的字节数,如果读取前已到输入流的末尾返回-1
int read(byte[] buffer) throws IOException
关闭流释放内存资源
void close() throws IOException
● OutputStream的基本方法
创建一个字节输出流对象,同时创建一个空文件,如果路径不对,抛出异常(throws FileNotFoundException)
FileOutputStream out = new FileOutputStream("E:/test.txt");
向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException
将一个字节类型的数组中的从指定位置(off)开始的 len个字节写入到输出流
void write(byte[] b, int off, int len) throws IOException
关闭流释放内存资源 void close() throws IOExceptio
3.2 文件的复制
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo {
public static void main(String[] args) {
// 把D盘中的“test.txt”文件内容(abcdefg)复制到 E盘中的“test.txt”文件
FileInputStream in = null;
FileOutputStream out = null;
try {
//创建字节输入流对象,接入到指定的文件上,如果找不到文件,抛出异常
// FileInputStream in = new FileInputStream("D:/test.txt");
in = in = new FileInputStream("D:/test.txt");
// 创建一个字节输出流对象,同时创建一个空文件,如果路径不对,会报异常
// FileOutputStream out = new FileOutputStream("E:/test.txt");
out = new FileOutputStream("E:/test.txt");
int a = 0;
// in.read() 返回为int类型,如果文件读完后返回 -1
while ((a = in.read() )!= -1){
out.write(a);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("系统找不到指定文件夹");
} catch (IOException e) {
e.printStackTrace();
System.out.println("读或写出现异常");
}finally {
// 在此处不能直接在异常中调用文件输入/输出字节流,
// 所以我们在开始创建文件输入/输出字节流
// 关闭文件输入/输出字节流
try {
if(in != null) {
in.close();
}
if(out != null){
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
第一种
以字节为单位对字符进行输入输出,有多少字节就进行多少次输入输出
int a = 0;
while ((a = in.read() )!= -1){
out.write(a);
}
第二种
使用容器来对字符进行输入输出
byte[] bytes = new byte[10];
int size = 0; //表示实际长度
while((size = in.read(bytes)) != -1){
System.out.println(size); //数组每次最大可以装 bytes.length 个
out.write(bytes, 0, size); //一般从 0 开始从数组的指定位置开始,写出实际装入的个数
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream("D:/test.txt");
FileOutputStream out = new FileOutputStream("E:/test.txt");
// in.read() 返回为int类型,如果文件读完后返回 -1
// 第一种 以字节为单位对字符进行输入输出,有多少字节就进行多少次输入输出
/*int a = 0;
while ((a = in.read() )!= -1){
out.write(a);
}*/
//第二种
// int c = in.read(b);//返回的也是int值,表示实际向数组中装入字节的个数
//使用容器来对字符进行输入输出
byte[] bytes = new byte[10];
int size = 0;//表示实际长度
while((size = in.read(bytes)) != -1){
System.out.println(size);//数组每次最大可以装 bytes.length 个
//一般从 0 开始从数组的指定位置开始,写出实际装入的个数
out.write(bytes, 0, size);
}
in.close();
out.close();
}
}
3.3 字节流和字符流两种读写速度的比较
public class FilePractice1 {
public static void main(String[] args) throws IOException {
FileInputStream in1 = null;
FileOutputStream out1 = null;
in1 = new FileInputStream("E:/feige.exe");
out1 = new FileOutputStream("E:/学习哦/feige.exe");
long s1 = System.currentTimeMillis();
int a = 0;
while((a = in1.read()) != -1){
out1.write(a);
}
long e1 = System.currentTimeMillis();
System.out.println("第一种读写:" + (e1 - s1)); //第一种读写:21486
if(in1 != null)
in1.close();
if(out1 != null)
out1.close();
FileInputStream in2 = null;
FileOutputStream out2 = null;
in2 = new FileInputStream("E:/feige.exe");
out2 = new FileOutputStream("E:/学习哦/feige.exe");
long s2 = System.currentTimeMillis();
byte[] bytes = new byte[100];
int size = 0;
while((size = in2.read(bytes)) != -1){
out2.write(bytes,0,size);
}
long e2 = System.currentTimeMillis();
System.out.println("第二种读写:" + (e2 - s2)); //第二种读写:305
if(in2 != null)
in2.close();
if(out2 != null)
out2.close();
}
}
4. 节点流和处理流
节点流
流对象中直接包含的就是数据,并对数据进行操作(如文件、字符串、字符串数组等)
例:FileInputStream in = new FileInputStream("D:/test.txt");
FileOutputStream out = new FileOutputStream("E:/test.txt");
处理流
处理流中包含的是其他的流的对象(节点) 可以缓冲区功能
bout.flush();//刷新缓冲区
import java.io.*;
public class Demo3 {
public static void main(String[] args) throws IOException {
//节点流:直接包含数据,对数据进行操作
FileInputStream in = new FileInputStream("D:/test.txt");
FileOutputStream out = new FileOutputStream("E:/test.txt");
//创建处理流(包装流)
/*
底层有一个缓冲数组,每次读到的数据线存入到缓冲数组中,等缓冲数组满后再实际操作,
一旦自己定义的数组长度大于缓冲区数组大小,缓冲区是数据就失效了
*/
BufferedInputStream bin = new BufferedInputStream(in);
BufferedOutputStream bout = new BufferedOutputStream(out);
byte[] bytes = new byte[1024];
int size = 0;
while((size = bin.read(bytes)) != -1){
bout.write(bytes, 0, size);
}
bin.close();
bout.flush();//刷新缓冲区
bout.close();
}
}
4.1 文件夹的合并和分割(1MB大小)
分割
public static void Splits(File f) throws IOException {
int m = 1024*1024;
long num = 0;
if((f.length()% m ) == 0 ){
num = f.length() / m;
}else{
num = (f.length() / m) + 1;
}
System.out.println(num);
int count = 0;
FileInputStream in = new FileInputStream(f);
for (int i = 0; i < f.length(); i++) {
FileOutputStream out = new FileOutputStream("E:/temp/temp"+ i );
byte[] bytes = new byte[1024];
int size = 0;
while((size = in.read(bytes)) != -1){
out.write(bytes, 0, size);
count += size;
}
if(count == num){
out.close();
count = 0;
break;
}
}
in.close();
}
合并
public static void Join(File temp) throws IOException {
FileOutputStream out = new FileOutputStream("E:/feige.exe");
File fl = new File(String.valueOf(temp));
File[] fs = fl.listFiles();
for (int i = 0; i < fs.length; i++) {
FileInputStream in = new FileInputStream("E:/temp/temp"+ i );
byte[] bytes = new byte[1024];
int size = 0;
while((size = in.read(bytes)) != -1){
out.write(bytes, 0, size);
}
in.close();
}
out.close();
for (File f: fs
) {
f.delete();
}
fl.delete();
}
主线程
public static void main(String[] args) throws IOException {
File f = new File("E:/feige.exe");
Splits(f);
Join(f);
}
5. 输入输出字符流
每次读取单位为字符,字符流只能读取文本文件(.txt,.java,.html)
计算机上的文件存储都是字节,字符流每次之所以能读到一个字符,通过转换流,将读到的字节结合指定的字符编码转为字符
例:
Reader ---> InputStreamReader(转换流) ---> FileReader
Writer ---> InputStreamWriter(转换流) ---> FileWriter
方法一:每次可以读有个字符,进行输入输出字符
read() 每次直接可以读到一个字符的编码,一个中文由三个字节组成。
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Demo1 {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("D:/test.txt");
FileWriter writer = new FileWriter("E:/test.txt");
int c = reader.read();
// read() 每次直接可以读到一个字符的编码,一个中文由三个字节组成
while((c = reader.read())!= -1){
writer.write(c);
}
reader.close();
writer.close();
}
}
方法二:使用容器进行输入输出字符流(使用Char数组)
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Demo {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("D:/test.txt");
FileWriter writer = new FileWriter("E:/test.txt");
char[] chars = new char[100];
int size = 0;
while((size = reader.read(chars))!= -1){
writer.write(chars,0,size);
}
reader.close();
writer.close();
}
}
方法三:使用缓冲字符输入输出流
import java.io.*;
public class Demo2 {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("D:/test.txt");
FileWriter writer = new FileWriter("E:/test.txt",true);
BufferedReader breader = new BufferedReader(reader);
BufferedWriter bwrite = new BufferedWriter(writer);
String s = null;
// readLine() 每次读一行数据,读完返回 null
while((s=breader.readLine())!= null){
bwrite.write(s);
bwrite.newLine();//换行
}
breader.close();
bwrite.close();
}
}
6. Print流(打印流)
定义:只做输出,不做输入。(单向的从程序中向外输出)
底层都是使用write();
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class PrintDemo {
public static void main(String[] args) throws FileNotFoundException {
PrintWriter pw = new PrintWriter("D:/test.txt");
pw.print("abc"); //输出字符串
pw.println("cad"); //换行输出
pw.write("def"); //打印字符串
}
}
7. 对象输入输出流
定义:对象的输入输出流,将对象信息写入文件中,做到持久保存(序列化)
对象:程序运行时,创建的对象
7.1 对象输出
对象序列化:将程序运行时,创建的对象输出到指定的文件中,持久保存
public class Demo3 {
public static void main(String[] args) throws IOException {
Date date = new Date();
String s = "abcd";
FileOutputStream fout = new FileOutputStream("E:/test.txt");
ObjectOutputStream out = new ObjectOutputStream(fout);
out.writeObject(date);
out.writeObject(s); //对象序列化
out.close();
}
}
7.2 对象输入
import java.io.*;
import java.util.Date;
public class Demo3 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream in = new FileInputStream("E:/test.txt");
ObjectInputStream oin = new ObjectInputStream(in);
Date date = (Date) oin.readObject();
String s = (String)oin.readObject();
System.out.println(date);//Sat Dec 18 18:58:43 CST 2021
System.out.println(s);//abcd
oin.close();
}
}
7.3 自定义对象进行序列化
实现 Serializable 为类生成一个编号(唯一的)
private static final long serialVersionUID = 1712358556364516246L;
如果不显示的声明此编号,运行时会默认生成一个,如果类一旦发生变化,编号也会改变
自定义:User类
import java.io.Serializable;
public class User implements Serializable {
/*
实现 Serializable
为类生成一个编号(唯一的)
private static final long serialVersionUID = 1712358556364516246L;
如果不显示的声明此编号,运行时会默认生成一个,如果类一旦发生变化,编号也会改变
*/
private static final long serialVersionUID = 1712358556364516246L;
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
对象输出
import java.io.*;
public class ObjectOutputDeno {
public static void main(String[] args) throws IOException, ClassNotFoundException {
User user = new User(1001, "小段");
FileOutputStream fout = new FileOutputStream("E:/test.txt");
ObjectOutputStream out = new ObjectOutputStream(fout);
out.writeObject(user);
out.close();
}
}
对象输入
import java.io.*;
public class ObjectOutputDeno {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream in = new FileInputStream("E:/test.txt");
ObjectInputStream oin = new ObjectInputStream(in);
User user = (User) oin.readObject();
System.out.println(user);
oin.close();
}
}