Java Io

Java Io

1 按操作数据的类型分类

1.1字节流

  • 一般用于操作二进制文件,数据的单位是byte(视频,音频,图片,exe,dll等文件)

  • 以InputStream或OutputStream结尾

1.2字符流

  • 一般用于操作文本数据,数据的单位是char(txt,xml,html等文件)

  • 以Reade或Writer结尾

1.2.0按数据的流向分类

1.2.1 输入流

  • 从磁盘文件或网络流到java程序中,用于读取数据

  • 所有字节输入流的父类是InputStream;

  • 所有字符输入流的父类是Reade;

1.2.2 输出流

  • 从java程序流向磁盘文件或网络写入文件

  • 所有字节输出流的父类是OutputStream;

  • 所有字符输出流的父类是Writer;

1.3 File类

由于经常需要使用IO流来操作硬盘上的文件,JDK将硬盘上的文件映射为java.io.File类,所以我们先要学习如何使用这个类。

File类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建、文件的查找和文件的删除等。

File对象代表磁盘中实际存在的文件和目录。通过以下构造方法创建一个File对象。

  • 常用构造方法

new File(File parent,String child );
new File(String parent,String child);
new File(String pathName);
  • 常用方法

方法名描述
String getName()获取文件(夹)名
String getPath()获取文件(夹)路径
boolean exists()文件(夹)是否存在
boolean isFile()是否是一个文件
boolean isDirectory()是否是一个目录(文件夹)
boolean createNewFile()创建一个文件
boolean mkdir()创建一个具体的文件夹
boolean mkdirs()创建多级文件夹
boolean delete()删除某个文件(夹)
String [] list()返回某个文件夹下的所有文件(夹)名
File [] listFiles()获取某个文件夹下所有的文件(夹)

代码演示:

package yrh;
​
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
public class FileTest {
    public static void main(String[] args) throws IOException {
       File file=new File("D:/fff.txt");
       //输出文件是否存在
       System.out.println(file.exists());
       if (!file.exists()) {
       //创建这个文件
          file.createNewFile();  
       }
       //判断是否是一个文件
       System.out.println(file.isFile());
       //是否是一个目录
       System.out.println(file.isDirectory());
       //获取文件的名字
       System.out.println(file.getName());
       //获取文件路径
       System.out.println(file.getPath());
       //删除此文件
       file.delete();
       //返回dir目录的所有文件,以string[]数组保存
       File file2=new File("D:/dir");
       file2.mkdir();
       String[] list = file2.list();
       System.out.println(Arrays.toString(list));
     //返回dir目录的所有文件,以File[]数组保存
       File[] listFiles = file2.listFiles();
       for (File file3 : listFiles) {
        System.out.println(file3);
    }
       //删除目录
       file2.delete();
    }
}

代码演示:

要求:将盘中的qq.exe(D:\a\blb.jpg) 通过程序复制到另一个路径下(D:\b\qq.exe)。

package yrh;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class TetsIO {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //要求:将盘中的qq.exe(D:\a\blb.jpg)
        //通过程序复制到另一个路径下(D:\b\qq.exe)。
        //创建输入输出流接口
        InputStream fis=null;
        OutputStream fos=null;
        File f1=new File("d:/PCQQ2020.exe");
        File f2=new File("d:/test/PCQQ2020.exe");
        //创建目标文件
        if (!f2.exists()) {
            try {
                f2.createNewFile();
                //从f1读取文件流
                fis=new FileInputStream(f1);
                //写到f2输出流
                fos=new FileOutputStream(f2);
                //定义一个bety数组
                byte buffer[]=new byte[2048];
                int len=0;
                //循环读写文件
                while ((len=fis.read(buffer))!=-1) {
                    fos.write(buffer, 0, len);
                }
            } catch (IOException e) {
                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();
                    }
                }
            }
        }
    }
​
}

2文件读写

2.1文件读取

文件输入流FileInputStream

作用是:读取磁盘文件或网络的数据

FileInputStream(File file)
FileInputStream(String filepath)

主要方法:

  • int read(byte[] buffer)读取文件数据,保存到字节数组中,返回值是读取长度-1代表读取完毕

  • void close() 关闭文件流

try-with-resource IO流使用完后必须关闭,否则文件流无法得到释放,close方法调用要写在finally中。 为简化关闭流的代码,Java1.7引入了try-with-resource语法,让资源在try-catch完毕后自动关闭。 语法:

try(类 对象 = new 类()){
    可能出现异常的代码
}catch(异常类型 对象){
    处理异常的代码
}

