IO流
IO流:输入(Input)输出(Output)流
输入输出是相对于内存来讲的
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的类都在IO包中
流按流向分为两种:输入流,输出流
一、File类
File文件和目录路径名的抽象表示形式。
即,Java中把文件或者目录(文件夹)都封装成File对象。
也就是说如果我们要去操作硬盘上的文件,或者文件夹只要找到File这个类即可。
构造方法:
File(File parent, String child)
从父抽象路径名和子路径名字符串创建新的 File实例。
File(String pathname)
通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
File(String parent, String child)
从父路径名字符串和子路径名字符串创建新的 File实例。
File(URI uri)
通过将给定的 file: URI转换为抽象路径名来创建新的 File实例。
注意点:
1、文件路径
绝对路径:从盘符开始到文件的路径
相对路径:从某个参照路径开始到指定文件所经过的路径
2、文件分隔符:
Windows:\
Unix(Linux、Mac OS)?
File.sperator:获取当前系统的文件分隔符
常用方法
获取功能
File getAbsoluteFile() 返回此抽象路径名的绝对形式。
public String getPath() 获取路径(用什么方式创建的对象,就返回什么方式的路径(绝对路径/相对路径))
public String getName() 获取文件/文件夹的名称
public String getParent() 返回所在文件夹路径(根据创建对象时是否为绝对路径/相对路径)
long lastModified()
返回此抽象路径名表示的文件上次修改的时间。 (时间戳 毫秒)
long length()
返回由此抽象路径名表示的文件的大小。
创建与删除
public boolean createNewFile() throws IOException 创建文件
在创建文件时,如果文件所在的文件夹不存在,则报错系统找不到指定的路径.创建文件时,必须确保文件夹已经存在
public boolean mkdir() 使用mkdir方法创建文件夹时,必须保证其所在文件夹已经存在,否则创建失败(不会报错)
public boolean mkdirs() 一次性创建多级目录
public boolean delete() 删除文件夹不能为非空(有东西),否则删除失败
判断
public boolean exists() 文件或者文件夹是否存在
public boolean isDirectory() 判断文件对象是否为文件夹
public boolean isFile() 判断文件对象是否为文件
获取目录下的结构(必须是目录对象调用)
public File[] listFiles() 获取调用方法文件夹下的所有file对象(文件或文件夹)
String[] list() 返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。
public static void main(String[] args){
//File对象创建方式一:
File file1 = new File("hello.txt");//相对路径:相当于当前目录
File file2 = new File("D:\\a.txt");//绝对路径
System.out.println(file1);//hello.txt
System.out.println(file1.getAbsoluteFile());//E:\workspace\20190917\hello.txt
}
IO流基本划分:
1、按照操作的数据类型:字节流、字符流
2、按照流的流向:输入流、输出流
3、按照流的角色:节点流、处理流
流操作规律
(1)第一步:先明确源和目的源
源:字节(InputStream) 字符(Reader)
目的:字节(OutputStream) 字符(Writer)
(2)明确是不是纯文本:
是:用字符流
不是:用字节流
(3)明确流体系后,通过设备来明确设备来明确具体使用哪个流对象
IO体系:
抽象对象 节点流(文件流) 缓冲流(属于处理流的一种)
InputStream(字节) FileInputStream BufferedInputStream
OutputStream FileOutputStream BufferedOutputStream
Reader(字符) FileReader BufferedReader
Writer FileWriter BufferedWriter
1、字符流
1.1字符文件流
1.1.1字符文件输入流FileReader
//常用方法:int read()、int read(char[] cbuf)
//需求:hello.txt需要读取文件中字符内容
//1.创建文件对象
File file = new File("hello.txt");
//2.创建字符(文件)输入流对象
FileReader reader = new FileReader(file);
//3.读取数据
//方式一:一次读取一个字符
int read = reader.read();//read() 读取单个字符 ASCII
while(read!=-1){
System.out.print((char)read);
read = reader.read();
}
//方式一 优化
int read;
while((read = reader.read()!=-1)){
System.out.print((char)read);
}
//方式二
//定义读取字符的数组
char[] cbuf = new char[5];
int len;
while((len = reader.read(cbuf))!=-1){
for(int i = 0;i<len;i++){
System.out.print(chuf[i]);
}
}
4.关闭资源(流对象不会自动关闭,也不会被垃圾回收机制回收)
reader.close();
1.1.2字符文件输出流FileWriter
注意:
对于文本文件(.txt .java .c .cpp)可以使用字符流(字节流(可传不可看))传输
对于非文本文件(.png .avi .jpg .word)必须使用字节流传输
//常用方法:write()、write(String str)、write(char[] cbuf,int offset,int len)、write(char[] cbuf)
//将内存中数据写入磁盘中
//helloigeekhome
//1.创建文件对象(指定文件位置用于写入)
//注意点:
//1、如果文件不存在,那么会自动创建文件,并将内容写入到文件中,不会报错
//2、默认情况下,fw.write()会覆盖文件内容
File file = new File("hello.txt");
//2.创建输出流对象(字符)FileWriter
FileWriter fw = new FileWriter(file);
//3.写入
fw.write("helloigeekhome");
//4.关闭资源
fw.close();
1.1.3字符流文件拷贝
public class ReaderAndWriterDemo {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("D:\\a.txt");
fw = new FileWriter("D:\\b.txt");
int len = -1;
char[] cbuf = new char[1024];
while((len = fr.read(cbuf))!=-1) {
fw.write(cbuf, 0, len);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(fw!=null) {
try {
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fr!=null) {
try {
fr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
2、字节流
2.1文件字节流
2.1.1字节输入流
FileInputStream
2.1.2字节输出流
FileOutputStream
2.1.3字节流文件拷贝
public class FileInputStreamDemo01 {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("D:\\a.txt");
fos = new FileOutputStream("D:\\aa.txt");
byte[] b = new byte[1024];
int len = -1;
while ((len = fis.read(b)) != -1) {
fos.write(b, 0, len);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
3、缓冲流
作用:提高数据的读取与写入的效率
提高效率的原因(以字节缓冲流为例):因为缓冲流内置了缓冲区,缓冲区默认的是8129长度的字节\字符数组,当每次write操作中,如果缓冲区满了,会将自动将数据刷到文件中,当调用close()方法时,也会自动将数据刷新到内存中
3.1使用字符缓冲流拷贝文件
public class BufferedReaderAndWriter {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
FileReader fr = new FileReader("E:\\a.txt");
FileWriter fw = new FileWriter("E:\\b.txt");
br = new BufferedReader(fr);
bw = new BufferedWriter(fw);
String line = null;
while((line = br.readLine())!=null) {
bw.write(line);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(bw!=null) {
try {
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(br!=null) {
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
3.2使用字节缓冲流拷贝文件
public class BufferedInputStreamAndOutputStream {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("D:\\a.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
fos = new FileOutputStream("E:\\a.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] buf = new byte[1024];
int len = -1;
while((len = bis.read(buf))!=-1) {
fos.write(buf, 0, len);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(fos!=null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fis!=null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
4、转换流
InputStreamReader:可以完成字节输入流转换为字符输入流
OutputStreamWriter:可以完成字节输出流转换为字符输出流
使用转换流主要是因为字符输入流有readLine()方法,可以一次读取一行
4.1使用转换流拷贝文件
public class Transform {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
FileInputStream fis = new FileInputStream("D:\\a.txt");
FileOutputStream fos = new FileOutputStream("D:\\c.txt");
InputStreamReader isr = new InputStreamReader(fis);
OutputStreamWriter osr = new OutputStreamWriter(fos);
br = new BufferedReader(isr);
bw = new BufferedWriter(osr);
String line = null;
while((line = br.readLine())!=null) {
osr.write(line);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(bw!=null) {
try {
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(br!=null) {
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
5、其他流
5.1对象序列化与反序列化【掌握】
将自定义对象、String进行持久化(保存到文件中)=>序列化
将文件中的内容读取转换为自定义对象 =>反序列化
用于向流中写入对象的操作流ObjectOutputStream称为序列化流
用于从文件中读取对象的操作流ObjectInputStream称为反序列化流
特点:用于操作对象。可以将对象写入到文件中,也可以从文件中读取对象
自定义对象如果需要实现序列化操作,必须实现Serializable接口,否则抛出java.io.NotSerializableException
序列化机制就是允许将内存中的Java对象转换为与平台无关的二进制数据,可以将这些二进制数据永久的存储在磁盘中,或者通过网络传输到其他网络节点,只要其他程序获取到了这些二进制数据,就可以把数据再次转换为对象
5.1.1序列化操作 内存=>文件
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws FileNotFoundException, IOException {
//1、创建写出文件对象
File dest = new File("D:\\aaa.txt");//序列化操作的持久化文件可以是任意数据类型,不需要查看
//2、创建序列化对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(dest));
//3、将对象写入输入流
oos.writeObject("我有一个梦想");
//自定义对象如果需要实现序列化操作,必须实现Serializable接口,否则抛出java.io.NotSerializableException
oos.writeObject(new User("1","Jack"));
}
}
class User implements Serializable{
private String id;
private String name;
public User() {}
public User(String id,String name) {
this.id = id;
this.name = name;
}
}
5.1.2反序列化 文件=>内存(对象)
public class ObjectInputStreamDemo {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//1、创建读取文件对象
File dest = new File("D:\\aaa.txt");
//2、创建读取流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(dest));
//3、读取文件,获取对象
//readObject顺序要按照writeObject的顺序
String str = (String)ois.readObject();
User user = (User)ois.readObject();
System.out.println(str);
System.out.println(user);
ois.close();
}
}
注意点:
1、如果一个对象需要支持序列化与反序列化,那么该对象所属的类必须实现Serializable接口(类对应的对象具有了序列化与反序列化的能力)
2、需要实现序列化的类需要提供个serialVersionUID(如果没有提供,那么JVM会自动提供。每次修改类,该值都会发生变化)public static final long serialVersionUID = 1321554L;
3、如果一个类需要支持序列化与反序列化操作,那么这个类的所有属性也需要支持序列化与反序列化
4、被static与transient关键字修饰的属性无法被序列化
5.2标准的输入流、标准输出流【了解】
System.in 标准输入流(键盘)
System.out 标准输出流 (控制台)
5.3打印流【了解】
打印流只有输出流
PrintStream 字节打印流,调用println方法时自动刷新
PrintWriter 字符打印流,指定自动刷新开关后,调用println方法时自动刷新,无需手动调用flush()方法
tln(user);
ois.close();
}
}
**注意点:**
1、如果一个对象需要支持序列化与反序列化,那么该对象所属的类必须实现Serializable接口(类对应的对象具有了序列化与反序列化的能力)
2、需要实现序列化的类需要提供个serialVersionUID(如果没有提供,那么JVM会自动提供。每次修改类,该值都会发生变化)public static final long serialVersionUID = 1321554L;
3、如果一个类需要支持序列化与反序列化操作,那么这个类的所有属性也需要支持序列化与反序列化
4、被static与transient关键字修饰的属性无法被序列化
###### 5.2标准的输入流、标准输出流【了解】
System.in 标准输入流(键盘)
System.out 标准输出流 (控制台)
###### 5.3打印流【了解】
打印流只有输出流
PrintStream 字节打印流,调用println方法时自动刷新
PrintWriter 字符打印流,指定自动刷新开关后,调用println方法时自动刷新,无需手动调用flush()方法