JAVA中的IO流
关键知识点及补充
文章目录
IO流-节点流
-
流: 一连串流动的数据,以先入先出的方式进行流动,管道
-
以程序为中心 程序与 网络|文件|服务器|数组..
-
分类:
-
操作单元分:
-
字节流 ***:万能流:任何内容都可以转为字节,可以传输文本,图片,音频... 是一个节点流
-
字符流 :只能操作 纯文本数据 是一个节点流
-
按照功能:
-
节点流 : 包裹源头,实现基本功能 包括 字符流和字节流
-
功能流 : 对节点流增强性能,提高效率
-
分类之间是相辅相成的
-
字节流: 是节点流
-
字节输入流 : InputStream 此抽象类是表示字节输入流的所有类的超类。 抽象类不可以创建对象,只可以用来继承,所以寻找子类
-
利用 FileInputStream 从文件系统中的某个文件中获得输入字节。
-
字节输出流 : OutputStream (同字节输入流)
IO流–功能流 -
功能流(对节点流的增强): 增强功能,提高性能,加快读写效率…
缓冲流(用缓冲流包裹字节流): -
没有要使用的新增方法,可以发生多态使用
-
BufferedInputStream 字节输入流缓冲流
-
BufferedOutputStream 字节输出流缓冲流
-
有要使用的新增方法,不要使用
-
BufferedReader 字符输入流缓冲流
-
新增方法:String readLine() 读取一个文本行。
-
BufferedWriter 字符输出流缓冲流
-
新增方法:void newLine() 写入一个行分隔符。
数据流(用数据流包裹缓冲流,缓冲流包裹字节流):
*Data流(字节节点流)
- 读写基本数据类型+String类型数据
- 是字节流功能流的一种
- DataInputStream 新增方法: readXxx()
- DataOutputStream 新增方法: writeXxx()
- 存在要使用的 新增方法不能发生多态
- 先写出再写入
- EOFException 文件有,内容读入不到,必须读入的是写出的源文件
对象流同数据流
- 数据流和对象流都是得先输出在输入,也就是你先把 内容输入到磁盘再去读取
-
对象流: Object 保存数据类型+数据
-
字节的功能流:当想要传输|读写对象类型数据的时候,可以使用一个对象流
-
序列化: 把对象类型的数据转化为可存储|可传输的状态的过程
-
ObjectInputStream() 反序列化输入流 新增方法: readObject()
-
ObjectOutputStream() 序列化输出流 新增方法: writeObject()
- 注意:
- 1.先序列化后反序列化 //序列化和反序列化只是这个类的属性,方法完全可以等到反序列化后利用对象去调用方法
- 2.序列化反序列读写顺序一致
- 3.不是所有的类都能序列化 java.io.Serializable 空接口 只需要实现就行,里面是空的
- 4.不是所有的属性都需要序列化 transient 用来不让这个属性序列化
- 5.static内容不会被序列化,但是可以访问到数据,因为它是静态的,只有一份,如果你写完了,改变数据,再去读,会是改变的数据,证实了,不然你写了就写了,再改变也不会变
- 6.如果父类实现Serializable 接口,子类中可以序列化所有内容
- 7.如果子类实现Serializable 接口,但是父类没有实现,子类只能序列化子类独有的内容
例题
File类的使用
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
/*
* io: 上传下载,写入写出...
* File 类 文件和目录路径名的抽象表示形式。 只能够找到路径,不能操作具体内容,具体的要用io流
* 能够定义真实存在的路径|文件,不在的也可以定义,所以抽象表现形式
* 作用
* 构造器
* 方法
*/
/*
* File 和 字符串的转换:
* file.toString new File(string)
*/
public class FileDemo01 {
public static void main(String[] args) throws IOException {
//File(String pathname)
File file =new File("D:/test.txt"); //转义字符从\开始 所以在表示路径字符串中使用\\或者/表示
System.out.println(file);
//File(String parent, String child)
File file1 =new File("D:/AAA/haha.txt");
File file2 =new File("D:/AAA/","haha.txt");
System.out.println(file1);
System.out.println(file2);
File file3 =new File("D:/");
File file4 =new File(file3,"test.txt");
System.out.println(file3);
System.out.println(file4);
// boolean canWrite() 测试应用程序是否可以修改此抽象路径名表示的文件。
System.out.println("canWrite()"+file.canWrite());
//setReadOnly()
System.out.println("setReadOnly()"+file.setReadOnly());
System.out.println("canWrite()"+file.canWrite());
/*
* boolean mkdir()
创建此抽象路径名指定的目录。
boolean mkdirs()
创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。
*/
/*
* String getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。
File getParentFile()
*/
System.out.println("mkdir()"+file1.getParentFile().mkdir());
//boolean createNewFile()
System.out.println("createNewFile()"+file1.createNewFile());
// boolean delete() 删除此抽象路径名表示的文件或目录。
System.out.println("delete()"+file1.delete());
// boolean exists() 测试此抽象路径名表示的文件或目录是否存在。
System.out.println("exists()"+file1.exists());
/*
* File getAbsoluteFile()
返回此抽象路径名的绝对路径名形式。
String getAbsolutePath()
返回此抽象路径名的绝对路径名字符串。
*/
System.out.println("getAbsolutePath()"+file1.getAbsolutePath());
//long getFreeSpace() 返回此抽象路径名指定的分区中未分配的字节数。
System.out.println("getFreeSpace()"+file3.getFreeSpace());
// String getName() 返回由此抽象路径名表示的文件或目录的名称。
System.out.println("getName()"+file1.getName());
/*
* boolean isAbsolute() 测试此抽象路径名是否为绝对路径名。
boolean isDirectory() 测试此抽象路径名表示的文件是否是一个目录。
boolean isFile()
*/
System.out.println("isAbsolute()"+file1.isAbsolute());
file1.createNewFile();
System.out.println("isFile()"+file1.isFile()); //找路径下真实文件判断
//long lastModified()
System.out.println("lastModified()"+new SimpleDateFormat().format(new Date(file.lastModified())));
//File[] listFiles()
// String[] list()
System.out.println(Arrays.toString(new File("D:/code").listFiles()));
/*
* boolean renameTo(File dest) 重新命名
* 不能做跨盘符的文件重新命名
*/
File src=new File("D:/AAA");
System.out.println("renameTo()"+src.renameTo(new File("D:/BBB")));
}
}
复制文件
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
class CopyFile{
public static void copy2(File f1,File f2){
copy1(f1.toString(), f2.toString());
}
public static void copy1(String string1,String string2) {
// 1.选择流
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(string1); //流只是一个通道程序输入,能不能联通上就是会不会找到异常
os = new FileOutputStream(string2);
// 读入,写入
byte[] car = new byte[1024];
int len = -1;
while ((len = is.read(car)) != -1) {
os.write(car, 0, len); // 不能直接写car,不然会有很多空格,因为是1024为一组,
}
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch ( IOException e) {
e.printStackTrace();
}finally {
try {
if (os!=null) {
os.close();
}
if (is!=null) {
is.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
复制文件夹(文件夹内有文件和文件夹)—利用了拷贝文件类
import java.io.File;
class CopyDir{
public void copydir(String src,String dest){
//复制过去的一定是目的地,不会给你创建一些子目录,
//比如src:D:/AAA/DDD(里面还有:/BBB/test.txt和/CCC/) dest:D:
//拷贝文件夹一定是将AAA拷贝给D:所以要补全信息
File srcFile = new File(src);
File destFile = new File(dest,srcFile.getName());//获取的是前面的一级,注释中的DDD
details(srcFile, destFile);
}
public void details(File src,File dest){
//如果是文件,直接用copyFileTest里面的Copy类的copy2方法
if (src.isFile()) {
//注意有种情况:万一目标路径不存在,要创建路径
if (!dest.getParentFile().exists()) {
//创建文件的路径,创建完了再去拷贝
dest.getParentFile().mkdirs();
}
CopyFile.copy2(src, dest);
}else {
//就是是文件夹的情况
//目的地先创建文件夹,按理说一级就够了
dest.mkdir();
//遍历文件夹中剩余的内容,如果是文件拷贝,文件夹创建,再遍历文件夹下的内容
File[] files = src.listFiles();
for (File file : files) {
details(file,new File(dest,file.getName()));
}
}
}
}
字符流输入
public class CharDemo01 {
public static void main(String[] args) {
//FileReader(String fileName)
Reader rd=null;
try {
//1.选择流
rd=new FileReader("D:/hehe.txt");
//2.读入
//int read() 读取单个字符。
/*System.out.println((char)rd.read());
System.out.println((char)rd.read());*/
int len=-1; //存储读到的数据 如果为-1,证明已达到末尾
/*while(-1!=(len=rd.read())){
System.out.println((char)len);
}*/
// int read(char[] cbuf) 将字符读入数组。
char[] car=new char[1024];
while((len=rd.read(car))!=-1){
System.out.println(new String(car,0,len));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
if(rd!=null){
try {
rd.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符流输出
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
/*
* 字符输出流: Writer 写入字符流的抽象类
* FileWriter用来写入字符文件的便捷类。
*/
public class CharDemo02 {
public static void main(String[] args) {
//FileWriter(File file) //默认不追加
//FileWriter(File file, boolean append)
//FileWriter(String file)
//FileWriter(String file, boolean append)
Writer rt=null;
try {
//1.选择流
rt=new FileWriter("D:/houhou.txt",true);
//2.写出
/*
* void write(char[] cbuf)
写入字符数组。
abstract void write(char[] cbuf, int off, int len)
写入字符数组的某一部分。
void write(int c)
写入单个字符。
void write(String str)
写入字符串。
void write(String str, int off, int len)
写入字符串的某一部分。
*/
rt.write(97);
rt.write("\r\n"); //换行
rt.write("你真好看!!!!");
rt.write("\r\n");
rt.write("你真好看!!!!",2,2);
rt.write("\r\n");
char[] ch={'上','海','尚','学','堂'};
rt.write(ch);
rt.write("\r\n");
rt.write(ch,2,3);
//3.刷出
rt.flush();
} catch (IOException e) {
e.printStackTrace();
} finally{
//4.关闭
if(null!=rt){
try {
rt.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
增强字节流的使用
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/*
* 功能流(对节点流的增强),缓冲流: 增强功能,提高性能,加快读写效率..
*
* 字节流:
* BufferedInputStream 字节输入流缓冲流
* BufferedOutputStream 字节输出流缓冲流
* 没有新增方法,可以发生多态使用
*
* 字符流:
* BufferedReader 字符输入流缓冲流
* BufferedWriter 字符输出流缓冲流
*/
public class BufferedInputStream01 {
public static void main(String[] args) throws IOException {
//1.选择流
//BufferedInputStream(InputStream in)
InputStream is=new BufferedInputStream(new FileInputStream("D:/hehe.txt"));
OutputStream os=new BufferedOutputStream(new FileOutputStream("E:/hengheng.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();
}
}
增强字符流的使用
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 字符流:
* BufferedReader 字符输入流缓冲流
* 新增方法:String readLine() 读取一个文本行。
* BufferedWriter 字符输出流缓冲流
* 新增方法:void newLine() 写入一个行分隔符。
*
*/
public class BufferedReader02 {
public static void main(String[] args) throws IOException {
//1.选择流 导包快捷键: ctrl+shift+o
BufferedReader br=new BufferedReader(new FileReader("D:/hehe.txt"));
BufferedWriter bw=new BufferedWriter(new FileWriter("D:/ccc.txt"));
//2.读写
String msg=null;
while((msg=br.readLine())!=null){
bw.write(msg);
bw.newLine();
}
//3.刷出
bw.flush();
//4.关闭
bw.close();
br.close();
}
}
数据处理流
/**
* 数据+类型 输出到文件
* @param destPath
* @throws IOException
*/
public static void write(String destPath) throws IOException{
int point=2;
long num=100L;
String str="数据类型";
//创建源
File dest=new File(destPath);
//选择流
DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
//操作 写出的顺序 为读取作准备 顺序一定要一致
dos.writeInt(point);
dos.writeLong(num);
dos.writeUTF(str);
dos.flush();
//释放资源
dos.close();
}
对象处理流(序列化):ObjectOutputStream
//创建源
File dest=new File(destPath);
//选择流 OjbectOutputStream
ObjectOutputStream dos = new ObjectOutputStream(new BufferedOutputStream(
new FileOutputStream(dest)));
//操作 读取的顺序与写出的顺序一致 必须存在才能读取
Employee obj=new Employee (“yinwei”,1500);
dos.writeObject(obj);
//刷出
dos.flush();
//释放资源
dos.close();
对象处理流(反序列化):ObjectInputStream
/**
* 反序列化:
* 1、先写入再读取
* 2、读取对象需要知道具体类型,依次读取
* 注意:
* 1)不是所有的对象都可以序列化 Serializable
* 2)不是所有的属性都需要序列化 transient
*/
public static void read(String srcPath) throws FileNotFoundException, IOException, ClassNotFoundException{
//创建源
File src=new File(srcPath);
//选择流 OjbectInputStream
ObjectInputStream dis=new ObjectInputStream(
new BufferedInputStream(
new FileInputStream(src)
)
);
//操作 读取的顺序与写出的顺序一致 必须存在才能读取
Object obj=dis.readObject();
if(obj instanceof Employee){
Employee emp=(Employee)obj;
System.out.println(emp.getName());
System.out.println(emp.getSalary());
}
obj=dis.readObject();
int[]arr=(int[])obj;
System.out.println(Arrays.toString(arr));
//释放资源
dis.close();
}
数据流:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
*Data流(字节节点流)
* 读写基本数据类型+String类型数据
* 是字节流功能流的一种
* DataInputStream 新增方法: readXxx()
* DataOutputStream 新增方法: writeXxx()
* 存在要使用的 新增方法不能发生多态
* 先写出再写入
*
* EOFException 文件有,内容读入不到,必须读入的是写出的源文件
*/
public class DataDemo01 {
public static void main(String[] args) throws IOException {
//write("D:/data.txt");
read("D:/data1.txt");
}
//读入
public static void read(String path) throws IOException{
//1.输入流 数据类型+数据
DataInputStream in=new DataInputStream(new BufferedInputStream(new FileInputStream(path)));
//2.读入
int i=in.readInt();
boolean b=in.readBoolean();
String s=in.readUTF();
System.out.println(i+"-->"+b+"-->"+s);
//3.关闭
in.close();
}
//写出
public static void write(String path) throws IOException{
//1.输出流
DataOutputStream out=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
//2.准备数据
int i=101;
boolean f=false;
String s="哈哈";
//3.写出 写出和读入的顺序要保持一致
out.writeInt(i);
out.writeBoolean(f);
out.writeUTF(s);
//4.刷出
out.flush();
//5.关闭
out.close();
}
}
对象流 :
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
/**
* 数据流和对象流都是得先输出在输入,也就是你先把 内容输入到磁盘再去读取
*
* 对象流: Object 保存数据类型+数据
* 字节的功能流:当想要传输|读写对象类型数据的时候,可以使用一个对象流
* 序列化: 把对象类型的数据转化为可存储|可传输的状态的过程
* ObjectInputStream() 反序列化输入流 新增方法: readObject()
* ObjectOutputStream() 序列化输出流 新增方法: writeObject()
*
* 注意:
* 1.先序列化后反序列化 //序列化和反序列化只是这个类的属性,方法完全可以等到反序列化后利用对象去调用方法
* 2.序列化反序列读写顺序一致
* 3.不是所有的类都能序列化 java.io.Serializable 空接口 只需要实现就行,里面是空的
* 4.不是所有的属性都需要序列化 transient 用来不让这个属性序列化
* 5.static内容不会被序列化,但是可以访问到数据,因为它是静态的,只有一份,如果你写完了,改变数据,再去读,会是改变的数据,证实了,不然你写了就写了,再改变也不会变
* 6.如果父类实现Serializable 接口,子类中可以序列化所有内容
* 如果子类实现Serializable 接口,但是父类没有实现,子类只能序列化子类独有的内容
*/
public class ObjectDemo02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//write("G:/object.txt");
read("F:/object.txt");
}
//反序列化输入
public static void read(String path) throws IOException, ClassNotFoundException{
//1.输入流
ObjectInputStream is=new ObjectInputStream(new BufferedInputStream(new FileInputStream(path)));
//2.读入
Object p= is.readObject();
int[] arr= (int[]) is.readObject();
if(p instanceof Person){
Person person=(Person)p;
System.out.println(person.getName());
}
System.out.println(p);
System.out.println(Arrays.toString(arr));
//3,关闭
is.close();
}
//序列化输出
public static void write(String path) throws IOException{
//1.输出对象信息
ObjectOutputStream os=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
//2.准备数据
Person p=new Person("冬冬",18);
int[] arr={1,2,3,4};
//3.输出
os.writeObject(p);
os.writeObject(arr);
//4.刷出
os.flush();
//5.关闭
os.close();
p.setAge(100);
}
}
class Person implements Serializable{
private String name;
private static int age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
os.writeObject(arr);
//4.刷出
os.flush();
//5.关闭
os.close();
p.setAge(100);
}
}
class Person implements Serializable{
private String name;
private static int age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}