文件读取过程

  1. 创建文件输入流

  2. 创建byte数组

  3. 循环调用read方法,存入byte数组中

  4. 操作byte数组

  5. 读取完毕关闭文件流

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class FileInputStreamTest {
​
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
//      1.创建文件输入流
        String filepath="D:/ddd.txt";
        InputStream input=new FileInputStream(filepath);
//      2.创建byte数组
        byte b[]=new byte[1024];
//      3.循环调用read方法读取数据,存入byte数组
        int len=0;
        while ((len=input.read(b))!=-1) {
              String str=new String(b,0,len,"UTF-8");
              System.out.println(str);
        }
//      4.操作byte数组
        
//      5.读取完毕关闭文件流
        input.close();
    }
​
}

2.2 文件写入

文件输出流 FileOutputStream

作用是 :将数据写入磁盘文件或网络

构造方法:

FileOutPutStream(File flie)
FileOutPutStream(String fliepath)

主要方法:

  • write(byte[] buffer,int offset,int length) 写入文件,offset开始位置,length写入长度

  • write(byte[] buffer)

  • close() 关闭流

文件写入步骤

  1. 创建文件输出流

  2. 将字符串转换问byte数组

  3. 调用writer方法

  4. 关闭文件流

package yrh;
​
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Scanner;
public class FileOutputStreamTest {
    public static void main(String[] args) {
        String filepath="d:/ccc.txt";
//      创建文件输出流
        try {
            OutputStream fos=new FileOutputStream(filepath);
            Scanner in = new Scanner(System.in);
            System.out.println("输入写入内容");
            String txt=in.next();
//          将字符串转换为byte数组
            //调用write写入文件
            fos.write(txt.getBytes());  
//          关闭文件流
            fos.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }   
    }
}

2.3文件的复制

文件的复制是在读取文件的同事,将数据写到另一个文件中

思路

  1. 创建文件输入输出流

  2. 通过文件输入流读取数据到byte数组中

  3. 同时将byte数组中的数据写入到输出流中

  4. 循环 1,2,3

package yrh;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Filecopy {
//文件复制
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		//读取文件位置
		String filepath="d:/ccc.txt";
		//写入文件位置
		String fileOut="d:/eee.txt";
//		1、创建输入流和输出流
		InputStream fis=new FileInputStream(filepath);
		OutputStream fos=new FileOutputStream(fileOut);
//		2、创建byte数组
		byte buffer[]=new byte[2048];
		int len=0;
		//循环从输入流中读取数据
		while ((len=fis.read(buffer))!=-1) {
			//向输出流中写入数据
			fos.write(buffer, 0, len);
		}
      //关闭文件流
	 //先使用的后关闭
		fos.close();
		fis.close();
		System.out.println("复制完成");
	}

}

3 缓冲

什么事缓冲

前提是内存的读写速度要远高于磁盘的读写速度,缓冲就是内存中的一块空间,通过缓冲可以提高数据的读写速度

JAVA的IO体系中有些流不能独立使用,必须套在其它流的上面才能使用,称为包装流。JAVA的IO体系就是通过装饰模式来实现。需要什么流的功能就在外面套一个对应的流即可,就像一个武士,需要一把武器就装饰一把武器,需要一身铠甲就套一层铠甲,这个武士就能使用武器跟铠甲的功能了。

而缓冲流就是常用的一个包装流,也叫高效流,是对4个基本的File 流的增强,所以也是4个流,按照数据类型分类:

  • 字节缓冲流BufferedInputStreamBufferedOutputStream

  • 字符缓冲流BufferedReaderBufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

为什么需要缓冲

如果没有缓冲,文件读写是直接从磁盘上进行的,速度比较慢;缓冲就是在内存建立一个空间,读写之前将一部分磁盘上的数据导入到

缓冲内存中,后面读写就直接从缓冲中进行,减少了直接冲磁盘读写的次数,从而提高读写效率。

缓冲流:在普通的IO流基础上,加入内存缓冲区提高IO效率

字节缓冲流

BufferdInputStream缓冲输入流

创建方法
     new BufferedInputStream(InputStream in);
     new BufferedInputStream(InputStream in,int bufferSize);创建一个`BufferedInputStream`并保存其参数,输入流`in`供以后使用。  内部缓冲区数组创建并存储在`buf` 。 

创建一个BufferedInputStream并保存其参数,输入流in供以后使用。 内部缓冲区数组创建并存储在buf

创建具有BufferedInputStream缓冲区大小的BufferedInputStream,并保存其参数,输入流in供以后使用。 长度为size的内部缓冲区阵列被创建并存储在buf

