当前位置: 首页 > article >正文

JavaSE基本知识补充 -IO流

目录

1.IO概述

1.1流的分类

2.字符流

2.2案例-输入

文件的追加

换行

Writer的五种写入的方法

2.3案例-输出

Reader的读取方式

2.4复制

2.5 BufferedWriter

2.6 BufferedReader

3.字节流

1.输出OutputStream

输出单个字符

输出字节数组

追加

2.输入InputStream

输入单个符

输入字节数组

输入字节到数组的某一部分

3.复制

复制图像

4.复制-BufferedInputStream和BufferedOutputStream

总结:

4.相互转化

5.properties

实际应用场景:

6.序列化流

7.random


1.IO概述

        IO(Input/Output):输入和输出,指的是某个设备或环境进行数据的输入或者输出。例如:键盘的输入,再比如显示器就是输出设备,输出图像。

        对于java来说输入输出问题,java将它抽象成流对象来解决。

        以游戏程序为中心读取文件就是输入,写入文件是输出。

     所有的文件的传递,都变成流。

        从外部读取文件叫做输入。reader

        把游戏记录保存到外部设备(目标文件)叫做输出。writer

1.1流的分类

IO流在java中从输入输出角度分类:

        1.输入流

        2.输出流

IO流在java中从数据的角度来分类:

        1.字符流

                文本,我们能读的懂的都可以认为是字符流。比如:文章,java文件等等

        2.字节流

                二进制的数据,这种数据一般用文本打开我们读不懂。比如,图片文件,mp3文件,等等。能看懂图片的样式,但是不懂怎么形成的图片

2.字符流

        文本,我们能读的懂的都可以认为是字符流。比如:文章,java文件等等

字符流

        输出流

输入流

字符流的类的命名的规则:

        如果是输出流就以Writer结尾

        如果是输入流就以Reader结尾

2.2案例-输入

使用字符流向一个文件输入helloworld。

分析:

        步骤:      

                1.创建文件

                 2.创建输出流对象

                 3.把流指向指定的文件

                 4.释放资源

//创建一个文件
File file = new File("test.txt");
Writer writer = null;

