目录
1、流的概念
内存与存储设备之间传输数据的通道
2、流的分类
2.1、按方向(重点)
- 输入流:将<存储设备>中的内容读到<内存>中
- 输出流:将<内存>中的内容写到<存储设备>中
2.2、按单位
- 字节流:以字节为单位,可以读写所有数据
- 字符流:以字符为单位,只能读写文本数据
2.3、按功能
- 节点流:具有实际传输数据的读写功能
- 过滤流:在节点流的基础之上增强功能
3、字节流
字节流的父类(抽象类)
//InputStream 字节输入流
public int read(){}
public int read(byte[] b){}
public int read(byte[] b, int off, int len){}
// OutputStream 字节输出流
public void write(int n){}
public void write(byte[] b){}
public void write(byte[] b, int off, int len){}
3.1、文件字节流
package com.liuxiang.IO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 演示FileInputStream的使用
* 文件字节输入流
* @author 86187
*/
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
// 1.创建FileInputStream,并指定文件路径
FileInputStream fileInputStream = new FileInputStream("d:\\aaa.txt");
// 2.读取文件 read()
// 2.1单字节读取
// int data = 0;
// while((data=fileInputStream.read())!=-1){
// System.out.print((char)data);
// }
// 2.2一次读取多个字节
byte[] bytes = new byte[3];
int count = 0;
while ((count=fileInputStream.read(bytes))!=-1){
System.out.println(new String(bytes,0,count));
}
// 3.关闭
fileInputStream.close();
System.out.println("执行完毕");
}
}
package com.liuxiang.IO;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 演示FileOutputStream的使用
* 文件字节输出流
* @author 86187
*/
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
// 1.创建文件字节输出流对象
FileOutputStream fileOutputStream = new FileOutputStream("d:\\bbb.txt",true); // true表示不覆盖原来的写入
// 2.写入文件
fileOutputStream.write(97); // 97是字符a对应的ASCII编码
fileOutputStream.write('b');
fileOutputStream.write('c');
String s = " liuxiang";
fileOutputStream.write(s.getBytes());
// 3.关闭
fileOutputStream.close();
System.out.println("执行完毕");
}
}
图片复制实例
package com.liuxiang.IO;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyPictureDemo {
public static void main(String[] args) throws IOException {
// 1 创建流
// 1.1 文件字节输入流
FileInputStream fis = new FileInputStream("d:\\1.jpg");
// 1.2 文件字节输出流
FileOutputStream fos = new FileOutputStream("d:\\2.jpg");
// 2 边读边写
byte[] buf = new byte[1024];
int count = 0;
while((count = fis.read(buf)) != -1){
fos.write(buf, 0, count);
}
System.out.println("复制图片成功");
// 3 关闭
fis.close();
fos.close();
}
}
3.2、字节缓冲流
缓冲流:BufferedInputStream/ BufferedOutputStream
- 提高IO效率,减少访问磁盘次数
- 数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close
package com.liuxiang.IO;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
/**
* 使用字节缓冲流读取
* BufferedInputStream
* @author 86187
*/
public class BufferedInputStreamDemo {
public static void main(String[] args) throws IOException {
// 1.创建BufferedInputStream对象
FileInputStream fis = new FileInputStream("d:\\aaa.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
// 2.读取
int data = 0;
while ((data=bis.read())!=-1){
System.out.print((char)data);
}
// 自己创建缓冲区
byte[] buf = new byte[1024];
int count = 0;
while ((count=bis.read(buf))!=-1){
System.out.print(new String(buf,0,count));
}
System.out.println("读取完毕");
// 3.关闭
bis.close();
}
}
package com.liuxiang.IO;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 使用字节缓冲流写入
* BufferedOutputStream
* @author 86187
*/
public class BufferedOutputStreamDemo {
public static void main(String[] args) throws IOException {
// 1.创建字节输出缓冲流
FileOutputStream fos = new FileOutputStream("d:\\buffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 2.写入文件
for (int i=0;i<10;i++){
bos.write("helloworld".getBytes()); //写入缓冲区,还没有写入D盘文件
bos.flush(); // 刷新到D盘文件中
}
// 3.关闭
bos.close();
}
}
4、对象流
//对象流:ObjectOutputStream / ObjectInputStream
- 增强了缓冲区功能
- 增强了读写8种基本数据类型和字符串的功能
- 增强了读写对象的功能
readObject()
从流中读取一个对象writeObject(Object obj)
向流中写入一个对象
使用流传输对象的过程称为序列化、反序列化
4.1、序列化
// 使用objectoutputStream实现序列化
public static void main(String[] args) throws IOException {
// 1. 创建对象流
FileOutputStream fos = new FileOutputStream("d:\\st.bin");
ObjectOutputSream oos = new objectOutputSream(fos);
// 2. 序列化(写入操作)
Student zhangsan = new Student("zs", 20);
oos.WriteObject(zhangsan);
// 3. 关闭
oos.close();
System.out.print("序列化完毕");
}
4.2、反序列化
// 使用ObjectInputSteam实现反序列化(读取重构对象)
public static void main(String[] args) throws IOException {
// 1. 创建对象流
FileInputStream fis = new FileInputStream("d:\\stu.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
// 2. 读取文件(反序列化)
Student s = (Student)ois.readObject();
// 3. 关闭
ois.close();
System.out.print("执行完毕");
System.out.print(s.toString());
}
4.3、注意事项
-
某个类要想序列化必须实现Serializable接口
-
序列化类中对象属性要求实现Serializable接口
-
序列化版本号ID,保证序列化的类和反序列化的类是同一个类
-
使用transient修饰属性,这个属性就不能序列化
-
静态属性不能序列化
-
序列化多个对象,可以借助集合来实现
5、字符编码
- ISO-8859-1:收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号
- UTF-8:针对Unicode码表的可变长度字符编码
- GB2312:简体中文
- GBK:简体中文、扩充
- BIG5台湾:繁体中文
当编码方式与解码方式不一致时,会出现乱码。
6、字符流
字符流的父类(抽象类)
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){}
6.1、文件字符流
package com.liuxiang.IO;
/**
* 使用FileReader读取文件
* @author 86187
*/
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
// 1. 创建FileReader 文件字符输入流
FileReader fr = new FileReader("d:\\aaa.txt");
// 2. 读取
// 2.1 单个字符读取
int data = 0;
while((data = fr.read()) != -1){
System.out.print((char)data);// 读取一个字符
}
char[] buf = new char[2];// 字符缓冲区读取
int count = 0;
while((count = fr.read(buf))!= -1){
System.out.print(new String(buf, 0, count));
}
// 3. 关闭
fr.close();
}
}
package com.liuxiang.IO;
import java.io.FileWriter;
import java.io.IOException;
/**
* 使用FileWriter写入文件
* @author 86187
*/
public class FileWriterDemo {
public static void main(String[] args) throws IOException {
// 1. 创建FileWriter对象
FileWriter fw = new FileWriter("d:\\ccc.txt");
// 2. 写入
for(int i = 0; i < 10; i ++){
fw.write("写入的内容");
fw.flush();
}
// 3. 关闭
fw.close();
System.out.println("执行完毕");
}
}
文本复制实例
package com.liuxiang.IO;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* 使用FileReader和FileWriter复制文本文件
* 使用字符流不能复制图片或二进制文件,使用字节流可以复制任意文件
*/
public class CopyTxtDemo {
public static void main(String[] args) throws IOException {
// 1. 创建
FileReader fr = new FileReader("d:\\ccc.txt");
FileWriter fw = new FileWriter("d:\\ddd.txt");
// 2. 读写
int data = 0;
while((data = fr.read()) != -1){
fw.write(data);
fw.flush();
}
// 3. 关闭
fw.close();
fr.close();
}
}
6.2、字符缓冲流
// 字符流:BufferedReader / BufferedWriter
高效读写、支持输入换行符、可一次写一行读一行
package com.liuxiang.IO;
/**
* 使用字符缓冲流读取文件
* BufferedReader
* @author 86187
*/
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
// 创建缓冲流
FileReader fr = new FileReader("d:\\write.txt");
BufferedReader br = new BufferedReader(fr);
// 读取
// 1. 第一种方式
char[] buf = new char[1024];
int count = 0;
while((count = br.read(buf)) != -1){
System.out.print(new String(buf, 0, count));
}
// 2. 第二种方式 一行一行读取
String line = null;
while((line = br.readLine()) != null){
System.out.print(line);
}
// 关闭
br.close();
}
}
package com.liuxiang.IO;
/**
* 使用字符缓冲流写入文件
* BufferedWriter
* @author 86187
*/
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
// 1. 创建BufferedWriter对象
FileWriter fw = new FileWriter("d:buffer.txt");
BufferedWriter bw = new BufferedWriter(fw);
// 2. 写入
for(int i = 0; i < 10; i ++){
bw.write("写入的内容");
bw.newLine(); // 写入一个换行符
bw.flush();
}
// 3. 关闭
bw.close(); // 此时会自动关闭fw
}
}
7、打印流PrintWriter
封装了print() / println()
方法 支持写入后换行
支持数据原样打印
package com.liuxiang.IO;
/**
* 演示PrintWriter的使用
* @author 86187
*/
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class PrintWriterDemo {
public static void main(String[] args) throws FileNotFoundException {
// 1 创建打印流
PrintWriter pw = new PrintWriter("d:\\print.txt");
// 2 打印
pw.println(12);
pw.println(true);
pw.println(3.14);
pw.println('a');
// 3 关闭
pw.close();
}
}
8、转换流
桥转换流 InputStreamReader / OutputStreamWriter
可将字节流转换为字符流
可设置字符的编码方式
public static void main(String[] args) throws IOException {
// 1 创建InputStreamReader对象
FileInputStream fis = new FisInputStream("d:\\aaa.txt");
InputStreamReader isr = new InputStreamReader(fis, "utf-8");
// 2 读取文件
int data = 0;
while((data = isr.read()) != -1){
System.out.print((char)data);
}
// 3 关闭
isr.close();
}
public static void main(String[] args) throws IOException {
// 1 创建OutputStreamReader对象
FileOutputStream fos = new FisOutputStream("d:\\bbb.txt");
OutputStreamWRITER osw = new OutputStreamReader(fos, "utf-8");
// 2 写入
for(int i = 0; i < 10; i ++){
osw.write("写入内容");
osw.flush();
}
// 3 关闭
osw.close();
}
9、File类
概念:代表物理盘符中的一个文件或者文件夹
方法:
- createNewFile() //创建一个新文件
- mkdir() //创建一个新目录
- delete() //删除文件或空目录
- exists() //判断File对象所对象所代表的对象是否存在
- getAbsolutePath() //获取文件的绝对路径
- getName() //取得名字
- getParent() //获取文件/目录所在的目录
- isDirectory () //是否是目录
- isFile() //是否是文件
- length() //获得文件的长度
- listFiles() //列出目录中的所有内容
- renameTo() //修改文件名为
package com.liuxiang.IO;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Date;
/**
* File类的使用
* (1)分隔符
* (2)文件操作
* (3)文件夹操作
* @author 86187
*/
public class FileDemo {
public static void main(String[] args) throws Exception {
separator();
fileOpen();
directoryOpe();
}
public static void separator() {
System.out.println("路径分隔符"+ File.pathSeparator);
System.out.println("名称分隔符"+File.separator);
}
// 文件操作
public static void fileOpen() throws IOException {
// 1. 创建文件 createNewFile()
File file = new File("d:\\abc.txt");
if(!file.exists()){
boolean b = file.createNewFile();
System.out.println("创建结果"+b);
}
// 2. 删除文件
// 2.1 直接删除
// file.delete(); // 成功true
// // 2.2 使用jvm退出时删除
// file.deleteOnExit();
// 3. 获取文件信息
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());
System.out.println("文件创建时间" + new Date(file.lastModified()).toLocaleString());
// 4. 判断
System.out.println("是否可写" + file.canWrite());
System.out.println("是否是文件" + file.isFile());
System.out.println("是否隐藏" + file.isHidden());
}
// 文件夹操作
public static void directoryOpe() throws Exception{
// 1. 创建文件夹
File dir = new File("d:\\aaa\\bbb");
System.out.println(dir.toString());
if(!dir.exists()){
//dir.mkdir(); // 只能创建单级目录
dir.mkdirs(); // 创建多级目录
}
// 2. 删除文件夹
// 2.1 直接删除
// dir.delete(); // 只能删除最底层空目录
// // 2.2 使用jvm删除
// dir.deleteOnExit();
// 3. 获取文件夹信息
System.out.println("获取绝对路径" + dir.getAbsolutePath());
System.out.println("获取路径" + dir.getPath());
System.out.println("获取文件名称" + dir.getName());
System.out.println("获取夫目录" + dir.getParent());
System.out.println("获取文件长度" + dir.length());
System.out.println("文件夹创建时间" + new Date(dir.lastModified()).toLocaleString());
// 4. 判断
System.out.println("是否是文件夹" + dir.isFile());
System.out.println("是否隐藏" + dir.isHidden());
// 5. 遍历文件夹
File dir2 = new File("d:\\aaa\\bbb");
String[] files = dir2.list();
for(String string : files){
System.out.println(string);
}
// FileFilter接口的使用
// 当调用File类中的listFiles()方法时,支持传入FileFilter接口接口实现类,
// 对获取文件进行过滤,只有满足条件的文件的才可出现在listFiles()的返回值中。
File[] files2 = dir2.listFiles(new FileFilter(){
@Override
public boolean accept(File pathname){
if(pathname.getName().endsWith(".jpg")){
return true;
}
return false;
}
});
for(File file : files2){
System.out.println(file.getName());
}
}
}
9.1、递归遍历文件夹
public static void main(String[] args) throws Exception {
listDir(new File("d:\\myfiles"));
}
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());
}
}
}
}
9.2、递归删除文件夹
public static void deleteDir(File dir){
File[] files = dir.listFiles();
if(files != null && files.length > 0){
for(File file : files){
if(file.idDirectory()){
deleteDir(file); // 递归
}else{
// 删除文件
System.out.println(file.getAbsolutePath() + "删除" + file.delete());
}
}
}
}
10、Properties属性集合
特点
- 存储属性名和属性值
- 属性名和属性值都是字符串类型
- 没有泛型
- 和流有关
package com.liuxiang.IO;
import java.io.*;
import java.util.Properties;
import java.util.Set;
/**
* 演示Properties集合的使用
* @author 86187
*/
public class PropertiesDemo {
public static void main(String[] args) throws IOException {
// 1.创建集合
Properties properties = new Properties();
// 2.添加数据
properties.setProperty("username","zhangsan");
properties.setProperty("age","20");
System.out.println(properties.toString());
// 3.遍历
Set<String> set = properties.stringPropertyNames();
for (String pro:set) {
System.out.println(pro+"====="+properties.getProperty(pro));
}
// 4.和流有关的方法 列表list()
PrintWriter pw = new PrintWriter("d:\\print.txt");
properties.list(pw);
pw.close();
// 5.和流有关的方法 保存store()
FileOutputStream fos = new FileOutputStream("d:\\store.properties");
properties.store(fos,"注释");
fos.close();
// 6.和流有关的方法 加载load()
Properties properties1 = new Properties();
FileInputStream fis = new FileInputStream("d:\\store.properties");
properties1.load(fis);
fis.close();
System.out.println(properties1.toString());
}
}