一.理清字符流与字节流
通俗理解:对于图片/视频类的数据用字节流传输;对于汉字类的文本用字节流传输
各方法辨析:
文件 | 目录 | 多级目录 | ||
创建新文件new一个,使用File类 | file | mdir | mdirs | |
字节流 | 字符流 | |||
流用来传输数据(in与read相关;out与write相关) | FileInputStream与FileOutputStream | 缓冲流 BufferedInputStream与BufferedOutputStream | OutputStreamWriter与InputStreamReader | 缓冲流 BufferedWriter与BufferedReader |
相关读写操作 | 读操作写操作 | |||
直接写入; 每次读取一个字节或数组 | 读写操作相似 | 读写操作相似,只是变成了读写字符或字符数组 | 特有方法带line |
二.常用情境
1.文件与集合的转换
(1)集合到文件
public class file1 {
public static void main(String[] args) throws IOException {
//创建空数组
ArrayList<String> arr=new ArrayList<String>();
//添加元素
arr.add("张叔");
arr.add("张子雯");
arr.add("张海军");
//创建字符缓冲流输出对象
BufferedWriter f=new BufferedWriter(new FileWriter("java.txt"));
//遍历获取元素
for(String s:arr){
f.write(s);
f.newLine();
f.flush();
}
f.close();
}
}
(2)文件到集合
package file;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
//读取文本数据并输入到集合中进行遍历
public class file2 {
public static void main(String[] args) throws IOException {
ArrayList<String > arr=new ArrayList<>();
BufferedReader f=new BufferedReader(new FileReader("java.txt"));
//注意此为非缓冲流遍历做法
/*char[] c=new char[1024];
int len;*/
//此为缓冲流特有方法
String line;
while((line=f.readLine())!=null){
arr.add(line);
}
f.close();
for(String s:arr){
System.out.println(s);
}
//实现点名
Random r=new Random();
int number=r.nextInt(arr.size());
String name=arr.get(number);
System.out.println("被点到的人是:"+name);
}
}
(3)面向对象版
package file;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
//先存储学生对象再写入文件
public class file3 {
public static void main(String[] args) throws IOException {
ArrayList<student> arr=new ArrayList<student>();
student s1=new student("张子雯",13);
student s2=new student("张淑",23);
arr.add(s1);
arr.add(s2);
BufferedWriter f=new BufferedWriter(new FileWriter("java.txt"));
//遍历数组循环写入
for(student s:arr){
f.write(s.getName()+","+s.getAge());
f.newLine();
f.flush();
}
f.close();
}
}
package file;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
//读出文件数据放入数组中循环遍历
public class file4 {
public static void main(String[] args) throws IOException {
ArrayList<student> arr=new ArrayList<student>();
BufferedReader f=new BufferedReader(new FileReader("java.txt"));
student s1=new student("张子雯",13);
student s2=new student("张淑",23);
//定义每行数据
String line;
while((line=f.readLine())!=null){
//用spilt对文件每行数据进行划分
String[] split = line.split(",");
student s=new student();
s.setName(split[0]);
//需要用Integer类型方法进行转换
s.setAge(Integer.parseInt(split[1]));
arr.add(s);
}
f.close();
//遍历数组
for(student s:arr){
System.out.println(s.getName()+","+s.getAge());
}
}
}
package file;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
//存储学生对象至集合进行遍历再写入文本,要求成绩排序
public class file5 {
public static void main(String[] args) throws IOException {
//创建集合的同时建立比较器接口,直接实现排序
TreeSet<teacher> ts = new TreeSet<teacher>(new Comparator<teacher>() {
@Override
public int compare(teacher t1, teacher t2) {
//先比较成绩再比较姓名
//升序排序用2-1
int num= t2.sum()- t1.sum();
int num1=num==0?t2.getArt()-t1.getArt():num;
int num2=num1==0?t2.getMath()-t1.getMath():num1;
int num3=num2==0?t2.getName().compareTo(t1.getName()):num2;
return num3;
}
});
//循环3次
//多次循环用while死循环,明确次数用for循环
for(int i=1;i<4;i++){
//注意这句话不能写入循环外,每次都需要创建一个新对象来进行调用
Scanner sc = new Scanner(System.in);
System.out.println("请录入老师信息:");
teacher t = new teacher();
String name = sc.nextLine();
t.setName(name);
int math = sc.nextInt();
t.setMath(math);
int art = sc.nextInt();
t.setArt(art);
//System.out.println(t.getName());
//将输入数据添加到集合中,即每个对象
ts.add(t);
}
//创建字符缓冲流输出流,遍历集合的同时把每个对象写入文本
BufferedWriter f=new BufferedWriter(new FileWriter("java.txt"));
for(teacher t:ts){
f.write(t.getName()+","+t.getMath()+","+t.getArt());
f.newLine();
f.flush();
}
f.close();
}
}
2.复制
(1)复制内容
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//复制文本内容
public class file {
public static void main(String[] args) throws IOException {
FileInputStream f1=new FileInputStream("io\\inf.txt");
FileOutputStream f2=new FileOutputStream("java.txt");
int by;
//In为写入数据即进行读取
while((by=f1.read())!=-1){
//out为输出数据即写入
f2.write((char)by);
}
f1.close();
f2.close();
}
}
(2)复制图片
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//复制图片
public class pic {
public static void main(String[] args) throws IOException {
FileInputStream f1=new FileInputStream("E:\\JAVA\\pic.jpeg");
//也需要写入新的图片文件
FileOutputStream f2=new FileOutputStream("io\\p.jpeg");
byte[] b=new byte[1024];
int len;
while((len=f1.read(b))!=-1){
f2.write(b,0,len);
}
f1.close();
f2.close();
}
}
(3)复制视频
package file.copy;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//复制视频
public class video {
public static void main(String[] args) throws IOException {
FileInputStream f1=new FileInputStream("C:\\Users\\zhangshu\\Documents\\TencentMeeting\\2022-07-20 16.43.07 张淑的快速会议 839556028\\meeting_01.mp4");
FileOutputStream f2=new FileOutputStream("io\\study.mp4");
byte[] b=new byte[1024];
int len;
while((len=f1.read())!=-1){
//直接写入
f2.write(b,0,len);
//读取分为读字节或读数组;而写入很简单
}
}
}
(4)复制文件
package file.copy;
import java.io.*;
//用字符缓冲流复制文件
public class java1 {
public static void main(String[] args) throws IOException {
BufferedReader f1=new BufferedReader(new FileReader("io\\copy.java"));
BufferedWriter f2=new BufferedWriter(new FileWriter("io\\copydemo1.java"));
String line;
while((line=f1.readLine())!=null){
f2.write(line);
f2.newLine();
f2.flush();
}
f1.close();
f2.close();
}
}
以上复制思路大致相似:都是创建输入输出流对象,遍历输入流内容对输出流进行方法写。
较难点:复制单级目录与多级目录(用到递归思想:方法内部调用自己的方法)
(5)复制单级文件夹(不含嵌套文件夹)
package file.copy;
import java.io.*;
//复制单级文件夹
public class floder1 {
public static void main(String[] args) throws IOException {
//创建数据源这个文件夹对象
File f = new File("E:\\za");
//获取文件夹名称,用作后续判断条件
String name = f.getName();
//创建目的地文件对象,代表文件夹这个数据对象,这里传入name是为了方便后续改变不报错
File f1 = new File("io", name);
//判断是否存在,不存在再创建
if (!f1.exists()) {
//只要没有使用这个语句就代表没有创建新东西,只是new了一个对象
f1.mkdir();
}
//获取数据源所有文件
File[] files = f.listFiles();
//遍历所有数据源对象
for (File file : files) {
//获取每个数据源文件名称
String name1 = file.getName();
//给每个文件对象创建其目的地地址
//辨别一下:f1是目的地文件夹对象,而f2是文件夹中每一个文件的目的地对象对象
File f2 = new File(f1, name1);
copy(file,f2);
}
//复制也可写成一个方法
}
//两个参数分别是每个数据源文件对象和其对应的目的地对象
//要想复制必须得到文件的原始位置对象和目的地位置对象
public static void copy(File file,File f2) throws IOException {
//进行复制操作
BufferedInputStream f3=new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream f4=new BufferedOutputStream(new FileOutputStream(f2));
//多文件复制也是此固定写法
byte[] b=new byte[1024];
int len;
while((len=f3.read(b))!=-1){
f4.write(b,0,len);
}
f3.close();
f4.close();
}
}
(6)复制多级文件夹
package file.copy;
import java.io.*;
//复制有嵌套的文件夹
public class floder2 {
public static void main(String[] args) throws IOException {
//获取数据源对象
File f1=new File("E:\\JAVA");
//获取目的地对象
File f2=new File("F:\\");
//调用文件夹复制方法,传入文件夹数据源对象和目的地对象两个参数
copy1(f1,f2);
}
public static void copy1(File f1,File f2) throws IOException {
//先判断源数据文件是否为目录
if(f1.isDirectory()){
//在目的地创建一样的目录对象
String name = f1.getName();
File f3=new File(f2,name);
//创建文件夹,有了对象才能调用创建方法
if(!f3.exists()){
f3.mkdir();
}
//获取文件夹下的所有数据源对象
File[] files = f1.listFiles();
//遍历所有数据源,可能是文件,也可能是文件夹
for(File file:files){
//递归调用,重新判断是否嵌套了文件夹
//传入遍历的每个数据源对象,对应地址是创建好的目的地地址对象
//为什么传入f3,该方法就是要传入数据源对象和目的地对象,而f3就是已经复制过来的文件夹名称
copy1(file,f3);
}
}
//不是文件夹就调用文件复制方法,与上述判断是并列关系
else {
//代表就是一个文件
//传入数据源对象
//封装目的地地址对象
File f4=new File(f2,f1.getName());
copy2(f1,f4);
}
}
public static void copy2(File f1,File f4) throws IOException {
BufferedInputStream f5=new BufferedInputStream(new FileInputStream(f1));
BufferedOutputStream f6=new BufferedOutputStream(new FileOutputStream(f4));
//多文件复制也是此固定写法
byte[] b=new byte[1024];
int len;
while((len=f5.read(b))!=-1){
f6.write(b,0,len);
}
f5.close();
f6.close();
}
}