参数

in - 底层输入流。

size - 缓冲区大小。

BufferdOutputStream 缓冲输入流

BufferedOutputStream(OutputStream out) 
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。  
BufferedOutputStream(OutputStream out, int size) 
创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。  

使用非缓冲流和缓冲流进行文件复制的效率对比:

package yrh;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class BufferdInputStreamTest {
   //字节缓冲流
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		//读取文件位置
				String filepath="d:/ccc.txt";
				//写入文件位置
				String fileOut="d:/eee.txt";
		//程序开始时间
		long start = System.currentTimeMillis();
		System.out.println("使用文件缓冲流");
		//创建缓冲文件输入输出流对象
		InputStream fis=new BufferedInputStream(new FileInputStream(filepath));
		OutputStream fos=new BufferedOutputStream(new FileOutputStream(fileOut));
		//创建byte数组存放文件
		byte buffer[]=new byte[2048];
		int len=0;
		//循环读取文件
		while((len=fis.read(buffer))!=-1){
			//向输出流写入文件
			fos.write(buffer, 0, len);
		}
		//关闭文件流
		fos.close();
		fis.close();
		System.out.println("复制完成");
		long end = System.currentTimeMillis();
		System.out.println("程序运行时间:"+(end-start)+"ms");
//		System.out.println("不使用文件缓冲数据流");
//		//程序开始时间
//		long start = System.currentTimeMillis();
//		//创建文件输入输出流对象
//		InputStream fis=new FileInputStream(filepath);
//		OutputStream fos=new FileOutputStream(fileOut);
//		//创建byte数组存放文件
//		byte buffer[]=new byte[2048];
//		int len=0;
//		//循环读取文件
//		while ((len=fis.read(buffer))!=-1) {
//			//向输出流写入文件
//			fos.write(buffer, 0, len);
//		}
//		//关闭文件流
//		fos.close();
//		fis.close();
//		System.out.println("复制完成");
//		long end = System.currentTimeMillis();
//		System.out.println("程序运行时间:"+(end-start)+"ms");	
	}
}

4 字符流

4.1 FileReader 字符输入流

以字符char为单位进行的流,适合操作文本数据

  • Reader 字符输入流的父类

  • Writer 字符输出流的父类

FileReader 文件读取器

创建方法:

FileReader(File file) 
创建一个新的 FileReader ,给出 File读取。  
FileReader(FileDescriptor fd) 
创建一个新的 FileReader ,给定 FileDescriptor读取。  
FileReader(String fileName) 
创建一个新的 FileReader ,给定要读取的文件的名称。 

主要方法

  • public void close() :关闭此流并释放与此流相关联的任何系统资源。

  • public int read(): 从输入流读取一个字符。

  • public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。

代码演示:

要求:将文本文件中的内容读取到控制台中显示。

