前置知识:

序列化和反序列化

  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. test_4 实现一个统计函数运行时间

    1.datetime显示当前时间 import datetimeimport timedef func(): t = datetime.datetime.now() print t print &qu ...

  2. 输出前 n 个Fibonacci数

    本题要求编写程序,输出菲波那契(Fibonacci)数列的前N项,每行输出5个,题目保证输出结果在长整型范围内.Fibonacci数列就是满足任一项数字是前两项的和(最开始两项均定义为1)的数列,例如 ...

  3. [转载]Win10蓝牙设备删除后无法连接解决办法

    转自 https://blog.csdn.net/Tokeyman/article/details/86268005 现象 一般情况下,当操作系统无法与蓝牙设备,比如鼠标键盘等出现无法连接的情况,通过 ...

  4. 【记录一个问题】android opencl c++: 不要Context, CommandQueue类的赋值函数

    一开始代码中这样写了: cl::Context ctx = cl::Context(CL_DEVICE_TYPE_GPU, NULL); cl::CommandQueue queue= cl::Com ...

  5. CMake语法—普通变量与子目录(Normal Variable And Subdirectory)

    目录 CMake语法-普通变量与子目录(Normal Variable And Subdirectory) 1 CMake普通变量与子目录示例 1.1 代码目录结构 1.2 父目录CMakeLists ...

  6. Rust 使用 dotenv 来设置环境变量

    在项目中,我们通常需要设置一些环境变量,用来保存一些凭证或其它数据,这时我们可以使用 dotenv 这个 crate. 首先在项目中添加 dotenv 这个依赖: 例如在下面这个项目中,需要设置数据库 ...

  7. gin框架中全局跨域请求处理设置

    跨域访问的问题 OPTIONS请求 全局跨域访问中间件 // 跨域访问:cross origin resource share func Cors() gin.HandlerFunc { return ...

  8. golang中浮点型底层存储原理和decimal使用方法

    var price float32 = 39.29 float64和float32类似,只是用于表示各部分的位数不同而已,其中:sign=1位,exponent=11位,fraction=52位,也就 ...

  9. maven一键构造及常用命令

    maven一键构造及常用命令 1.maven的一键构建 我们不再使用本地的Tomcat对项目进行编译.测试.运行.打包.安装.部署等一系列过程,而是使用maven自身集成的Tomcat插件来完成这些操 ...

  10. 命令行传参是否只能针对main方法

    先上结论 命令行传参只能针对main方法而言,而且格式严格 这里在原有主类test基础上创建了另一个类,名字为testCMD,但里面创建的方法并不是main方法,在cmd内编译后进行命令行传参,结果如 ...