什么是IO流?
I : Input O : Output 可以通过IO完成硬盘文件的读和写
Output
把内存中的数据存储到持久化设备上(比如:硬盘)这个动作称为输出(写,write)Output操作
Input
把持久设备上(比如:硬盘)的数据读取到内存中的这个动作称为输入(读,read)Input操作
IO操作
把上面的这种输入和输出动作称为IO操作
2. IO流的分类2.1 输入流和输出流输入流、输出流、字节流、字符流
以内存作为参照物 往内存中去,叫做输入(Input)。或者叫做读(Read)。 从内存中出来,叫做输出(Output)。或者叫做写(Write)。2.2 字节流
有的流是按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位,这种流是万能的,什么类型的文件都可以读取。包括:文本、图片、声音文件、视频 假设文件ccy.txt,采用字节流的方式读取: a楚shen 第一次读:一个字节,正好读到'a' 第二次读:一个字节,正好读到'楚'字节的一半 第三次读:一个字节,正好读到'楚'字节的另外一半2.3 字符流
有的流是按照自第六的方式读取数据的,一次读取1个字符,这种流是为了方便读取普通文本而存在的,不能读取的有:图片、声音、视频等文件。只能读取纯文本文件,连word文件都读取不了 假设文件ccy.txt,采用字符流的方式读取: a楚shen 第一次读:'a'字符('a'字符在window系统中占用1个字节) 第二次读:'楚'字符('楚'字符在window系统中占用2个字节)3. IO流包的存在位置
java中所有的流都是在:java.io.*下
java中主要研究:
怎么new流对象。
调用流对象的哪个方法是读,哪个方法是写
4. 流的四大家族 4.1 四大家族的首领都是抽象类。(abstract class)java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流
java.io.Read 字符输入流
java.io.Write 字符输出流
注意:在java中只要"类名"结尾的都是字节流,以"Read/Write"结尾的都是字符流
4.2 所有的流都实现了close()方法java.io.Closeable接口,都是可关闭的,都是有close()方法。流毕竟是一个管道,这个是内存和硬盘之间的通道,用完一定要关闭,不然会耗费(占用)很多资源。
4.3 所有的输出流都实现了flush()方法java.io.Flushable接口,都是可刷新的,都是flush()方法。养成一个好习惯,输出流在最终输出之后,一定要记得使用flush()刷新一下。这个刷新可以将通道/管道当中剩余未输出的数据强行输出完(清空管道),刷新的作用就是清空管道
注意:如果没有flush()可能会导致丢失数据
5. 要掌握的流 java.io包下需要掌握的流有16个 5.1 文件专属java.io.FileInputStream(掌握) java.io.FileOutputStream(掌握) java.io.FileReader java.io.FileWriter5.2 转换流(将字节流转换成字符流)
java.io.InputStreamReader java.io.OutputStreamWriter5.3 缓冲流专属
java.io.BufferedReader java.io.BufferedWriter java.io.BufferedInputStream java.io.BufferedPutputStream5.4 数据流专属
java.io.DataInputStream java.io.DataOutputStream5.5 标准输出流
java.io.PrintWriter java.io.PrintStream(掌握)5.6 对象专属流
java.io.ObjectInputStream(掌握) java.io.ObjectOutputStream(掌握)6. FileInputStream
文件字节输入流
package com.ccy.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStream01 {
public static void main(String[] args) {
//创建文件字节输入流对象
//文件路径:E:java编写位置ccy (IDEA会自动把变成\,因为java表示转义字符)
//E:\java编写位置\ccy,也可以这么写:E:/java编写位置/ccy
//以下都采用了:绝对路径
//FileInputStream fileInputStream = new FileInputStream("E:\java编写位置\ccy");
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("E:/java编写位置/ccy");
//开始读
// while (true){
// int read = fileInputStream.read();
// //当读取不到数据了,就会返回-1
// if(read == -1){
// System.out.println("已经没有数据可以读了!");
// break;
// }
// System.out.println(read);
// }
int read = 0;
//循环
while ((read = fileInputStream.read()) != -1){
System.out.println(read);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{ //在finally语句中确保流一定关闭
if(fileInputStream != null){ //避免空指针异常
//关闭流的前提是:流不是空的,流是null时没必要关闭
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
结果
97 98 99 100 已经没有数据可以读了!
分析上面程序的缺点:
一次读取一个字节byte,这样内存和硬盘交互太频繁,基本上时间/资源都耗费在交互上面了。能不能一次读取多个字节呢?答案是可以的
改造上面的程序:
package com.ccy.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStream02 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
//相对路径的话呢?相对路径一定从当前所在的位置作为起点开始找!
//IDEA默认的当前路径是哪里呢?工程Project的src就是IDEA的默认当前路径。
fis = new FileInputStream("src/com/ccy/java/io/tempfile");
//开始读,采用byte数组,一次读取多个字节。最多读取"数组.length"个字节
byte[] bytes = new byte[4]; //准备一个4个长度的byte数组,一次最多读取4个字节
System.out.println("tempfile文件中只有:abcdef");
int read = fis.read(bytes); //这个方法返回的是字节的个数,不是字节本身
System.out.println("第一次读取:"+read);// 4
//将读取到的数据转换成字符串,这样的写法是把读取到的数据全部转换成字符串
//System.out.println(new String(bytes));//abcd
//读取多少个就转换多少个,new String(数组,起始位置,转换个数)
System.out.println("将读取到的数转换成字符串:"+new String(bytes,0,read));//abcd
int read1 = fis.read(bytes);
System.out.println("第二次读取:"+read1); // 2
//将读取到的数据转换成字符串,这样的写法是把读取到的数据全部转换成字符串
//System.out.println(new String(bytes));//efcd
//读取多少个就转换多少个,new String(数组,起始位置,转换个数)
System.out.println("将读取到的数转换成字符串:"+new String(bytes,0,read1));//ef
int read2 = fis.read(bytes);
System.out.println("第三次读取:"+read2); // -1 读取不到数据了就会返回-1
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
结果
tempfile文件中只有:abcdef 第一次读取:4 将读取到的数转换成字符串:abcd 第二次读取:2 将读取到的数转换成字符串:ef 第三次读取:-1
最终版,需掌握
package com.ccy.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStream03 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
//打印文件的数据
System.out.println("tempfile文件:abcdef");
//文件的路径
fis = new FileInputStream("E:\java编写位置\IO\src\com\ccy\java\io\tempfile");
//创建byte数组,每次读取4个字节
byte[] bytes = new byte[4];
int readCount = 0;
//当读取到为-1时,就代表没数据可读了,会停止循环
while ((readCount = fis.read(bytes)) != -1){
System.out.print(new String(bytes,0,readCount));
}
System.out.println();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//当数据不为空时,关闭文件字节输出流
if (fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(fis);//java.io.FileInputStream@4554617c
}
}
}
显示结果
tempfile文件:abcdef abcdef java.io.FileInputStream@4554617c6.1 available(),记录未读取的个数 6.2 skip(),跳过几个字节不读取
package com.ccy.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStream04 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
System.out.println("tempfile文件:abcdef");
fis = new FileInputStream("E:\java编写位置\IO\src\com\ccy\java\io\tempfile");
//可以计算未读取的数据个数,返回的是int
int count = fis.available();
//跳过一个字节,代表第一个字节不读取
fis.skip(1);
byte[] bytes = new byte[count];//这种方法只适合读取小文件,因为byte[]不能存储太大的数据,但可以减少了循环语句
int sum = fis.read(bytes);
System.out.print(new String(bytes));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
显示结果
tempfile文件:abcdef bcdef7. FileOutputStream 7.1 文件字节输出流,可以写,从内存往硬盘中写入
package com.ccy.java.io.demo02;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutStream01 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("ccy",true);
//写数据
byte[] bytes = {97,98,99,100};
//往硬盘中,将bytes的数据全部写入
fos.write(bytes);
//往硬盘中,将bytes的数据写入两个字节
fos.write(bytes,0,2);
//字符串
String str = "我是ccy,你好!";
//将字符串转换成byte[]
byte[] by = str.getBytes();
//往硬盘中,将by的数据全部写入
fos.write(by);
//写完之后一定要刷新
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
显示
abcdab我是ccy,你好!abcdab我是ccy,你好!abcdab我是ccy,你好!7.2 文件复制
使用FileInputStream + FileOutputStream 完成文件的复制
复制过程中是一边读一边写
使用以上的字节流复制文件的时候,文件类型没有限制,万能的,什么样的文件类型都能复制
文件复制的原理:
package com.ccy.java.io.demo02;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Copy01 {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//创建一个输入流
fis = new FileInputStream("E:\PS部分.mp4");
//创建一个输出流
fos = new FileOutputStream("D:\PS部分.mp4");
//最核心的部分:一边读一边写
byte[] bytes = new byte[1024 * 1024];
int readCount = 0;
//读
while ((readCount = fis.read(bytes)) != -1){
//写
fos.write(bytes,0,readCount);
}
//刷新,输出流最后刷新
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
8. 字符流
8.1 FileRead
文件字符输入流,只能读取普通文本
读取文本内容时,比较方便,快捷
package com.ccy.java.io.demo02;
import java.io.FileReader;
import java.io.IOException;
public class FileRead01 {
public static void main(String[] args) {
FileReader read = null;
try {
System.out.println("ccy文件:abcd");
//创建文件字符流
read = new FileReader("ccy");
//创建char数组
char[] chars = new char[2];//一次读取2个字符
int writerCount = 0;
//循环
while ((writerCount = read.read(chars)) != -1){
//将字符转换成字符串
System.out.print(new String(chars));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(read !=null){
try {
read.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
显示结果
ccy文件:abcd abcd8.2 FlieWriter
文件字符输出流,写
只能输出普通文本
package com.ccy.java.io.demo02;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriter02 {
public static void main(String[] args) {
FileWriter writer = null;
try {
//创建一个文件字符流
writer = new FileWriter("ccy",true);
//创建字符数组
char[] chars = {97,98,99,100};
//写
writer.write(chars);
//writer.write(chars,0,2);
//writer.write("中国人,你好!");
//输出流刷新
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(writer != null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
显示结果
abcd8.3 复制普通文本
复制普通文件:FileRead + FileWriter
package com.ccy.java.io.demo02;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Copy02 {
public static void main(String[] args) {
FileReader read = null;
FileWriter writer = null;
try {
//读
read = new FileReader("src/com/ccy/java/io/demo02/Copy01.java");
//写
writer = new FileWriter("Copy01.java");
char[] chars = new char[1024 * 1024];
int readCount = 0;
while ((readCount = read.read(chars)) != -1){
writer.write(chars,0,readCount);
}
//刷新
writer.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(read != null){
try {
read.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(writer != null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
9.缓冲流
9.1 BufferedReader
BufferedReader:
带有缓冲区的字符输入流
使用这个流的时候不需要自定义,或者说不需要自定义byte数组,自带缓冲
package com.ccy.java.io.demo02;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class BufferedRead01 {
public static void main(String[] args) {
FileReader reader = null;
try {
System.out.println("Copy02.java文件:package com.ccy.java.io.demo02;");
reader = new FileReader("Copy01.java");
//当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流
//外部负责包装的这个流,叫做:包装流/处理流
//当前程序的FileReader是字节流,BufferedReader是处理流/包装流
//这个构造方法只能传一个字符流,不能传字节流
BufferedReader bu = new BufferedReader(reader);
String readerStr = null;
//readLine()一次读一行,但不带换行符,返回的是字符串类型
while ((readerStr = bu.readLine()) != null){
System.out.println(readerStr);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
显示结果
package com.ccy.java.io.demo02;9.2 转换流
InputStreamReader:转换流,将字节流转换成字符流
package com.ccy.java.io.demo02;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class BufferedRead01 {
public static void main(String[] args) {
try {
System.out.println("Copy02.java文件:package com.ccy.java.io.demo02;");
FileInputStream fis = new FileInputStream("Copy01.java");
//转换流,将字节流转换成字符流
//节点流和包装流/处理流是相对而言的
//当前程序的fis是节点流,reader是包装流/处理流
InputStreamReader reader = new InputStreamReader(fis);
//这个构造方法只能传一个字符流,不能传字节流,但可以通过转换流进行转换
//当前程序的reader是节点流,bu是包装流/处理流
BufferedReader bu = new BufferedReader(reader);
//上面三句可以合并写成这样
//BufferedReader bu = new BufferedReader(new InputStreamReader(new FileInputStream("Copy01.java")));
String readerStr = null;
//readLine()一次读一行,但不带换行符,返回的是字符串类型
while ((readerStr = bu.readLine()) != null){
System.out.println(readerStr);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(reader != null){
try {
bu.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
9.3 BufferedWriter
BufferedWriter:带有缓冲区的字符输出流
OutputStreamWriter:转换流,将字节流转换成字符流
package com.ccy.java.io.demo02;
import java.io.*;
public class BufferedWriter01 {
public static void main(String[] args) throws IOException {
//带有缓冲区的字符输出流
//BufferedWriter out = new BufferedWriter(new FileWriter("ccy"));
//转换流,将字节流转换成字符流
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("ccy")));
//开始写
out.write("你好!");
//刷新
out.flush();
//关闭最外层
out.close();
}
}
10. 数据流
10.1 DataOutputStream
DataOutputStream:数据字节输出流
这个刘可以将数据和数据类型一并写入文件
注意:这个文件不是普通文本文档(这个文件使用记事本是打不开的)
package com.ccy.java.io.demo03;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStream01 {
public static void main(String[] args) {
DataOutputStream dataOut = null;
try {
//创建数据字节输出流
dataOut = new DataOutputStream(new FileOutputStream("ccy01"));
//写数据
byte b = 10;
int i = 3;
dataOut.writeByte(b);//把数据和数据类型一并写入文件
dataOut.writeInt(i);
//刷新数据
dataOut.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(dataOut != null){
try {
//关闭最外层
dataOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
10.2 DataInputStream
DataInputStream:数据字节输入流
DataOutputStream写的文件,只能使用DataInputStream去读取,并且读的时候你需要提前知道写入的顺序
读取的顺序和写的顺序一致,才可以正常读取数据
package com.ccy.java.io.demo03;
import java.io.*;
public class DataInputStream02 {
public static void main(String[] args) {
DataInputStream dis = null;
try {
dis = new DataInputStream(new FileInputStream("ccy01"));
Byte b = dis.readByte();
int i = dis.readInt();
System.out.println(b);
System.out.println(i);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(dis != null){
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
显示结果
10 311. 标准输出流
PrintStream:标准的字节输出流,默认输出到控制台
package com.ccy.java.io.demo03;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class PrintStream03 {
public static void main(String[] args) {
//正常写法,在控制台输出
System.out.println("我是正常的写法哦!");
//分开写法
PrintStream out = System.out;
out.println("我是分开写法的哦!");
try {
//可以改变标准输出流的方向,方向指向ccy02文件,而不在控制台打印输出
PrintStream ps = new PrintStream(new FileOutputStream("ccy02",true));
System.setOut(ps);
ps.println("我是标准输出流哦!");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
显示结果
我是正常的写法哦! 我是分开写法的哦! ccy02文件: 我是标准输出流哦!打印日志
package com.ccy.java.io.demo03;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class logger {
public static void Log(String mess) {
try {
//指向一个日志文件
PrintStream ps = new PrintStream(new FileOutputStream("log.txt",true));
System.setOut(ps);
//获取当前的时间
Date date = new Date();
//设置时间格式
SimpleDateFormat sip = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//获取指定格式的时间
String str = sip.format(date);
//打印输出
System.out.println(str +"-->"+mess);
} catch(FileNotFoundException e){
e.printStackTrace();
}
}
}
//测试类
class test{
public static void main(String[] args) {
//调用日志方法
logger.Log("你好,我是标准输出流!");
logger.Log("你好,我已执行标准输出流!");
}
}
显示结果
2021-12-31 14:30:03 196-->你好,我是标准输出流! 2021-12-31 14:30:03 273-->你好,我已执行标准输出流!12. File类 12.1 file的常用方法
1.File类和四大家族没有哦关系,所以File类不能完成文件的读和写
2.File对象代表什么?
文件和目录名的抽象表示形式
E:360downloadswpcache
E:java存放a.txt 也是File对象
一个File对象有可能对应的是目录,也可能是文件
File只是一个路径名的抽象表示形式
3.需要掌握File类中常用的方法
exists()
createNewFile()
mkdir()
mkdirs()
getParent()
getParentFile()
getAbsoluteFile()
getAbsolutePath()
package com.ccy.java.io.demo03;
import java.io.File;
import java.io.IOException;
public class File01 {
public static void main(String[] args) {
//创建一个File对象
File fi1 = new File("D:\ccy");
//判断是否存在
System.out.println(fi1.exists()); //false
//如果D:\ccy不存在,则以文件的形式创建出来
if(!fi1.exists()){
//以文件的形式创建
try {
fi1.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
File fi5 = new File("D:\ccy2");
//如果D:\ccy不存在,则以目录的形式创建出来
if(!fi5.exists()){
//以目录的形式创建
fi5.mkdir();
}
//创建多重目录 mkdirs()方法
File fi2 = new File("D:\ccy1\f\b");
//如果D:\ccy1\f\b不存在,则以目录的形式创建出来
if(!fi2.exists()){
//以目录的形式创建
fi2.mkdirs();
}
File fi3 = new File("E:\360downloads\wpcache");
String parent = fi3.getParent();
System.out.println(parent);//E:360downloads 返回的是String类型
File parentFile = fi3.getParentFile();
System.out.println(parentFile);//E:360downloads 返回的是File类型
File fi4 = new File("ccy");
File absoluteFile = fi4.getAbsoluteFile();
System.out.println(absoluteFile);//E:java编写位置IOccy 返回的是File类型
String absolutePath = fi4.getAbsolutePath();
System.out.println(absolutePath);//E:java编写位置IOccy 返回的是String类型
File fi6 = new File("D:\HBuilderX\HBuilderX\Qt5Network.dll");
//获取文件名
System.out.println(fi6.getName());//Qt5Network.dll
//判断是否是一个目录
System.out.println(fi6.isDirectory());//false
//判断是否是一个文件
System.out.println(fi6.isFile());//true
//获取文件最后一次修改的时间
long l = fi6.lastModified();//这个毫秒是从1970年到现在的总毫秒数
//将毫秒转换成时间格式
Date date = new Date(l);
//定义时间格式
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//获取时间格式
String format = simpleDateFormat.format(date);
System.out.println(format);
//获取文件的大小
System.out.println(fi6.length());//851968字节
File fi7 = new File("D:\NDM下载器");
//D:NDM下载器NeatDM.exe
//D:NDM下载器unins000.dat
//D:NDM下载器unins000.exe
//可以获取D:NDM下载器目录下的所有文件
File[] files = fi7.listFile s();
for(File list : files){
System.out.println(list.getAbsoluteFile());
}
}
}
显示结果
false E:360downloads E:360downloads E:java编写位置IOccy E:java编写位置IOccy Qt5Network.dll false true 2021-11-05 20:33:09 331 851968 D:NDM下载器的子目录有: D:NDM下载器NeatDM.exe D:NDM下载器unins000.dat D:NDM下载器unins000.exe D:NDM下载器NeatDM.exe D:NDM下载器unins000.dat D:NDM下载器unins000.exe12.2 复制目录
1.拷贝源(被拷贝的路径)
2.拷贝目标(拷贝后存的路径)
3.拷贝方法
- 判断是目录还是文件
package com.ccy.java.io.demo03;
import java.io.*;
public class CopyDir01 {
public static void main(String[] args) {
//拷贝源
File srcFile = new File("E:\copy测试\visio");
//拷贝目标
File destFile = new File("D:\copy测试02\");
//拷贝方法
copyDir(srcFile, destFile);
}
private static void copyDir(File srcFile, File destFile) {
if(srcFile.isFile()){
//srcFile如果是一个文件的话,递归结束
//是文件的时候需要拷贝
//一边读一边写
FileInputStream fis = null;
FileOutputStream out = null;
try {
//创建文件字节输入流
fis = new FileInputStream(srcFile);
//创建文件输出流
String path = (destFile.getAbsolutePath().endsWith("\") ? destFile.getAbsolutePath() : destFile.getAbsolutePath()+"\") + srcFile.getAbsolutePath().substring(3);
out = new FileOutputStream(path);
//创建byte[]
byte[] bytes = new byte[1024 * 1024];
int readCount = 0;
//一边读一边写
while ((readCount = fis.read(bytes)) != -1){
out.write(bytes,0,readCount);
}
//刷新输出流
out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fis != null){
try {
//关闭文件字节输入流
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out != null){
try {
//关闭文件字节输出流
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//返回空值
return;
}
//获取拷贝源的子目录
File[] files = srcFile.listFiles();
//用forEach循环
for(File file : files ){
//测试是否拿到了子目录
if(file.isDirectory()){
//获取目录的绝对路径
String Str = file.getAbsolutePath();
//将字符串0-2的索引切掉
String substring = Str.substring(3);
//拼接绝对路径,类型是字符串
String destDir = (destFile.getAbsolutePath().endsWith("\") ? destFile.getAbsolutePath() : destFile.getAbsolutePath()+"\") + substring;
//将字符串转换成文件绝对路径
System.out.println(destDir);
File fi = new File(destDir);
//判断目录是否存在
if(!fi.exists()){
fi.mkdirs();
}
}
//递归调用
copyDir(file,destFile);
}
}
}
13. 对象流
13.1 序列化
package com.ccy.java.io.demo03;
import java.io.*;
public class Serialize01 implements Serializable{
//java虚拟机看到Serializable接口之后,会自动生成一个序列化版本号。
//这里没有手动写出来,java虚拟机会默认提供这个序列化版本号。
private int no;
private String name;
public int getNo() { return no; }
public void setNo(int no) { this.no = no; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Serialize01(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "Serialize01{" + "no=" + no + ", name='" + name + ''' + '}';
}
public static void main(String[] args) {
//创建java对象
Serialize01 serialize01 = new Serialize01(11,"楚胜");
ObjectOutputStream oos = null;
try {
//序列化
oos = new ObjectOutputStream(new FileOutputStream("Student"));
//序列化对象
oos.writeObject(serialize01);
//刷新
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(oos != null){
try {
//关闭
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
13.2 反序列化
package com.ccy.java.io.demo04;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeSerialize01 {
public static void main(String[] args) {
ObjectInputStream ois = null;
try {
//创建反序列化
ois = new ObjectInputStream(new FileInputStream("Student"));
//反序列化回来的是一个学生对象,所有会调用学生对象的toString方法
Object o = ois.readObject();
System.out.println(o);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if(ois != null ){
try {
//关闭
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
显示结果
Serialize01{no=11, name='楚胜'}
13.3 序列化多个对象
User类
package com.ccy.java.io.demo04;
import java.io.Serializable;
public class User implements Serializable {
private int no;
private String name;
public User() { }
public User(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "User{" + "no=" + no + ", name='" + name + ''' + '}'; }
public int getNo() { return no; }
public void setNo(int no) { this.no = no; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
ObjectOutputStream01类
package com.ccy.java.io.demo04;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
public class ObjectOutputStream01 {
public static void main(String[] args) {
//创建集合
List userList = new ArrayList<>();
//向集合中添加User对象
userList.add(new User(1,"楚1"));
userList.add(new User(2,"楚2"));
userList.add(new User(3,"楚3"));
ObjectOutputStream oos = null;
try {
//创建序列化
oos = new ObjectOutputStream(new FileOutputStream("Users"));
//开始序列化
oos.writeObject(userList);
//刷新
oos.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(oos != null){
try {
//关闭
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
13.4 反序列多个对象
package com.ccy.java.io.demo04;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.List;
public class ObjectInputStreams02 {
public static void main(String[] args) {
ObjectInputStream ois = null;
try {
//创建反序列化
ois = new ObjectInputStream(new FileInputStream("Users"));
//返回的是一个集合
List userList = (List)ois.readObject();
//System.out.println(o instanceof List);
//循环遍历出集合中的元素
for(User user : userList){
System.out.println(user);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
if(ois != null){
try {
//关闭
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
显示结果
User{no=1, name='楚1'}
User{no=2, name='楚2'}
User{no=3, name='楚3'}
13.5 transient
transient关键字表示游离的,transient关键字修饰的是不参与序列化
private transient String name;//name 不参与序列化操作,返回一个null值
反序列化的结果
User{no=1, name='null'}
User{no=2, name='null'}
User{no=3, name='null'}
13.6 序列化版本号
需先设置:
Settings--Editor--Inspections--Serializable class without 'serialVersionUID'(勾上)--Apply
//IDEA鼠标光标放在类名中alt+回车可以自动生成序列化版本号
14. IO+Properties
package com.ccy.java.io.demo04;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
public class IoProperties01 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
System.out.println("db.properties文件有:nadmin=adminn" +
"password=123456");
//创建一个输入流
fis = new FileInputStream("db.properties");
//创建一个Map集合
Properties pro = new Properties();
//调用Properties对象的load方法将文件的数据加载到Map集合中。
//文件中的数据顺着管道加载到Map集合中,其中等号左边是key,右边是value
pro.load(fis);
//通过getProperty()方法来获取value值
System.out.print("获取admin的value值:");
String admin = pro.getProperty("admin");
System.out.println(admin);
System.out.print("获取passsword的value值:");
String password = pro.getProperty("password");
System.out.println(password);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fis != null){
try {
//关闭
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
显示结果
db.properties文件有: admin=admin password=123456 获取admin的value值:admin 获取passsword的value值:123456



