前置知识:

序列化和反序列化

  1.序列化就是在保存数据时, 保存数据的值和数据类型
  2.反序列化就是在恢复数据时, 恢复数据的值和数据类型
  3.需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该
     类必须实现如下两个接口之一:
     Serializable //这是一个标记接口,没有方法
     Externalizable //该接口有方法需要实现,因此我们一般实现上面的Serializable接口

IO流的三种分类

  第一种:输入流和输出流
    按照流的流向来分,可以分为输入流和输出流。输入,输出都是从程序运行所在内存的角度来划分的。
    输入流:只能从中读取数据,而不能向其写入数据,由InputStream和Reader作为基类。
    输出流:只能向其写入数据,而不能从中读取数据。由OutputStream和Writer作为基类

  第二种:字节流和字符流
    字节流和字符流的用法几乎完全一样,区别在于字节流和字符流所操作的数据单元不同。
    字节流操作的数据单元是8位字节,由InputStream和OutputStream作为基类。
    字符流操作的数据单元是16位的字符,由Reader和Writer作为基类

  第三种:节点流和处理流
    按照流的角色来分,可以分为节点流和处理流。
    节点流:可以从向一个特定的IO设备(如磁盘、网络)读/写数据的流。也被称为低级流。
    处理流:用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能。也称为高级流

节点流和处理流的区别和联系
   1.节点流是底层流/低级流,直接跟数据源相接。
   2.处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
   3.处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连[模拟修饰器设计模式]
    

   处理流的功能主要体现在以下两个方面:
   1.性能的提高:主要以增加缓冲的方式来提高输入输出的效率。
   2.操作的便捷:处理流可能提供了- -系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便

   常见的处理流BufferedReader和BufferedWriter

   在关闭处理流时,只关闭外层流即可

一、字节流

字节流通常用来处理二进制文件,视频,音频,图片  

1、inputStream

  1.1、FileInputStream