package test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class RederTest {
	public static void main(String[] args) throws IOException {
    //要求:将文本文件中的内容读取到控制台中显示。
		//1,创建字符输入流
		FileReader fReader=null;
		
		try {
			File f1=new File("d:/ccc.txt");
			fReader=new FileReader(f1);
			int len=0;
			while ((len=fReader.read())!=-1) {
				  System.out.print((char)len);
			}
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally {
            try {
//                关闭流
                if (fReader != null) {
                	fReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
	}
}

4.2 FileWriter 字符输出流

java.io.FileWriter抽象类是表示用于写出字符流的超类。构造时使用系统默认的字符编码和默认字节缓冲区。

  • void write(int c) 写入单个字符。

  • void write(char[] cbuf)写入字符数组。

  • abstract void write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。

  • void write(String str)写入字符串。

  • void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。

  • void flush()刷新该流的缓冲。

  • void close() 关闭此流,但要先刷新它。

代码演示:

要求:将下面的一段话输入到D盘的文本文件中。

昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否,知否?应是绿肥红瘦。

package test;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class WriterTest {

	public static void main(String[] args) throws IOException {
	   //要求:将下面的一段话输入到D盘的文本文件中。
       //昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否,知否?应是绿肥红瘦。`
       //创建文件输出流
		FileWriter writer=null;
		File f1=new File("D:/eee.txt");
		//创建文件
		if (!f1.exists()) {
			f1.createNewFile();
		}
		//构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。  
		writer=new FileWriter(f1, true);
		writer.write("昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否,知否?应是绿肥红瘦。");
		writer.close();
	}
}

5 对象流

5.1.1概述

Java 提供了一种对象序列化的机制。用来将某个对象保存到磁盘上或者-在网络上传输。可以理解为将内存中的对象进行持久化保存下来。反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

JAVA中是通过对象流来实现对象的序列化跟反序列化的,对象流也是一种包装流。

5.1.2 序列化

java.io.ObjectOutputStream 类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。

被序列化的对象需要实现java.io.Serializable 接口。Serializable 是一个标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛出NotSerializableException

如果有不需要序列化的字段使用transient关键字修饰即可。

代码演示:

package pojo;

import java.io.Serializable;
//实体类
public class Person implements Serializable{
    //  序列化版本号,必须保证序列化跟反序列化的版本号一致
    private static final long seriaVersionUID=-1213754818242979380L;
    public String name;
    //设置age字段为transient,表示此字段不需要序列化
    public transient int age=1;
    public String sex;
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", sex=" + sex + ", getClass()=" + getClass() + ", hashCode()="
				+ hashCode() + ", toString()=" + super.toString() + "]";
	}
    
}

序列化代码演示

package test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import pojo.Person;

public class Demo12Serializable {

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		// TODO Auto-generated method stub
		//序列化
         //saveObject();
		//反序列化
		readObject();
	}
	//序列化
	public static void saveObject() throws IOException{
		//准备序列化的对象
		Person person=new Person();
		person.name = "张三";
        person.age = 18 ;
        person.sex = "男";
        //准备数据流
        FileOutputStream fos=new FileOutputStream("d:/eee.txt");
        ObjectOutputStream out=new ObjectOutputStream(fos);
        //序列化对象
        out.writeObject(person);
//      关闭流
        out.close();
        fos.close();
	}
	//反序列化
	public static void readObject() throws IOException, ClassNotFoundException{
		//准备对象流
		FileInputStream fis=new FileInputStream("d:/eee.txt");
		ObjectInputStream in=new ObjectInputStream(fis);
		Person person = (Person) in.readObject();
		System.out.println(person);
		 //关闭流
        in.close();
        fis.close();
	}

}

重点

序列化的重点在于序列化跟反序列化的的版本号要一致,通常可以设置成固定值或者有IDE自动生成,这个版本号定义在实体类的属性private static final long serialVersionUID。如果版本号信息不一致会抛出InvalidClassException异常。1

5.3 properties属性集

5.3.1 概述

前面学习过集合,集合家族中有个成员java.util.Properties ,它继承于HashtableProperties是使用键值结构存储数据的,但它最大的特点是具有持久化功能。

5.3.2 常用API

  • public Properties() :创建一个空的属性列表。

  • public Object setProperty(String key, String value) : 保存一对属性。

  • public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。

  • public Set<String> stringPropertyNames() :所有键的名称的集合。

  • public void load(InputStream inStream): 从字节输入流中读取键值对数据。

  • public void store(OutputStream out,String comments):从字节输入流中存储键值对数据。

代码演示

要求:往Properties中存储数据,并通过流写出到本地文件中。

package test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.util.Properties;
public class TestProperties {
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
      //创建对应属性文件
		File file=new File("D:/yhr.properties");
		if (!file.exists()) {
			file.createNewFile();
		}
		//创建properties对象,存储文件
		Properties p=new Properties();
		p.setProperty("name", "易荣辉");
		p.setProperty("age", "12");
		p.setProperty("sex", "男");
		//通过OutputStreamWriter包装一层流,可以解决乱码问题
		FileOutputStream fos=new FileOutputStream(file);
		OutputStreamWriter osw=new OutputStreamWriter(fos,"utf-8");
		p.store(osw, "");
		osw.close();
		fos.close();
	}

}

代码演示

要求:将Properties中的数据读取到程序中,遍历所有的数据。

package test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;
import java.util.Set;

public class Demo14Properties {

	public static void main(String[] args) throws IOException {
      //创建对应的属性文件
		File file=new File("D:/yhr.properties");
		//建立到文件直接的流
		FileInputStream fis=new FileInputStream(file);
		InputStreamReader read=new InputStreamReader(fis);
		//通过流把配置文件中的数据加载到Propertis对象中
		Properties properties=new Properties();
		properties.load(read);
		//关闭流
		read.close();
		fis.close();
         //遍历
		Set<String> keys = properties.stringPropertyNames();
		for (String string : keys) {
			System.out.println(string+" = "+properties.getProperty(string));
		}
	}

}

tips:

  • properties文件中键值对之间的分割可以使用= :跟空格。

  • 由于properties继承Hashtable,所有还可以通过枚举器来遍历。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值