我们于2021/07/17 的学习目标是:IO与容器,核心任务为:
1、学习技术:
1)、IO拷贝文件与文件夹
2)、缓冲流
3)、基本数据类型流
4)、引用数据类型流
5)、CommonsIO工具包
6)、手动简单封装容器
7)、集合
8)、遍历
9)、序列号
2、文档总结
1)、IO拷贝文件与文件夹
拷贝文件 : 必会
拷贝文件夹 : 了解
import java.io.*;
public class CopyFileUtils {
public static void main(String[] args) {
copyFile("D://test.txt","D://a.txt"); //调用方法
}
public static void copyFile(String src,String dest){
copyFile(src!=null?new File(src):null,dest!=null?new File(dest):null);
}
public static void copyFile(File src, File dest){
if(src==null || dest==null){
throw new NullPointerException("数据源或者目的地为null");
}
//1.创建流
InputStream is = null;
OutputStream os = null;
try {
is= new FileInputStream(src);
os = new FileOutputStream(dest);
//2.拷贝
byte[] car = new byte[1024];
int len = -1;
while((len=is.read(car))!=-1){
os.write(car,0,len);
}
//3.刷出
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class Class003_CopyDIR {
static String dir1 = "D://pingfanzhilu";//源文件夹
static String dir2 = "E://pingfanzhilu";//目标文件夹
public static void main(String[] args)throws IOException {
new File(dir2).mkdirs();//创建文件夹
File[] file = (new File(dir1)).listFiles();//获取源文件夹下的文件和目录
for(int i = 0;i<file.length-1;i++){//循环判断文件
if(file[i].isFile()) //如果是文件,复制
copyFile(file[i],new File(dir2+file[i].getName()));
if(file[i].isDirectory()){//如果是目录,调用复制目录的函数
String sourceDir=dir1 + File.separator+file[i].getName();//拼接源文件地址
String targetDir=dir2 + File.separator+file[i].getName();//拼接目标文件地址
copyDirectory(sourceDir,targetDir);
}
}
}
public static void copyFile(File source,File target) throws IOException{
//输入流
FileInputStream input = new FileInputStream(source);
BufferedInputStream inbuff = new BufferedInputStream(input);
//输出流
FileOutputStream output = new FileOutputStream(target);
BufferedOutputStream outbuff = new BufferedOutputStream(output);
//缓冲数组
byte[] car = new byte[1024];
int len;
while((len=inbuff.read(car))!=-1)
outbuff.write(car,0,len);
//刷新
outbuff.flush();
//关闭
inbuff.close();
outbuff.close();
output.close();
input.close();
}
public static void copyDirectory(String source,String target) throws IOException{
(new File(target)).mkdirs(); //创建对应旧目录的文件夹
File[] file = (new File(source)).listFiles();
for(int i = 0;i< file.length;i++){
if(file[i].isFile()){ //如果有文件,调用复制文件的函数
File sourceFile=file[i];
File targetFile = new File(new File(target).getAbsolutePath()+File.separator+file[i].getName());
copyFile(sourceFile,targetFile);
}
if(file[i].isDirectory()){
String d1 = source + "/" + file[i].getName();
String d2 = target + "/" + file[i].getName();
copyDirectory(d1,d2);
}
}
}
}
2)、缓冲流
缓冲流属于功能流,作用是提高读写效率,即对应功能流的特性加强性能。
字节节点流有:
FileInputStream 文件流
ByteArrayInputStream 字节数组流
FileOutputStream
ByteArrayOutputStream
字节缓冲流有:
BufferedInputStream 字节输入缓冲流
BufferedOutputStream 字节输出缓冲流
public class Class001_Buffered {
public static void main(String[] args) throws IOException {
//1.创建流
InputStream is = new BufferedInputStream(new FileInputStream("D://test.txt"));
OutputStream os = new BufferedOutputStream(new FileOutputStream("D://heihei.txt"));
//2.拷贝
byte[] car = new byte[1024];
int len = -1;
while((len=is.read(car))!=-1){
os.write(car,0,len);
}
//3.刷出
os.flush();
//4.关闭
os.close();
is.close();
}
}
字符节点流:
FileReader
FileWriter
字符缓冲流:
BufferedReader
BufferedWriter
存在新增方法: 不能发生多态
readLine()
newLine()
import java.io.*;
public class Class002_Buffered {
public static void main(String[] args) throws IOException {
//1.创建流
BufferedReader rd = new BufferedReader(new FileReader("D://test.txt"));
BufferedWriter rw = new BufferedWriter(new FileWriter("D://b.txt"));
//2.读写
String msg = null;
while((msg = rd.readLine())!=null){
rw.write(msg);
rw.newLine();
//rw.write("\n\r");
}
//3.刷出
rw.flush();
//4.关闭
rw.close();
rd.close();
}
}
3)、基本数据类型流
功能上属于功能流,操作单元上属于字节流。
作用是保留数据以及数据类型(基本数据类型+String)
DataInputStream(新增功能:readXxx())
DataOutputStream(新增功能:writeXxx())
注意:
读入与写出的顺序要保持一致
java.io.EOFException:读入的文件不是源文件
import java.io.*;
public class Class001_Data {
public static void main(String[] args) throws IOException {
readFromFile("D:/d.txt");
}
//读入
public static void readFromFile(String path) throws IOException {
//1.创建流
DataInputStream is = new DataInputStream(new BufferedInputStream(new FileInputStream(path)));
//2.读入
int i = is.readInt();
boolean flag = is.readBoolean();
char ch = is.readChar();
String s = is.readUTF();
//3.处理数据
System.out.println(i);
System.out.println(flag);
System.out.println(ch);
System.out.println(s);
//4.关闭
is.close();
}
//写出
public static void writeToFile(String path) throws IOException {
//1.创建输出流
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
//2.准备数据
int i = 1;
boolean flag = false;
char ch = 'c';
String str = "哈哈";
//3.写出
out.writeInt(i);
out.writeBoolean(flag);
out.writeChar(ch);
out.writeUTF(str);
//4.刷出
out.flush();
//5.关闭
out.close();
}
}
4)、引用数据类型流
又称Object流,对象流。
作用:读写对象数据(引用数据类型的数据,也包含基本数据类型)
ObjectInputStream 反序列化输入流(新增功能:readObject())
ObjectOutputStream 序列化输出流(新增功能:writeObject(Object obj))
序列化:将对象数据转换一个可存储或者可传输的状态过程
先序列化后反序列化
不能所有的类型都能序列化 java.io.Serializable
不是所有的属性都需要序列化
静态的内容不会序列化
如果父类实现序列化,子类没有实现,可以序列化所有的成员
如果子类实现序列化,父类实现,只能序列化子类成员
public class Class001_Object {
public static void main(String[] args) throws IOException, ClassNotFoundException {
writeToFile("D://e.txt");
readFile("D://e.txt");
}
//反序列化
public static void readFile(String path) throws IOException, ClassNotFoundException {
//1.输入流
ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(path)));
//2.读入
User obj1 = (User) in.readObject();
int[] arr = (int[]) in.readObject();
//3.处理数据
System.out.println(obj1);
System.out.println(Arrays.toString(arr));
//4.关闭
in.close();
}
//序列化输出
public static void writeToFile(String path) throws IOException {
//1.输出流
ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
//2.数据
User user = new User("zhangsan",18,"123");
int[] arr = {1,2,3,4};
//3.写出
out.writeObject(user);
out.writeObject(arr);
//4.刷出
out.flush();
//5.关闭
out.close();
//修饰user对象的成员,静态
user.username = "lisi";
user.password = "4321";
}
}
class User implements Serializable{
public String username;
//transient 修饰的字段不会序列化
public transient int age;
public static String password;
public User() {
}
public User(String username, int age, String password) {
this.username = username;
this.age = age;
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
", password='" + password + '\'' +
'}';
}
}
5)、CommonsIO工具包
CommonsIO 是apache的一个开源的工具包,封装了IO操作的相关类,使用Commons IO可以很方便的读写文件,url源代码等。
使用第三方组件的方式|步骤:
1.下载源码资源,找到核心jar包
2.项目下新建文件夹lib,放入jar包
3.commons-IO 需要加入classpath 的第三方 jar 包内的 class 文件才能在项目中使用
选中jar包右键->add as lib...
public class Class001_CommonsIO {
public static void main(String[] args) throws IOException {
//1.创建File对象
File src = new File("D://a.txt");
File dest = FileUtils.getFile("D://f.txt");
//FilenameUtils
//isExtension(String fileName, String text) // 判断fileName是否是text后缀名
//FilenameUtils.getBaseName(String filename) // 去除目录和后缀后的文件名
System.out.println(FilenameUtils.getBaseName("D://DDD/haha.txt"));;
System.out.println(FilenameUtils.getName("D://DDD/haha.txt"));;
System.out.println(FilenameUtils.isExtension("D://DDD/haha.txt","txt"));;
//FileUtils
//FileUtils.copyFile(File srcFile, File destFile)` // 复制文件
FileUtils.copyFile(src,dest);
// **复制文件夹**
//FileUtils.copyDirectory(File srcDir, File destDir)` // 复制文件夹(文件夹里面的文件内容也会复制)
FileUtils.copyDirectory(new File("D://DDD"), new File("D://hehe/DDD"));
//FileUtils.copyDirectory(File srcDir, File destDir, FileFilter filter)` // 复制文件夹,带有文件过滤功能
FileUtils.copyDirectory(new File("D://DDD"), new File("D://houhou/DDD"), FileFilterUtils.fileFileFilter());
//**把字符串写入文件**
//`FileUtils.writeStringToFile(File file, String data, String encoding)` // 字符串以指定的编码写到文件
//`FileUtils.writeStringToFile(File file, String data, String encoding, boolean append)`// 指定知否追加
FileUtils.writeStringToFile(src,"yyds!!!!","UTF-8",true);
}
}
6)、手动简单封装数组容器
由于数组是定长的,一旦确定长度则不可改变。所以为了解决存储数目数据的问题,这里引入容量跟随内容的多少进行动态的增删,并且能存储任意引用类型数据容器解决。
import java.util.ArrayList;
public class Class001_App {
public static void main(String[] args) {
//容器类型
ArrayList list = new ArrayList();
list.add("zhangsan");
list.add(123);
System.out.println(list.size());
System.out.println(list.get(0));
System.out.println(list.get(1));
MyContainer my = new MyContainer();
my.add("abc");
my.add("efg");
System.out.println(my.size());
my.add("efg");
System.out.println(my.size());
System.out.println(my.get(0));
System.out.println(my.get(1));
System.out.println(my.get(2));
}
}
//封装自定义容器类型 : 只能存储字符串类型的数据
class MyContainer{
//存储数据的结构
private String[] elementData;
//存储数据的个数
private int size;
public MyContainer() {
}
//添加方法
public void add(String value) {
//判断是否为第一次添加数据
if(elementData==null && size==0){
//创建新数组
elementData = new String[1];
//直接把value放入数组
elementData[0] = value;
//长度+1
size++;
return;
}
//备份原数组: 用来做数组数据拷贝
String[] temp = elementData;
//创建新数组
elementData = new String[size+1];
//1)数组数据的拷贝 i作为新数组与原数组索引
for(int i=0;i<size;i++){
elementData[i] = temp[i];
}
//2)添加新数据
elementData[size++] = value;
//长度+1
}
//size
public int size(){
return this.size;
}
/**
* 根据索引获取数据
* @param index 索引
* @return index索引位置的数据
*/
public String get(int index) {
if(index<0 || index>=size){
throw new IndexOutOfBoundsException("索引越界啦!!!");
}
return elementData[index];
}
//根据索引删除
//修改制定索引位置的数据
}
7)、Collection集合
Collectio表示的是集合层次结构中的根接口.
集合表示一组对象,称其为元素。
Collection col = new ArrayList();
集合的创建
col.add("abc");
col.add(false);
col.add(100);
给集合添加内容
col.addAll(col2);
集合加集合
//boolean contains(Object o) 如果此collection包含指定的元素,则返回 true 。
//boolean containsAll(Collection<?> c) 如果此集合包含指定集合中的所有元素,则返回 true
System.out.println(col.contains(100));
col2.add("ccc");
System.out.println(col.containsAll(col2));
//boolean remove(Object o) 从此集合中移除指定元素的单个实例(如果存在)(可选操作)。
//boolean removeAll(Collection<?> c) 删除此集合的所有元素,这些元素也包含在指定的集合中(可选操作)。
System.out.println(col.remove(100));
System.out.println(col);
//System.out.println(col.removeAll(col2));
//System.out.println(col);
//boolean retainAll(Collection<?> c) 仅保留此集合中包含在指定集合中的元素(可选操作)。
System.out.println(col.retainAll(col2));
System.out.println(col);
System.out.println(col2);
//Object[] toArray() 返回包含此集合中所有元素的数组。
System.out.println(Arrays.toString(col.toArray()));
8)、遍历
集合可以使用增强for,也可以使用迭代器遍历
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Class002_Each {
public static void main(String[] args) {
Collection col = new ArrayList();
col.add("aaa");
col.add("bbb");
col.add("ccc");
col.add("ddd");
//1.增强for
for(Object s:col){
System.out.println(s);
}
//2.迭代器
//1)获取迭代器对象
Iterator it = col.iterator();
//2)判断是否存在下一个数据
while(it.hasNext()){
//3)获取下一个数据
System.out.println(it.next());
}
}
}
9)、序列号
1.实现Serializable接口的类型默认生成序列号,序列号会根据成员的修改做更新 serialVersionUID = -5204947308809070324
2.控制版本的统一问题: 控制类型修改之前与之后序列不变
3.通过工具生成序列号:
①.实现Serializable接口
②.setting设置
③.选中类名->alt+enter->生成序列号
class User implements Serializable{
private static final long serialVersionUID = -5204947308809070324L;
public String username;
//transient 修饰的字段不会序列化
public transient int age;
public static String password;
//成员的修改: 新增的成员
public int vip;
public int id; //用户编号
public User() {
}
public User(String username, int age, String password) {
this.username = username;
this.age = age;
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
", password='" + password + '\'' +
'}';
}
}