try {
    //IO流是需要关闭的,如果不这样设计就会不能关闭资源
    writer = new FileWriter(file);
    writer.write("HelloWorld");

} catch (IOException e) {
    e.printStackTrace();
}finally {
    //判断writer不是空防止空指针异常
    if(writer != null) {
        try {
            //在关闭前会做flush的事情
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在IO流里一定会用try-catch

finally一定会执行,无论有没有异常

如果有异常,捕获异常。

流,就要关闭流。

文件的追加

Writer writer = null;

try {
    //IO流是需要关闭的,如果不这样设计就会不能关闭资源
    //writer = new FileWriter("test.txt", true);
    writer = new FileWriter("test.txt", true);
    writer.write("zhangsan");
} catch (IOException e) {
    e.printStackTrace();
}finally {
    //判断writer不是空防止空指针异常
    if(writer != null) {
        try {
            //在关闭前会做flush的事情
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

追加,不然会覆盖。

换行

输出换行

                把文本写入文件中\n代表换行

                问题是不同的环境下换行的方式也不一样

                Windows: \r\n

                Linux:\n

                Mac:\r

//创建一个文件
File file = new File("test.txt");
Writer writer = null;

try {
    //IO流是需要关闭的,如果不这样设计就会不能关闭资源
    writer = new FileWriter(file);
    for (int i = 0; i < 100; i++) {
        writer.write("HelloWorld\r\n");
        //每次写入10个helloworld的时候做一次flush
        if(i % 10 == 0){
            writer.flush();
        }
    }

} catch (IOException e) {
    e.printStackTrace();
}finally {
    //判断writer不是空防止空指针异常
    if(writer != null) {
        try {
            //在关闭前会做flush的事情
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

        flush:流可以理解为一个管道,如果一直开着,最后关闭管道里还会有数据。每十个做一次把数据推出去。刷新缓冲

不是追加,覆盖

Writer的五种写入的方法

1.写入字符数组

char[] c = {'a','b','p','b','p'};
writer.write(c);

2.写入字符数组的某一部分

char[] c = {'a','b','p','b','p'};
//            writer.write(c);
            //把数组中的一部分写入文件
            writer.write(c, 2, 2);

从下标为2开始,长度为2

3.写入单个字符

writer.write(97);

4.写入字符串

writer.write("nihao");

5.写入字符串的某一部分

writer.write("helloworld", 2, 2);


2.3案例-输出

分析:

        步骤:      

                 1.创建文件

                  2.创建输出流对象

                  3.把流指向指定的文件

                  4.释放资源

File file = new File("c.txt");

Reader reader = null;

try {
    //创建出入流对象FileReader
    reader = new FileReader(file);
    //读取数据, 读取的字符被转换成了ascii
    int c = -1;
    //单个字符的读取性能低
    while((c = reader.read()) != -1){
        System.out.print((char)c);
    }


} catch (Exception e) {
    e.printStackTrace();
} finally {
    //关闭资源
    if(reader != null){
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

如果读取到的是-1后面就没有字符了

Reader的读取方式

1.将字符读入数组

File file = new File("c.txt");

Reader reader = null;

try {
    //创建出入流对象FileReader
    reader = new FileReader(file);
    //定义一个数组   字符 char
    char[] cs = new char[5];
    //向字符数组中填数据
    int len = reader.read(cs);
    System.out.println("读取的长度:"+len+"    读取的内容:"+ Arrays.toString(cs));

    //本次读取的字符的长度,如果要是文件中没有数据了,读取到的是-1
    len = reader.read(cs);
    System.out.println("第二次读取的长度:"+len+"    读取的内容:"+ Arrays.toString(cs));

    len = reader.read(cs);
    System.out.println("第三次读取的长度:"+len+"    读取的内容:"+ Arrays.toString(cs));


} catch (Exception e) {
    e.printStackTrace();
} finally {
    //关闭资源
    if(reader != null){
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

2.将字符读入数组的某一部分

File file = new File("c.txt");

Reader reader = null;

try {
    //创建出入流对象FileReader
    reader = new FileReader(file);
    //定义一个数组
    char[] cs = new char[5];

    int read = reader.read(cs, 2, 3);
    System.out.println(Arrays.toString(cs));

} catch (Exception e) {
    e.printStackTrace();
} finally {
    //关闭资源
    if(reader != null){
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

3.读取单个字符

reader = new FileReader(file);
System.out.println((char)reader.read());

reader = new FileReader(file);
for (int i = 0; i <5 ; i++) {
    System.out.println((char)reader.read());
}

4.读入字符串

reader = new FileReader(file);
StringBuilder s=new StringBuilder();
int c = -1;
//单个字符的读取性能低
while((c = reader.read()) != -1){
    s.append((char)c);
}
System.out.println(s);

读到-1表示没有了。

2.4复制

        1.创建输入输出流对象

        2.创建要拷贝的文件对象和要到达的文件对象

        3.输入流读取文件

        4.输出流写入

        5.关闭输入输出流

//1.创建需要的输出输入流对象
Reader reader=null;
Writer writer=null;
//2.创建要拷贝的文件file对象  以及要到达的新文件
File file=new File("test3.txt");
File file1=new File("test5.txt");
//3.利用字符输入流读取文件test3.txt
try {
    //读取文件test3.txt
    reader = new FileReader(file);
    //创建字符输出流对象
    writer=new FileWriter(file1);
    //创建一个字符数组  减少读取的io次数
    char [] cs = new char[1024];
    //定义边界值
    int len = -1;
    //利用循环  找到边界值  读取文件
    while((len = reader.read(cs)) != -1){
        //此时读到的内容要写进新的文件通过字符输出流
        //把输入流读取到的数据写入字符输出流
        writer.write(cs, 0, len);
    }
    //为了解决传递压迫性能问题  使用flush操作
    writer.flush();
    //改成大异常 更方便
} catch (Exception e) {
    e.printStackTrace();
}finally{
    //最后把两个流关闭
    try {
        if(writer != null){
            writer.close();
        }
        if(reader != null){
            reader.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

2.5 BufferedWriter

        .newLine()一行一行输入的

BufferedWriter (Java 2 Platform SE 6)

        可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

        该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,

//创建高效缓冲字符输出流
BufferedWriter writer = null;

try {
    writer = new BufferedWriter(new FileWriter("IOTest.java"));
    //写一行数据
    writer.write("helloworld");
    //换行
    writer.newLine();
    writer.write("helloworld");
    writer.flush();

} catch (IOException e) {
    e.printStackTrace();
} finally {

    //资源关闭
    if(writer != null){
        try {
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.6 BufferedReader

BufferedReader reader = null;

try {
    //创建一个高效缓存字符输入流对象
    reader = new BufferedReader(new FileReader("CopyDemo1.java"));
    String line = null;
    while((line = reader.readLine()) != null){
        //打印一行
        System.out.println(line);
    }

} catch (Exception e) {
    e.printStackTrace();
}finally {
    //关闭外层的对象的时候,内存的资源会自动的背关闭
    if(reader != null){
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Java。io下的outputStream


3.字节流

        二进制的数据,这种数据一般用文本打开我们读不懂。比如,图片文件,mp3文件,等等。

        能看懂图片的样式,但是不懂怎么形成的图片

1.输出OutputStream

输出单个字符

//创建字节输出流
OutputStream out = null;

try {
    out = new FileOutputStream(new File("a.txt"));
    //字节流不需要flush
    out.write(98);
} catch (Exception e) {
    e.printStackTrace();
} finally {
    try {
        if(out != null){
            out.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

输出字节数组

//创建一个字节的数组
byte[] bs = {97, 99, 103, 111};
out = new FileOutputStream(new File("a.txt"));
out.write(bs);

追加

//创建一个字节的数组
byte[] bs = {97, 99, 103, 111};
//out = new FileOutputStream(new File("a.txt"));
out = new FileOutputStream("a.txt", true);
out.write(bs, 1, 2);

2.输入InputStream

创建输入流对象

创建输入流文件对象

关闭

输入单个符

//创建字节输入流的对象
InputStream in = null;

try {
    in = new FileInputStream("a.txt");
    int r = in.read();
    System.out.println((char)r);


} catch (Exception e) {
    e.printStackTrace();
} finally {
    if(in != null){
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

输入字节数组

//创建字符输入流的对象
InputStream in = null;

try {
    byte[] bs = new byte[6];
    in = new FileInputStream("a.txt");
    int len = in.read(bs);
    System.out.println("读取了字节数:"+len+"    读取的内容:"+ new String(bs, 0, len ));


    len = in.read(bs);
    System.out.println("读取了字节数:"+len+"    读取的内容:"+  new String(bs, 0, len ));


    len = in.read(bs);
    System.out.println("读取了字节数:"+len);

//创建一个字节的数组
byte[] bs = new byte[1024];
//创建字符输入流的对象,如果有中文有可能出现乱码
in = new FileInputStream("a.txt");
//定义读取到的长度的标识
int len = -1;
while((len = in.read(bs)) != -1){
    String s = new String(bs, 0 , len);
    System.out.print(s);
}

输入字节到数组的某一部分

byte[] bs = new byte[6];
in = new FileInputStream("a.txt");
int len = in.read(bs, 1, 2);
System.out.println("读取了字节数:"+len+"   读取到的内容:"+ Arrays.toString(bs));

从下标为1开始,长度为2

3.复制

创建输入输出流对象

创建被复制文件的输入流对象

创建目标文件的输出流对象

定义一个字节数组,输入流读取写入数组,输出流读取数组中的内容写入字节输出流对象

复制图像

InputStream in = null;
OutputStream out = null;

try {
    //创建字节输入流
    in = new FileInputStream("plane.jpg");
    //创建字节输出流
    out = new FileOutputStream("plane01.jpg");
    //定义一个字节数组,输入流读取写入数组,输出流读取数组中的内容写入字节输出流对象
    byte[] bs = new byte[1024];
    int len = -1;
    while((len = in.read(bs)) != -1){
        //把读取的数据写入字节输出流
        out.write(bs, 0, len);
    }


} catch (Exception e) {
    e.printStackTrace();
} finally {
    try {
        if(out != null){
            out.close();
        }
        if(in != null){
            in.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

}

4.复制-BufferedInputStream和BufferedOutputStream

BufferedInputStream (Java 2 Platform SE 6)

        创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。

        之前的是一个字节一个字节读,带缓冲之后的流,可以一次读很多字节。

//定义一个高效缓存字节流
BufferedInputStream in = null;
BufferedOutputStream out = null;

try {
    //创建一个高效缓存字节流对象
   in = new BufferedInputStream(new FileInputStream("plane.jpg"));
    out = new BufferedOutputStream(new FileOutputStream("plane01.jpg"));
    //定义一个字节数组
    byte[] bs = new byte[1024];
    //定义一个标志
    int len = -1;
    while((len = in.read(bs)) != -1){
        out.write(bs, 0, len);
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    try {
        if(out != null){
            out.close();
        }
        if(in != null){
            in.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

总结:

  • 从输入输出角度,分为

         输入流,输出流

  • 从数据角度,分为
  1. 字符流:Writer和Reader

                高级的

                        BufferedReader和BufferedWriter

     2. 字节流:inputStream和outputStream

                高级的就是BufferedinputStream和BufferedOutputStream

         复制,就是先输入,再输出


4.相互转化

字符流可以操作字节流的所有操作

        编码格式不一样,会造成翻译过来的字节数组不一样。

OutputStreamWriter是一个单独的类:字符流通向字节流的桥梁

        与之相对的是InputStreamReader: 字节流通向字符流的桥梁

//创建字符流转换字节流的桥梁的对象
OutputStreamWriter ow = null;

try {
    ow = new OutputStreamWriter(new FileOutputStream("b.txt"));
    ow.write("中");
    ow.flush();
} catch (Exception e) {
    e.printStackTrace();
}finally {
    try {
        if(ow != null){
            ow.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

String s = new String("中");
byte[] gbks = s.getBytes("GBK");
System.out.println(Arrays.toString(gbks));


5.properties

在JDK里properties是对象

        有一种文件格式.properties,里面是key-value格式。

        通过IO流读取这个文件,得到key和value。一般可以用于连接数据库。

Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。

特点:

        1.继承于Hashtable,是线程安全的键值对存储结构

        2. Properties 可保存在流中或从流中加载

        3. 只能保存字符串的键值对。

//创建一个Properties对象
Properties prop = new Properties();

System.out.println(prop);

InputStream in = null;
try {
    //in = new FileReader("src/names.properties");
    //通过类的类对象  加载的时候读取 propreties文件拿到键值对数据   并使用Properties的类的API存取数据的过程
     in = PropTest6.class.getClassLoader().getResourceAsStream("names.properties");
    System.out.println(in);
     //从字节流中来加载数据到属性对象中
    prop.load(in);
    System.out.println(prop);

} catch (Exception e) {
    e.printStackTrace();
} finally {
    if(in != null){
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

类名.class发射获取类信息。

.getClassLoader()加载的时候

getResourceAsStream资源变成流的形式。

创建properties对象,这个对象加载这个流得到键值对。

//创建一个Properties对象
        Properties prop = new Properties();

        //存储键值对
        prop.setProperty("001", "liangge");
        prop.setProperty("002", "liangliang");
        prop.setProperty("003", "daliang");

        System.out.println(prop);

        String name1 = prop.getProperty("001");
        String name2 = prop.getProperty("002");
        String name3 = prop.getProperty("003");

        System.out.println(name1);
        System.out.println(name2);
        System.out.println(name3);

 

实际应用场景

JDBC:

创建了一个连接数据库的文件。

工具类:

        创建properties对象,在加载这个流的时候得到键值对。

        通过key找到对应的value值,把value值赋给静态对象。

        static代码块:类一加载的时候就调用

        一加载一调用一读取,就可以连接到数据库。

        之后如果再想更改数据,直接在配置文件里更改

        微服务器:游戏,原来更新需要停服好几天。现在是不停服更新。

        以后项目部署了,想换一个库,不需要停掉项目,可以在外部映射一个文件,外部这个文件改,里面那个文件跟着改。


6.序列化流

序列化流:

        对象输出流:(对象序列化)

ObjectOutputStream 将 Java 对象写入 OutputStream。

        对象输入流:(对象反序列化)

ObjectInputStream 对以前使用 ObjectOutputStream 写入的对象进行反序列化。

将对象序列化:

        实现序列化接口

以后在写实体类对象时可以加上。

生活例子:

        两套一模一样的积木,每一个零件都有编码,如果打散了,还能再找回。

        我们一般会提供一个serialVersionUID

        某个类序列化之后,如果类发生了 ,那么依然可以反序列化。

如果要是对多个对象来做序列化,一定要放在集合中。

一旦实现了Serializable接口,就能够实现序列化和反序列化接口

        当我们的业务中需要序列化多个文件时,用ArrayList存储对象,并序列化这个ArrayList就可以了。

        因为ArrayList本身是就是实现了Serializable接口,所以ArrayList是可以参与序列化的。


7.random

Random (Java 2 Platform SE 6)

        Random(long seed)           使用单个 long 种子创建一个新的随机数生成器。

                                种子不变,生成的这一组数据不变。

next(int bits)           生成下一个伪随机数。

nextInt()           返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。 

nextInt(int n)           返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。


http://www.kler.cn/a/544587.html

相关文章:

  • DeepSeek 助力 Vue 开发:打造丝滑的通知栏(Notification Bar)
  • post、get、delete、put请求
  • cnn以及例子
  • AI时代前端工程师的职业发展新路径
  • IS-IS 泛洪机制 | LSP 处理流程
  • 【Unity3D杂谈】使用NDK命令行工具翻译Android Vitals上的内存堆栈
  • 如何部署DeepDeepSeek-V3 大模型部署全流程解析:从云平台到本地化实践Seek—V3
  • OpenAI推出全新AI助手“Operator”:让人工智能帮你做事的新时代!
  • ConcurrentHashMap扩容
  • Spring Boot 中的事务管理:默认配置、失效场景及集中配置
  • Android原生的HighCPU使用率查杀机制
  • 基于Python的医院运营数据可视化平台:设计、实现与应用(下)
  • 使用CherryStudio、Ollama、腾讯云搭建本地个人知识库、智能体
  • LabVIEW外腔二极管激光器稳频实验
  • 【leetcode】关于循环数组的深入分析
  • Opensearch/ElasticSearch-ctx查询内容不全的问题
  • Python从0到100(八十八):LSTM网络详细介绍及实战指南
  • 基于千兆5G网关的5G急救车方案
  • git用法(简易版)
  • SSH 代理与私钥持久化:让你的开发环境不再因重启而中断