/**
* FileInputStream使用(文件-->程序)
*/
public class FileInputStream_ {
public static void main(String[] args) {
// readFile01();
readFile02();
} //单个字节的读取,效率比较低
public static void readFile01(){
String filePath="D://a.txt";
int readData=0;
FileInputStream fileInputStream=null;
try {
//创建FileInputStream对象,用于读取 文件
fileInputStream = new FileInputStream(filePath);
//一个字节一个字节的读,读取的数据存储在readData里,如果返回-1,则代表读取完毕
while ((readData = fileInputStream.read())!=-1){
System.out.print((char) readData);//转成char输出
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭文件流释放资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} public static void readFile02(){
String filePath="D://a.txt";
int readLen=0;
FileInputStream fileInputStream=null;
//添加一个Byte容量设置为10数组
byte[] bytes = new byte[9];
try {
//创建FileInputStream对象,用于读取文件
fileInputStream = new FileInputStream(filePath);
//从该输入流读取最多10个字节的数据到字节数组。
//如果返回-1,则代表读取完毕
//如果读取正常返回实际读取的字节数
while ((readLen=fileInputStream.read(bytes))!=-1){
System.out.print(new String(bytes,0,readLen));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭文件流释放资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

  1.2、ObjectInputStream(对象反序列化)

    注意先进行 ObjectOutputStream 序列化到 D:\a.dat 文件中 然后才进行的反序列化

public class ObjectInputStream_ {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//指定反序列化的文件
String filePath="D:\\a.dat"; ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filePath)); //读取
//反序列的顺序需要和保存的数据的顺序一致,否则会出现异常
System.out.println(objectInputStream.readInt());
System.out.println(objectInputStream.readBoolean());
System.out.println(objectInputStream.readChar());
System.out.println(objectInputStream.readDouble());
System.out.println(objectInputStream.readUTF());
Object dog = objectInputStream.readObject();
System.out.println("运行类型:"+dog.getClass());
System.out.println("dog信息:"+dog);//底层 Object-->Dog //关闭外层流即可
objectInputStream.close();
}
}

可以看到输出:

2、OutputStream

  2.1、FileOutputStream

public class FileOutputStream_ {
public static void main(String[] args) {
writeFile();
}
/**
* 使用FileOutputStream将数据写入文件中
* 如果数据不存在,则自动创建该文件
*/
public static void writeFile(){
String filePath="D:\\a.txt";
FileOutputStream fileOutputStream=null;
try {
//得到FileOutputStream对象
//1、这种创建方式,写入的内容是覆盖原来的文件中的内容
//2、在构造器中添加 true 为追加填写
fileOutputStream = new FileOutputStream(filePath,true); //写入一个字节
// fileOutputStream.write('a'); fileOutputStream.write(97); //写入字符串 str.getBytes()字符串转为字节数组
String str="hollow";
//fileOutputStream.write(str.getBytes()); //也可以指定字节数组中的起始位置,末尾位置
fileOutputStream.write(str.getBytes(),0,str.length());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

  2.2、ObjectOutputStream(对象序列化)  

/**
* ObjectOutputStream的使用,完成数据的序列化
*/
public class ObjectOutputStream_ {
public static void main(String[] args) throws Exception {
//序列化后,保存的格式,不是纯文本,而是按照他的格式来保存
String filePath = "D:\\a.dat";
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath)); //序列化数据到 D:\a.bat
objectOutputStream.write(100);//int-->Integer(实现了Serializable)
objectOutputStream.writeBoolean(true);//boolean-->Boolean(实现了Serializable)
objectOutputStream.writeChar('a');//chat-->Character(实现了Serializable)
objectOutputStream.writeDouble(1.1);//double-->Double(实现了Serializable)
objectOutputStream.writeUTF("阿龙学习");//String //保存一个对象
objectOutputStream.writeObject(new Dog("旺财",5));
objectOutputStream.close();
System.out.println("序列化数据保存完毕");
}
}
//lombok插件
@Data
@AllArgsConstructor
@NoArgsConstructor
//要实现Serializable接口才能够进行序列化
class Dog implements Serializable {
private String name;
private int age;
}

  2.3、PrintStream(字节打印流)  

/**
* PrintStream字节打印流
*/
public class PrintStream_ {
public static void main(String[] args) throws IOException {
// System.out 就是 PrintStream
PrintStream out = System.out;
//在默认情况下,默认打印的是标准输出(即 显示器)
out.println("你好");
//因为底层使用的是write,所以可以直接调用write进行打印/输出
out.write("hello,你好!".getBytes(StandardCharsets.UTF_8));
//关闭流。
out.close();
//我们可以修改打印输出流的位置/设备
//修改成"D:\\a.txt"
//这句话将会输出到D:\a.txt
System.setOut(new PrintStream("D:\\a.txt"));
System.out.println("这句话将会输出到D:\\a.txt");
}
}

二、字符流

  通常用来处理文本文件,更高效。

1、Reader

  1.1、FileReader 

public class FileReader_ {
public static void main(String[] args) {
String filePath="d:\\a.txt";
FileReader fileReader=null;
int data= 0;
char[] chars = new char[10];
//1、创建FileReader对象
try {
fileReader = new FileReader(filePath);
//循环读取,使用read(chars),返回的是实际读取到的字符数
//如果返回-1则表示读到文件结尾
while ((data = fileReader.read(chars))!=-1){
System.out.print(new String(chars,0,data));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

  1.2、BufferedReader

    BufferedReader类中,有属性Reader,即可以封装一个节点流,该节点流可以是任意的,只要是Reader子类 (BufferedWriter也是一样的操作)

    

public class BufferedReader_ {
public static void main(String[] args) throws Exception { //异常也可以try catch
String filePath = "D:\\a.txt"; //创建bufferedReader
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
//读取
String line;//按行读取,效率高
//1.bufferedReader.readLine() 按行读取文件
//2.当返回为空时,表示文件读取完毕。
while ((line = bufferedReader.readLine())!=null){
System.out.println(line);
}
//关闭流,只需要关闭外层的流,即bufferedReader,因为底层会自动的去关闭节点流 FileReader
bufferedReader.close();
}
}

  1.3、InputStreamReader(转换流,并可以指定编码格式读取)

/**
* InputStreamReader 转换流解决中文乱码问题
* 将字节流 FileInputStream 转换成字符流 InputStreamReader, 指定编码 gbk/utf-8
*/
public class InputStreamReader_ {
public static void main(String[] args) throws IOException {
String filePath = "D:\\a.txt";
//把 new FileInputStream(filePath) 转成 InputStreamReader 同时指定了编码 utf-8
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8);
//把 InputStreamReader 传入 BufferedReader
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String readLine;
while(( readLine = bufferedReader.readLine())!=null){
System.out.println(readLine);
}
bufferedReader.close();
}
}

2、Writer

  2.1、FileWriter

注意:FileWriter使用后,必须要关闭(close)或刷新(flush)流, 否则写入不到指定的文件!

public class FileWriter_ {
public static void main(String[] args) {
String filePath="D:\\a.txt";
FileWriter fileWriter=null;
String str="哈哈哈哈哈哈哈哈哈";
try {
fileWriter = new FileWriter(filePath,true);//true为追加,不写则覆盖
//fileWriter.write(str);
fileWriter.write(str,0,2);//指定str的某一部分
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

  2.2、BufferedWriter

public class BufferedWriter_ {
public static void main(String[] args) throws IOException {
String filePath="D:\\a.txt";
//创建BufferedWriter
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));//追加要在节点流中进行设置
bufferedWriter.write("红红火火恍恍惚惚红红火火恍恍惚惚吼吼吼1");
//插入一个换行
bufferedWriter.newLine();
bufferedWriter.write("红红火火恍恍惚惚红红火火恍恍惚惚吼吼吼2");
//插入一个换行
bufferedWriter.newLine();
bufferedWriter.write("红红火火恍恍惚惚红红火火恍恍惚惚吼吼吼3"); //关闭外层流即可
bufferedWriter.close();
} }

  2.3、OutputStreamWriter(转换流,并可以指定编码格式写入)

/**
* 将字节流FileOutputStream包装成(转换成)字符流OutputStreamWriter,
* 对文件进行写入(按照gbk格式,可以指定其他,比如utf-8/utf8)
*/
public class InputStreamWriter_ {
public static void main(String[] args) throws IOException {//异常直接进行的抛出,也可以try catch
String filePath = "D:\\a.txt";
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(filePath), "gbk");
outputStreamWriter.write("gbk格式的编码");
//关闭流
outputStreamWriter.close();
}
}

  2.4、PrintWriter(字符打印流)

public class PrintWriter_ {
public static void main(String[] args) throws IOException {
//创建PrintWriter对象
PrintWriter printWriter = new PrintWriter(new FileWriter("D:\\a.txt"));
//将会打印到 D:\a.txt
printWriter.println("哈喽你好 ");
printWriter.close(); //flush + 关闭流
}
}

三、Properties类 

  load:加载配置文件的键值对到Properties对象
  list:将数据显示到指定设备
  getProperty(key):根据键获取值
  setProperty(key,value):设置键值对到Properties对象
  store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果
  含有中文,会存储为unicode码

  1、Properties读取数据   

public class Properties_read {
public static void main(String[] args) throws IOException {
//使用Properties读取ycl.properties文件
Properties properties = new Properties();
//加载指定的配置文件
properties.load(new FileReader("src/main/resources/ycl.properties"));
//键值对显示到控制台
properties.list(System.out);
//根据key 获取对应的值
String id = properties.getProperty("id");
System.out.println("id是:"+id);
}
}

  2、Properties写入数据

public class Properties_writer {
public static void main(String[] args) throws IOException {
//使用Properties类, 创建配置文件,修改配置文件内容
Properties properties = new Properties(); //设置内容
     //如果该文件没有对应的key,就是创建
     //如果该文件有对应的key,就是修改
properties.setProperty("charset","utf-8");
properties.setProperty("username","小刚");//中文保存的是unicode码
properties.setProperty("pwd","123567894"); //将k-v 存储至文件
properties.store(new FileOutputStream("D:\\a.data"),null);
System.out.println("保存成功");
}
}

  

四、copy练习

  1、字节流copy练习

public class FileCopy {
public static void main(String[] args) {
copy();
}
public static void copy(){
String resourcePath="D:\\壁纸\\1.jpg";
String targetPath="D:\\壁纸\\3.jpg";
FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;
int readLen=0;
try {
fileInputStream = new FileInputStream(resourcePath);
fileOutputStream=new FileOutputStream(targetPath);
//定义一个数组提高效率
byte[] bytes = new byte[1024];
while ((readLen=fileInputStream.read(bytes))!=-1){
//边读边写
fileOutputStream.write(bytes,0,readLen);//必须用这个参数,否则出现文件损失
}
System.out.println("copy完成");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileInputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

  2、缓冲字符流copy文本练习

    BufferedReader和BufferedWriter 是按照字符操作的,不要去操作二进制文件(声音、视频、doc、pdf、图片等等),拷贝后的文件可能会造成文件损坏

public class Buffered_copy {
public static void main(String[] args) {
//源文件路径
String resourcePath = "D:\\a.txt";
//目标文件的路径
String targetPath = "D:\\b.txt";
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
//创建bufferedReader、bufferedWriter
bufferedReader = new BufferedReader(new FileReader(resourcePath));
bufferedWriter = new BufferedWriter(new FileWriter(targetPath,true));//true表示追加写入
String line;
//readLine() 读取一行内容,但是没有换行
while ((line = bufferedReader.readLine()) != null) {
//每读取一行就写入
bufferedWriter.write(line);
//插入换行
bufferedWriter.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//关闭流
if (bufferedReader!=null){
bufferedReader.close();
}
if (bufferedWriter!=null){
bufferedWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

  3、缓冲字节流copy二进制文件(copy文本文件一样可以) 

/**
* BufferedInputStream、BufferedOutputStream的使用
*/
public class Buffered_copy02 {
public static void main(String[] args) {
String resourcePath = "D:\\壁纸\\2.jpg";
String targetPath = "D:\\壁纸\\4.jpg";
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
//创建对象
bufferedInputStream = new BufferedInputStream(new FileInputStream(resourcePath));
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(targetPath));
int readLen;
byte[] buf = new byte[1024];
//返回读取到的长度,当返回-1时,就表示文件读取完毕
while ((readLen = bufferedInputStream.read(buf))!=-1){
bufferedOutputStream.write(buf,0,readLen);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//关闭外层处理流即可,底层会自动关闭节点流
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (bufferedOutputStream!=null){
bufferedOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

   

io流复习+代码演示的更多相关文章

  1. JavaSE复习_11 IO流复习

    △FileReader是使用默认码表读取文件, 如果需要使用指定码表读取, 那么可以使用InputStreamReader(字节流,编码表)    FileWriter是使用默认码表写出文件, 如果需 ...

  2. Java基础学习笔记二十 IO流

    转换流 在学习字符流(FileReader.FileWriter)的时候,其中说如果需要指定编码和缓冲区大小时,可以在字节流的基础上,构造一个InputStreamReader或者OutputStre ...

  3. java的IO流初探

    DEMO代码: /* * 文件IO流的简单演示 */ package com.IO; import java.io.*; public class Demo_IO_1 { /** * @param a ...

  4. IO流的Properties集合,序列化流与反序列化流,打印流及commons-IO

    内容介绍 Properties集合 序列化流与反序列化流 打印流 commons-IO Properties类 Properties类介绍 Properties 类表示了一个持久的属性集.Proper ...

  5. Java:IO流(二)——InputStream/OutputStream具体用法:FileXXXStream、ByteArrayXXXStream

    1.说明 InputStream和OutputStream是Java标准库中最基本的IO流,它们都位于java.io包中,该包提供了所有同步IO的功能. 2.模块:java.io.InputStrea ...

  6. JavaSE复习(四)File类与IO流

    File类 构造方法 public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例. public File(String parent ...

  7. IO流----操作文件的9种方法代码实现

    IO流----操作文件的9种方法代码实现: 1:使用字节流读写数据: 四种方式: method1:          每次读写一个字节,边读边写: /* * 复制文本文件. * * 数据源:从哪里来 ...

  8. java IO流 对文件操作的代码集合

    Io流 按照分类 有两种分类 流向方向: 有输入流和输出流 按照操作类型有:字节流和字符流 按照流向方向 字节流的一些操作 //读文件 FileInputStream fis = new FileIn ...

  9. IO流详解及测试代码

    IO流 (1)IO用于在设备间进行数据传输的操作 (2)分类:    A:流向       输入流 读取数据      输出流 写出数据   B:数据类型     字节流         字节输入流  ...

随机推荐

  1. Go 中实现用户的每日限额(比如一天只能领三次福利)

    如果你写一个 bug 管理系统,用了这个 PeriodLimit 你就可以限制每个测试人员每天只能给你提一个 bug.工作是不是就轻松很多了? 如今微服务架构大行其道本质原因是因为要降低系统的整体复杂 ...

  2. Solon 开发,二、注入或手动获取Bean

    Solon 开发 一.注入或手动获取配置 二.注入或手动获取Bean 三.构建一个Bean的三种方式 四.Bean 扫描的三种方式 五.切面与环绕拦截 六.提取Bean的函数进行定制开发 七.自定义注 ...

  3. 从带Per-Building数据的KML/COLLADA中创建3D Tiles

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 许多Cesium的使用者经常需要将整个城市的数十万个三维建筑可视 ...

  4. 539. Minimum Time Difference

    Given a list of 24-hour clock time points in "Hour:Minutes" format, find the minimum minut ...

  5. php的CI框架相关数据库操作

    在使用之前首先应该配置数据库的参数,详见文件application/config/database.php,里面包含主机名,登陆用户名,登录密码,数据库名,编码信息等. 在配置成功后,可以简单的调用: ...

  6. golang中的go get命令

    ### 下载指定版本 go get k8s.io/klog@v1.0.0 go get 命令可以借助代码管理工具通过远程拉取或更新代码包及其依赖包,并自动完成编译和安装. 这个命令在内部实际上分成了两 ...

  7. golang中字符串的底层实现原理和常见功能

    1. 字符串的底层实现原理 package main import ( "fmt" "strconv" "unicode/utf8" ) f ...

  8. 关于Linux安装中NAT模式和桥接模式的区别详解(转载)

    1.一般我们在创建一个Linux虚拟机时候,会面临三个网络配置选择: 桥接模式.nat模式.host-only模式(主机模式,这个模式用得少,就不介绍了) 2.NAT模式: 所谓nat模式,就是虚拟系 ...

  9. 导入 static 修饰的包

    一 static关键字,可以修饰变量  方法  代码块 ,  静态内部类.  还可以用来修饰 需要导入的包 准备工作 package zhouxufeng; public class Text1 { ...

  10. JavaScript之递归查找所有父节点

    ......data: () => ({ // 数据 dt: [{ id: '1', children: [ { id: '1-1', children: [ { id: '1-1-1', ch ...