I/O框架
流的概念与分类
概念:
- 内存与存储设备之间传输数据的通道
分类:
- 按方向【重点】:
- 输入流:将<存储设备>中的内容读入到<内存>中
- 输出流:将<内存>中的内容读入到<存储设备>中
- 按单位:
- 字节流:以字节为单位,可以读写所有数据,使用字节流可以复制任意文件
- 字符流:以字符为单位,只能读写文本数据,使用字符流只能复制文本文件
- 按功能:
- 节点流:具有实际传输数据的读写功能
- 过滤流:在节点流的基础之上增强功能
字节流
- 字节流的父类(抽象类):
- InputStream:字节输入流
- OutputStream:字节输出流
文件字节流
FileInputStream的使用
package com.yushuo.byteStream;
import java.io.FileInputStream;
/**
* 演示FileInputStream的使用
* 文件字节输入流
*/
public class Demo01 {
public static void main(String[] args) throws Exception {
//创建FileInputStream,并指定文件路径
FileInputStream fileInputStream = new FileInputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\FileInputStreamTest.txt");//文件路径
//读取文件
/*
//单个字节读取
int date = 0;
while ((date = fileInputStream.read()) != -1){
//date输出的是字符对应的ASCII码,可以进行转换
System.out.print((char) date);
}
*/
//一次读取多个字节
byte[] buffer = new byte[3];
int count = 0;//每次实际读取的字符的个数
while ((count = fileInputStream.read(buffer)) != -1){
//将数组0到count的内容转换为字符串,输出
System.out.print(new String(buffer,0,count));
}
//关闭
fileInputStream.close();
System.out.println();
System.out.println("执行完毕!");
}
}
FileOutputStream的使用
package com.yushuo.byteStream;
import java.io.FileOutputStream;
/**
* 演示FileOutputStream的使用
* 文件字节输出流
*/
public class Demo02 {
public static void main(String[] args) throws Exception {
//创建FileOutputStream,并指定文件路径
FileOutputStream fileOutputStream = new FileOutputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\FileOutputStreamTest.txt",//文件路径
true);//true即不覆盖之前的内容,没有true会覆盖
//写入文件
/*
//一次写一个字符
fileOutputStream.write(97);//a
fileOutputStream.write(98);//b
fileOutputStream.write(99);//c
*/
String string = "hello world";
fileOutputStream.write(string.getBytes());
//关闭
fileOutputStream.close();
System.out.println("执行完毕!");
}
}
字节流复制文件
package com.yushuo.byteStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* 使用文件字节流实现文件的复制
*/
public class Demo03 {
public static void main(String[] args) throws Exception {
//创建FileInputStream,并指定文件路径
FileInputStream fileInputStream = new FileInputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\001.png");
//创建FileOutputStream,并指定文件路径
FileOutputStream fileOutputStream = new FileOutputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\002.png");
//一边读,一边写
byte[] buffer = new byte[1024];//1K的缓冲区
int count = 0;//读取的字符数
while ((count = fileInputStream.read(buffer)) != -1){
fileOutputStream.write(buffer,0,count);
}
//关闭
fileInputStream.close();
fileOutputStream.close();
System.out.println("执行完毕!");
}
}
字节缓冲流
- 缓冲流:BufferedInputStream/BufferedOutputStream
- 提高IO效率,减少访问磁盘的次数
- 数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close
BufferedInputStream的使用
package com.yushuo.byteStream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
/**
* 使用字节缓冲流BufferedInputStream读取
*/
public class Demo04 {
public static void main(String[] args) throws Exception{
//创建BufferedInputStream
FileInputStream fileInputStream = new FileInputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\BufferedInputStreamTest.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
/*
//读取
int date = 0;
while ((date = bufferedInputStream.read()) != -1){
System.out.print((char) date);
}
*/
//自己创建缓冲区
byte[] buffer = new byte[1024];
int count = 0;
while ((count = bufferedInputStream.read(buffer)) != -1){
System.out.println(new String(buffer,0,count));
}
//关闭
bufferedInputStream.close();
//关闭bufferedInputStream会默认关闭fileInputStream
System.out.println("执行完毕!");
}
}
BufferedOutputStream的使用
package com.yushuo.byteStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
/**
* 使用字节缓冲流BufferedOutputStream写入文件
*/
public class Demo05 {
public static void main(String[] args) throws Exception{
//创建BufferedOutputStream
FileOutputStream fileOutputStream = new FileOutputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\BufferedOutputStreamTest.txt");
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
//写入文件
for (int i = 0; i < 10; i++) {
bufferedOutputStream.write("helloworld\r\n".getBytes());//写入8K缓冲区
bufferedOutputStream.flush();//刷新到硬盘
}
//关闭
bufferedOutputStream.close();
System.out.println("执行完毕!");
}
}
对象流
-
对象流:ObjectOutputStream/ObjectInputStream
- 增强了缓冲区功能
- 增强了读写8种基本数据类型和字符串功能
- 增强了读写对象的功能:
- readObject() 从流中读取一个对象
- writeObject(Object obj) 向流中写入一个对象
使用流传输对象的过程称为序列化、反序列化
序列化与反序列化
package com.yushuo.objectStream;
import java.io.Serializable;
public class Student implements Serializable {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
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 "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.yushuo.objectStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
/**
* 使用ObjectOutputStream实现对象的序列化
* 要求:序列化的对象需要实现Serializable接口
*/
public class Demo01 {
public static void main(String[] args) throws Exception{
//创建对象流
FileOutputStream fileOutputStream = new FileOutputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\ObjectStreamTest.bin");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
//序列化(写入操作)
Student zhangsan = new Student("zhangsan",20);
objectOutputStream.writeObject(zhangsan);
//NotSerializableException,类不能序列化
//因此,需要实现Serializable接口,以显示类可以序列化
//关闭
objectOutputStream.close();
System.out.println("序列化完毕!");
}
}
package com.yushuo.objectStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
/**
* 使用ObjectInputStream实现对象的反序列化(读取重构成对象)
* 要求:序列化的对象需要实现Serializable接口
*/
public class Demo02 {
public static void main(String[] args) throws Exception{
//创建对象流
FileInputStream fileInputStream = new FileInputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\ObjectStreamTest.bin");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
//反序列化(读取操作)
Student student = (Student) objectInputStream.readObject();
//关闭
objectInputStream.close();
System.out.println("反序列化完毕!");
System.out.println(student);
}
}
注意事项
-
序列化类必须要实现Serializable接口
-
序列化类中对象属性要求实现Serializable接口,即如果属性中有类,类也需要实现Serializable接口
-
序列化版本号ID,保证序列化的类和反序列化的类是同一个类
序列化版本号ID,serialVersionUID,为实现Serializable接口时可以添加的一个静态常量private static final long serialVersionUID,系统根据版本号ID判断序列化与反序列化是不是同一个类
-
使用transient(瞬间的)修饰属性,这个属性不能序列化
-
静态属性不能序列化
-
序列化多个对象,可以借助集合实现。
序列化几次对象就可以反序列化几次,如果向一次性序列化多个对象,将他们放入一个集合,将集合序列化,反序列化得到的也是一个集合,对集合进行操作
字符编码
- ISO-8859-1 收录处ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号——单字节表示一个字符
- UTF-8 针对Unicode码表的可变长度字符编码——多字节表示一个字符
- GB2312 简体中文
- GBK 简体中文、扩充
- BIG5 台湾,繁体中文
- 当编码方式和解码方式不一致时,会出现乱码
字符流
- 字符流的父类(抽象类):
- Reader:字符输入流:
- public int read(){}
- public int read(char[] c){}
- public int read(char[] b, int off, int len){}
- Writer:字符输出流:
- public void write(int n){}
- public void write(String str){}
- public void write(char[] c){}
- Reader:字符输入流:
文件字符流
- FileReader:
- public int read(char[] c) //从流中读取多个字符,将读到内容存入c数组,返回实际读到的字符数;如果到达文件的尾部,则返回-1
- FileWriter:
- public void write(String str) //一次写多个字符,将b数组中所有字符,写入输出流
FileReader的使用
package com.yushuo.charStream;
import java.io.FileReader;
/**
* 使用FileReader读取文件
*/
public class Demo01 {
public static void main(String[] args) throws Exception{
//创建FileReader文件字符输入流
FileReader fileReader = new FileReader(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\FileReaderTest.txt");
//读取
/*
//单个字符读取
int date = 0;
while ((date = fileReader.read()) != -1){//读取一个字符,不是字节
System.out.print((char) date);
}
*/
//创建缓冲区
char[] buffer = new char[1024];
int count = 0;
while ((count = fileReader.read(buffer)) != -1){
System.out.println(new String(buffer,0,count));
}
//关闭
fileReader.close();
System.out.println("执行完毕!");
}
}
FileWriter的使用
package com.yushuo.charStream;
import java.io.FileWriter;
/**
* 使用FileWriter写入文件
*/
public class Demo02 {
public static void main(String[] args) throws Exception{
//创建FileWriter对象
FileWriter fileWriter = new FileWriter(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\FileWriterTest.txt");
//写入
for (int i = 0; i < 10; i++) {
fileWriter.write("你好世界helloworld\r\n");//\r\n换行
fileWriter.flush();//刷新到硬盘
}
//关闭
fileWriter.close();
System.out.println("执行完毕!");
}
}
字符流复制文件
package com.yushuo.charStream;
import java.io.FileReader;
import java.io.FileWriter;
/**
* 字符流复制文本文件,不能复制图片或二进制文件
*/
public class Demo03 {
public static void main(String[] args) throws Exception{
//创建FileReader和FileWriter
FileReader fileReader = new FileReader(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\FileWriterTest.txt");
FileWriter fileWriter = new FileWriter(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\Copy.txt");
//读写
int date = 0;
while ((date = fileReader.read()) != -1){
fileWriter.write(date);
fileWriter.flush();
}
//关闭
fileReader.close();
fileWriter.close();
System.out.println("复制完毕!");
}
}
字符缓冲流
-
缓冲流:BufferedReader/BufferedWriter
- 高效读写
- 支持输入换行符
- 可一次写一行、读一行
BufferedReader的使用
package com.yushuo.charStream;
import java.io.BufferedReader;
import java.io.FileReader;
/**
* 使用字符缓冲流读取文件
* BufferedReader
*/
public class Demo04 {
public static void main(String[] args) throws Exception{
//创建缓冲流
FileReader fileReader = new FileReader(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\FileWriterTest.txt"
);
BufferedReader bufferedReader = new BufferedReader(fileReader);
//读取
/*
//第一种方式
char[] buffer = new char[1024];
int count = 0;
while ((count = bufferedReader.read(buffer)) != -1){
System.out.print(new String(buffer,0,count));
}
*/
//第二种方式,一行一行读
String line = null;
while ((line = bufferedReader.readLine()) != null){
System.out.println(line);
}
//关闭
bufferedReader.close();
System.out.println("执行完毕!");
}
}
BufferedWriter的使用
package com.yushuo.charStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
/**
* 使用字符缓冲流写入文件
* BufferedWriter
*/
public class Demo05 {
public static void main(String[] args) throws Exception{
//创建缓冲流
FileWriter fileWriter = new FileWriter(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\BufferedWriterTest.txt");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
//写入
for (int i = 0; i < 10; i++) {
bufferedWriter.write("好好学习,天天向上!");
bufferedWriter.newLine();//写入一个换行符,如果是win,换行符为\r\n,linux为\n
bufferedWriter.flush();
}
//关闭
bufferedWriter.close();
System.out.println("执行完毕!");
}
}
打印流
- PrintWriter:
- 封装了print() / println() 方法,支持写入后换行
- 支持数据原样打印
package com.yushuo.charStream;
import java.io.PrintWriter;
/**
* 演示打印流PrintWriter的使用
*/
public class Demo06 {
public static void main(String[] args) throws Exception{
//创建打印流
PrintWriter printWriter = new PrintWriter(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\PrintWriterTest.txt");
//打印,打印原文
printWriter.println(97);//内部自动调用flush()
printWriter.println(true);
printWriter.println(3.14);
printWriter.println("a");
//关闭
printWriter.close();
System.out.println("执行完毕!");
}
}
转换流
内存中字符与硬盘中字节的转换
- 桥转换流:InputStreamReader/OutputStreamWriter
- 可将字节流转换为字符流
- 可设置字符的编码方式
InputStreamReader的使用
package com.yushuo.changeStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
/**
* InputStreamReader的使用,使用指定的编码
*/
public class Demo01 {
public static void main(String[] args) throws Exception{
//创建InputStreamReader对象
FileInputStream fileInputStream = new FileInputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\BufferedWriterTest.txt");
//InputStreamReader可以指定编码方式,需要和文件方式相同
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"utf-8");
//读取文件
int date = 0;
while ((date = inputStreamReader.read()) != -1){
System.out.print((char) date);
}
//关闭
inputStreamReader.close();
System.out.println("执行完毕!");
}
}
OutputStreamWriter的使用
package com.yushuo.changeStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
/**
* OutputStreamWriter的使用,使用指定的编码
*/
public class Demo02 {
public static void main(String[] args) throws Exception{
//创建OutputStreamWriter对象
FileOutputStream fileOutputStream = new FileOutputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\OutputStreamWriterTest.txt");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"gbk");
//写入
for (int i = 0; i < 10; i++) {
outputStreamWriter.write("好好学习,天天向上!\r\n");
outputStreamWriter.flush();
}
//关闭
outputStreamWriter.close();
System.out.println("执行完毕!");
}
}
File类
- 概念:代表物理盘符中的一个文件或者文件夹
- 方法:
- createNewFile()//创建一个新文件
- mkdir()//创建一个新目录
- delete()//删除文件或空目录
- exists()//判断File对象所代表的对象是否存在
- getAbsolutePath()//获取文件的绝对路径
- getName()//取得名字
- getParent()//获取文件/目录所在的目录
- isDirectory()//是否为目录
- isFile()//是否为文件
- length()//获得文件的长度
- listFiles()//列出目录中的所有内容
- renameTo()//修改文件名为
File类的使用
package com.yushuo.file;
import java.io.File;
import java.util.Date;
/**
* File类的使用
* (1)分隔符
* (2)文件操作
* (3)文件夹操作
*/
public class Demo01 {
public static void main(String[] args) throws Exception{
//separator();
//fileOperation();
directoryOperation();
}
//分隔符
public static void separator(){
System.out.println("路径分隔符:" + File.pathSeparator);
System.out.println("名称分隔符:" + File.separator);
}
//文件操作
public static void fileOperation() throws Exception{
//创建文件,文件路径可能存在也可能不存在
//创建文件对象
File file = new File(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\FileTest.txt");
//创建文件,判断文件是否存在,不存在则创建文件
if (! file.exists()){
boolean b = file.createNewFile();
System.out.println("创建结果:" + b);
}
/*
//删除文件
//直接删除
System.out.println("删除结果为:" + file.delete());
//使用jvm退出时删除
file.deleteOnExit();
*/
//获取文件信息
System.out.println("文件的绝对路径为:" + file.getAbsolutePath());//从盘符开始
System.out.println("文件的路径为:" + file.getPath());//创建文件对象时写什么就是什么
System.out.println("文件的名称为:" + file.getName());
System.out.println("文件的父目录为:" + file.getParent());
System.out.println("文件的长度为:" + file.length());//单位:字节
//返回的是long类型,可以转换为Data
System.out.println("文件的创建时间为:" + new Date(file.lastModified()).toLocaleString());
//判断
System.out.println("文件是否可写:" + file.canWrite());
System.out.println("是否是文件:" + file.isFile());
System.out.println("是否隐藏:" + file.isHidden());
}
//文件夹操作
public static void directoryOperation() throws Exception{
//创建文件夹
File directory = new File(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\DirectoryOperation");
if (! directory.exists()){
//创建目录
//directory.mkdir()只能创建单级目录
//directory.mkdirs()可以创建多级目录
System.out.println("创建结果为:" + directory.mkdirs());
}
/*
//删除文件夹
//直接删除,多级目录只删除最底层的目录,而且必须是空目录
System.out.println("删除结果为:" + directory.delete());
//使用jvm退出时删除
directory.deleteOnExit();
*/
//获取文件夹信息
System.out.println("文件夹的绝对路径为:" + directory.getAbsolutePath());//从盘符开始
System.out.println("文件夹的路径为:" + directory.getPath());//创建文件对象时写什么就是什么
System.out.println("文件夹的名称为:" + directory.getName());//只是最底层文件夹名字
System.out.println("文件夹的父目录为:" + directory.getParent());
System.out.println("文件夹的创建时间为:" + new Date(directory.lastModified()).toLocaleString());
//判断
System.out.println("是否是文件夹:" + directory.isDirectory());
System.out.println("是否隐藏:" + directory.isHidden());
//遍历文件夹
File directory1 = new File(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File");
String[] files = directory1.list();
//directory1.list()返回的是字符串数组
//directory1.listFiles()返回的是File数组
for (String file : files) {
System.out.println(file);
}
}
}
FileFilter接口
- public interface FileFilter
- boolean accept(File pathname)
- 当调用File类中的listFiles()方法时,支持传入FileFilter接口接口实现类,对获取文件进行过滤,只有满足条件的文件才可出现在listFiles()的返回值中
package com.yushuo.file;
import java.io.File;
import java.io.FileFilter;
/**
* FileFilter接口的使用
*/
public class Demo02 {
public static void main(String[] args) throws Exception{
directoryOperation();
}
//文件夹操作
public static void directoryOperation() throws Exception{
//遍历文件夹
File directory = new File(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File");
File[] files = directory.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.getName().endsWith(".txt")){
return true;
}
return false;
}
});
for (File file : files) {
System.out.println(file.getName());
}
}
}
递归遍历和递归删除
package com.yushuo.file;
import java.io.File;
/**
* 递归遍历文件夹
*/
public class Demo03 {
public static void main(String[] args) {
listdir(new File(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\ListDir"));
deletedir(new File(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\ListDir"));
}
//递归遍历文件夹
public static void listdir(File dir){
File[] files = dir.listFiles();
System.out.println(dir.getAbsolutePath());
if (files != null && files.length >0){
for (File file : files) {
if (file.isDirectory()){
listdir(file);
} else {
System.out.println(file.getAbsolutePath());
}
}
}
}
//递归删除文件夹
public static void deletedir(File dir){
File[] files = dir.listFiles();
System.out.println(dir.getAbsolutePath());
if (files != null && files.length >0){
for (File file : files) {
if (file.isDirectory()){
deletedir(file);
} else {
System.out.println(file.getAbsolutePath() + "删除:" + file.delete());
}
}
}
System.out.println(dir.getAbsolutePath() + "删除" + dir.delete());
}
}
Properties
- Properties:属性集合
- 特点
- 存储属性名和属性值
- 属性名和属性值都是字符串类型
- 没有泛型
- 和流有关
Properties的使用
package com.yushuo.properties;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.Set;
/**
* Properties集合的使用
*/
public class Demo01 {
public static void main(String[] args) throws Exception{
//创建集合
Properties properties = new Properties();
//添加数据
properties.setProperty("username","zhangsan");
properties.setProperty("age","20");
System.out.println(properties);
//遍历
//keyset
//entryset
//stringPropertyNames
Set<String> pronames = properties.stringPropertyNames();
for (String proname : pronames) {
System.out.println(proname + ":" + properties.getProperty(proname));
}
//和流有关的方法
//list
PrintWriter printWriter = new PrintWriter(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\Print.txt");
properties.list(printWriter);
printWriter.close();
//store保存
FileOutputStream fileOutputStream = new FileOutputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\Store.txt");
properties.store(fileOutputStream,"注释");
fileOutputStream.close();
//load加载
Properties properties1 = new Properties();
FileInputStream fileInputStream = new FileInputStream(
"D:\\Program_Files\\JetBrains\\JavaProjects\\File\\Store.txt");
properties1.load(fileInputStream);
fileInputStream.close();
System.out.println(properties1);
}
}
总结
- 流的概念:
- 内存与存储设备之间传输数据的通道
- 流的分类:
- 输入流、输出流;字节流、字符流;节点流、过滤流;
- 序列化、反序列化:
- 将对象通过流写入到文件,或将对象通过流读取到内存,必须实现Serializable接口
- File对象:
- 代表物理盘符中的一个文件或者文件夹