Java I/O框架
概念:内存与存储设备之间传输数据的通道。
分类:
- 按方向:
- 输入流:将存储设备中的内容读到内存中
- 输出流:将内存中的内容写到存储设备中
- 按单位:
- 字节流:以字节为单位,可以读写所有数据
- 字符流:以字符为单位,只能读写文本数据
- 按功能
- 节点流:具有实际传输数据的读写功能
- 过滤流:在节点流的基础之上增强功能
字节流
字节流的父类(抽象类):InputStream、OutputStream
文件字节流(子类):
FileInputStream
public int read(byte[] b): 从流中读取多个字节,将读到的内容存入b数组,返回实际读到的字节数,如果达到文件的尾部,则返回-1
FileOutputStream
public void write(byte[] b):一次写多个字节,将b数组中的所有字节,写入输出流
//1. 创建FileInputStream,并指定文件路径
FileInputStream fis = new FileInputStream("D:\\aaa.txt");
//2. 读取文件
// int data =0;
// while((data=fis.read())!=-1){
// System.out.print((char) data+" ");
// }
byte[] buf = new byte[3];
int count = 0;
while((count=fis.read(buf))!=-1){
System.out.println(count);
System.out.println(new String(buf,0,count));
}
//3. 关闭
fis.close();
FileOutputStream fos = new FileOutputStream("d:\\bbb.txt",true);
// fos.write(97);
// fos.write('b');
// fos.write('c');
String s ="hello world";
fos.write(s.getBytes());
fos.close();
小案例
对磁盘中的照片进行复制,过程为先将文件读到内存中,再写入磁盘中。
FileInputStream fis = new FileInputStream("D:\\3.jpg");
FileOutputStream fos = new FileOutputStream("D:\\1.jpg");
byte[] bytes = new byte[1024];
int count = 0;
while((count=fis.read(bytes))!=-1){
// System.out.println(count);
// System.out.println(bytes);
fos.write(bytes,0,count);
}
System.out.println("执行完毕");
fis.close();
fos.close();
字节缓冲流
缓冲流:BufferedInputStream/BufferedOutputStream
- 提高IO效率,减少访问磁盘的次数
- 数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close
BufferedInputStream有一个缓冲区,大小为8k,另也可以使用自己的缓冲区
FileInputStream fis = new FileInputStream("d:\\aaa.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
// int data = 0;
// while((data=bis.read())!=-1){
// System.out.print((char) data);
// }
byte[] bytes = new byte[1024];
int count = 0;
while((count=bis.read(bytes))!=-1){
System.out.print(new String(bytes,0,count));
}
FileOutputStream fos = new FileOutputStream("d:\\buffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
for(int i=0;i<10;i++){
bos.write("hello world".getBytes());
}
如果只是这样,磁盘中只会多一个buffer.txt,但是里面没有内容,这是因为内容只是写到了缓冲区,需要使用flush进行刷新
FileOutputStream fos = new FileOutputStream("d:\\buffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
for(int i=0;i<10;i++){
bos.write("hello world".getBytes());
}
FileOutputStream fos = new FileOutputStream("d:\\buffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
for(int i=0;i<10;i++){
bos.write("hello world\n".getBytes());
bos.flush();//调用flush会将磁盘缓冲区的内容刷新到硬盘中
}
bos.close();//即使上边没有写flush,只要是调用close,会自动调用flush,一次性将缓冲区内容刷新到硬盘中
对象流
对象流:ObjectInputStream、ObjectOutputStream
- 增强了缓冲区功能
- 增强了读写8种基本数据类型和字符串功能
- 增强了读写对象的功能 readObject() 从流中读取一个对象 writeObject(Object obj)向流中写入一个对象
使用流传输对象的过程称为序列化ObjectOutputStream、反序列化ObjectInputStream
序列化ObjectOutputStream
FileOutputStream fos = new FileOutputStream("d:\\stu.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Student s1 = new Student("张三", 20);
oos.writeObject(s1);
oos.close();
System.out.println("序列化完毕");
如果直接添加一个对象,就会出现以上错误,序列化失败,需要在类中实现一个接口Serializable(此接口并无方法是一个标志类接口)
public class Student implements Serializable
反序列化ObjectInputStream
FileInputStream fis = new FileInputStream("d:\\aaa.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
Student s1 = (Student) ois.readObject();
System.out.println(s1.getName());
System.out.println(s1.getAge());
ois.close();
//在Student类中声明的静态常量serialVersionUID,作用是表明序列化与反序列化时是同一个类
private static final long serialVersionUID = 100L;
- 序列化必须实现Serializable接口
- 序列化的类中对象属性要求实现Serializable接口
- serialVersionUID表明序列化与反序列化时是同一个类
- 若想有些属性不被序列化,只需在属性之前添加transient修饰。
- 静态属性也不能序列化的。
- 当需要序列化多个对象时,可以借助集合。
FileOutputStream fos = new FileOutputStream("d:\\aaa.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Student s1 = new Student("张三",20);
Student s2 = new Student("李四",25);
// oos.writeObject(s1);
// oos.writeObject(s2);
ArrayList<Student> arrayList = new ArrayList<>();
arrayList.add(s1);
arrayList.add(s2);
oos.writeObject(arrayList);
oos.close();
FileInputStream fis = new FileInputStream("d:\\aaa.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
// Student s1 = (Student) ois.readObject();
// Student s2 = (Student) ois.readObject();
ArrayList<Student> arrayList = (ArrayList<Student>) ois.readObject();
System.out.println(arrayList);
ois.close();
字符编码
ISO-8859-1:收录了ASCII、西欧、希腊语、泰语、阿拉伯语、希伯来语
UTF-8:针对Unicode码表的可变长度字符编码
GB2312:简体中文
GBK:简体中文、扩充
BIG5台湾:繁体
字符流
字符流的父类(抽象类):Reader(字符输入流)、Writer(字符输出流)
文件字符流(FileReader、FileWriter)
1. FileReader
//1. 创建FileReader 文件字符输入流
FileReader fileReader = new FileReader("d:\\hello.txt");
//2.1 单个字符读取
// int data =0;
// while((data=fileReader.read())!=-1){
// System.out.print((char)data);
// }
//2.2 多个字符读取
char[] buf = new char[1024];
int count=0;
while((count=fileReader.read(buf))!=-1){
System.out.println(new String(buf,0,count));
}
2. FileWriter
FileWriter fileWriter = new FileWriter("d:\\hello.txt",true);
for(int i=0;i<10;i++){
fileWriter.write("hello\n");
fileWriter.flush();
}
fileWriter.close();
利用字符流FileWriter、FileReader实现文本文件复制,不能复制图片或二进制文件
FileReader fileReader = new FileReader("d:\\hello.txt");
FileWriter fileWriter = new FileWriter("d:\\aa.txt");
char[] buf= new char[1024];
int count= 0;
while((count=fileReader.read(buf))!=-1){
fileWriter.write(buf);
}
System.out.println("复制完成");
fileReader.close();
fileWriter.close();
字符缓冲流(BufferedReader、BufferedWriter)
- 高效读写
- 支持输入换行符
- 可一次写一行、读一行
FileReader fileReader = new FileReader("d:\\hello.txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
//方法一
int count = 0;
while((count=bufferedReader.read())!=-1){
System.out.print((char) count);
}
//方法二
// char[] buf = new char[1024];
// int count = 0;
// while((count=bufferedReader.read(buf))!=-1){
// System.out.println(new String(buf,0,count));
// }
//方法三 一行一行的读取
// String s = null;
// while((s=bufferedReader.readLine())!=null){
// System.out.println(s);
// }
// bufferedReader.close();
FileWriter fileWriter = new FileWriter("d:\\c.txt");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
for (int i = 0; i <10 ; i++) {
bufferedWriter.write("我正在学习Java");
bufferedWriter.newLine();//换行
bufferedWriter.flush();
}
bufferedWriter.close();
打印流
PrintWriter:
- 封装了print()/println()方法,支持写入后换行
- 支持数据原样打印
PrintWriter printWriter = new PrintWriter("d:\\print.txt");
printWriter.println("你好");
printWriter.println(123);
printWriter.println(3.14);
printWriter.println(true);
printWriter.close();
转换流
桥转换流:InputStreamReader/OutputStreamWriter
- 可以将字节流(硬盘上)转为字符流(内存中)/字符流转为字节流
- 可设置字符的编码方式
使用OutputStreamWriter读入
FileInputStream fileInputStream = new FileInputStream("d:\\c.txt");
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"utf-8");
int data = 0;
while((data=inputStreamReader.read())!=-1){
System.out.print((char) data);
}
inputStreamReader.close();
FileOutputStream fileOutputStream = new FileOutputStream("d:\\c.txt");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"utf-8");
for(int i=0;i<10;i++){
outputStreamWriter.write("Java学习\n");
}
outputStreamWriter.close();
System.out.println("执行完毕");
File类
代表物理盘符中的一个文件或者文件夹
文件操作
方法 | 说明 |
---|---|
createNewFile() | 创建一个新文件 |
mkdir() | 创建一个新目录 |
delete() | 删除文件或者空目录 |
exists() | 判断File对象所代表的对象是否存在 |
getAbsolutePath() | 获取文件的绝对路径 |
getName() | 取的名字 |
getParent() | 获取文件/目录所在的目录 |
isDirectory() | 是否是目录 |
isFile() | 是否是文件 |
length() | 获得文件的长度 |
listFiles() | 列出目录中的所有内容 |
renameTo() | 修改文件名 |
File file = new File("d:\\test.txt");
//1. 创建文件
if(!file.exists()){
System.out.println("创建结果:"+ file.createNewFile());
}
//2.1 直接删除
//System.out.println("删除结果:"+file.delete());
//2.2 使用JVM退出时删除
// file.deleteOnExit();
// Thread.sleep(5000); jvm休眠五秒钟
//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.isFile());
System.out.println("是否为隐藏文件:"+file.isHidden());
System.out.println("是否为可写文件:"+file.canWrite());
文件夹操作
File file = new File("d:\\aaa\\bbb\\ccc");
//1. 创建文件夹
if(!file.exists()){
file.mkdir();//创建单级目录
System.out.println("创建结果:"+file.mkdirs());
}
//2. 删除文件夹
//2.1 直接删除(只能删除空文件夹,且只能删除最里层的文件夹)
//System.out.println("删除结果:"+file.delete());
//3.1 使用jvm结束时删除
//file.deleteOnExit();
//Thread.sleep(5000);
//3. 获取文件夹信息
System.out.println("获取绝对路径:"+file.getAbsolutePath());
System.out.println("获取路径:"+file.getPath());
System.out.println("获取最底层文件夹名称:"+file.getName());
System.out.println("获取父目录:"+file.getParent());
System.out.println("创建时间为:"+new Date(file.lastModified()).toLocaleString());
//4. 判断
System.out.println("是否为目录:"+file.isDirectory());
System.out.println("是否隐藏:"+file.isHidden());
//5. 遍历文件夹
String[] list = file.list();
for (String s : list) {
System.out.println(s);
}
FileFilter接口
过滤以.png为后缀的文件
File file1 = new File("d:\\照片");
File[] files = file1.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if(pathname.getName().endsWith(".png")){
return true;
}
return false;
}
});
for (File file2 : files) {
System.out.println(file2);
}
递归遍历文件夹
public static void main(String[] args) {
show(new File("d:\\aaa"));
}
public static void show(File dir){
File[] files = dir.listFiles();
System.out.println(dir.getAbsolutePath());
if(files!=null&&files.length>0){
for (File file : files) {
if(file.isDirectory()){
show(file);
}else{
System.out.println(file.getAbsolutePath());
}
}
}
}
递归删除文件夹
public static void main(String[] args) {
delete(new File("d:\\aaa"));
}
public static void delete(File dir){
File[] files = dir.listFiles();
if(files!=null&&files.length>0){
for (File file : files) {
if(file.isDirectory()){
delete(file);
}else{
System.out.println(file.getAbsolutePath()+"删除:"+file.delete());
}
}
}
System.out.println(dir.getAbsolutePath()+"删除:"+dir.delete());
}
Properties
特点:
- 存储属性名和属性值
- 属性名和属性值都是字符串类型
- 没有泛型
- 和流有关
Properties properties = new Properties();
properties.setProperty("name","zhangsan");
properties.setProperty("age","20");
System.out.println(properties);
Set<Object> objects = properties.keySet();
for(Object obj:objects){
System.out.println(obj+" "+properties.getProperty(obj.toString()));
}
System.out.println();
Set<Map.Entry<Object, Object>> entries = properties.entrySet();
for(Map.Entry<Object, Object> entry:entries){
System.out.println(entry.getKey()+" "+entry.getValue());
}
System.out.println();
Set<String> strings = properties.stringPropertyNames();
for (String string : strings) {
System.out.println(string+" "+properties.getProperty(string));
}
//和流有关的方法 list
// PrintWriter printWriter = new PrintWriter("d:\\test.txt");
// properties.list(printWriter);
// printWriter.close();
//保存 store
// FileOutputStream fileOutputStream = new FileOutputStream("d:\\store.properties");
// properties.store(fileOutputStream,"注释");
// fileOutputStream.close();
//加载 load
Properties properties1 = new Properties();
FileInputStream fileInputStream = new FileInputStream("d:\\store.properties");
properties1.load(fileInputStream);
System.out.println(properties1);
fileInputStream.close();