IO操作!~~~超 淦/详细 的3500字

简介: IO操作!~~~超 淦/详细 的3500字

一、数据流


文件的读写采用数据流的方式,类似于一个储水池,输入的一端叫做 输入流,输出的一端叫做 输出流。而输入流和输出流采用的是 不同的类。如下图的关系。



d0215b36572647e98ce5c25336e64e4c.png


为什么input是读取,output是写入?

程序和运行时数据是在内存中驻留的,而 input,output都是相对内存来说 的,input是从磁盘读取到内存 ,output是从内存写到磁盘.

二、InputStream 概述


1. 方法

InputStream 只是一个抽象类,如果要创建实例化还需要具体的实现类。关于InputStream 的实现类有很多,而我们只关心从文件中读取,所以通常用 FileInputStream 实现


  • read() -从文件输入流中读取一个字节。
  • read(byte[] b) -从此输入流中读取最多b.length个字节的数据到一个字节数组中。
  • read(byte[] b, int off, int len) -从此输入流中读取最多len个字节的数据到一个字节数组中。


2. FileInputStream 子类

①构造方法


FileInputStream(File file) -创建文件输入流以从File对象读取。

FileInputStream(String name) -创建文件输入流以从指定的文件名读取。

FileInputStream(FileDescriptor fdObj) -创建从指定文件描述符读取的文件输入。

②代码案例

注意 !!!!

~ ~ 为什么每次关闭代码一定要关闭文件?


每个进程对应着一个PCB,而PCB里有一个文件描述符表(同一个进程中多个PCB共同使用一份文件描述符表),文件描述附表其实就相当于一个 数组\顺序表。每次进程打开一个文件,都会在这个表里创建一个项,这个项就表示一个文件。

表的项最大容量,可以进行配置。

如果关闭一个文件就相当于把表里对应的项 给释放掉,但是如果一直不关闭,就会一直占用。这就意味着一直打开都不关闭,就会导致 表项被耗尽~~这是一个非常严重的bug

~ ~ 所以才能每次都关闭呢?


1. 使用 close() , 但是要注意每次一定能执行到这一条语句


2. 使用 try-with-resource 结构(推荐使用!),try结束就能保证关闭文件,不用考虑是否执行到close 语句。(下面的代码案例就是这样写的)  


代码1:试用 read()


public class Demo1 {
    public static void main(String[] args) throws IOException {
        try (InputStream stream = new FileInputStream("./文件部分/测试.txt")) {
            while (true) {
                int b = stream.read();
                System.out.print(b);
                if (b == -1) {//代表文件已经读完
                    break;
                }
            }
        }
    }
}

文件中的内容是: Hello word.

输出结果是


f608346b14044f50b5efd68f7baef8fe.png


代码2:尝试读取中文字符

    public static void main(String[] args) throws IOException {
        try (InputStream stream = new FileInputStream("./文件部分/测试.txt")){
            byte[] b = new byte[12];
            int len;
            while (true){
                len = stream.read(b);//每次读取一个字节,返回刚读到的字节
                if (len == -1){
                    break;
                }
            }
            for (int i =0;i< b.length;i+=3){//
                //每次读取3字节进行TTF-8解码,得到中文字符
                //利用String的构造方法完成,这个方法不是通用解法,知道就行
                String s = new String(b,i,3,"UTF-8");
                System.out.printf("%s",s);
            }
        }
    }

文件中的内容是: 你好中国

输出结果是:

d16e4e249348485ea140617cc5263ac5.png


代码3:使用 Scanner 读取

  • Scanner(InputStream ,String charset) --使用charset字符集进行 is 的扫描读取


    public static void main(String[] args) throws IOException {
        try (InputStream is = new FileInputStream("./文件部分/测试.txt")){
            Scanner s = new Scanner(is);
            while (s.hasNext()){
                String ch = s.next();
                System.out.println(ch);
            }
        }
    }

文件中的内容是: 你好中国

输出结果是:

d16e4e249348485ea140617cc5263ac5.png

三、OutputStream概述

1. 方法


write() -写入要给字节的数据。

read(byte[] b) -将b这个字符数组中的数据全部写入OS(OutputStream)中。

read(byte[] b, int off, int len) -将b这个字符数组中从off开始的数据写入OS中,一共写len个

close() -关闭字节流。

flush() -重要!我们知道I/O操作是比较慢的,大多的OutputStream为了减少设备操作的次数,在写数据的时候会 先暂时写入内存的一个指定区域,知道这个区域满了以后才一起写入设备中,而这个区域一般称为 缓冲区。但是因此我们的部分数据可能会留在缓冲区,因此我们在一段代码完成的时候,记得进行 flush(刷新) 操作。


2. FileInputStream 子类

1. 构造方法

  • FileOutputStream(File file) -从File对象读取。
  • FileOutputStream(String name) -从指定的文件名读取。
  • FileOutputStream(FileDescriptor fdObj) -从指定文件描述符读取。

2.代码案例

代码1:写入文件


    public static void main(String[] args) throws IOException {
        try (OutputStream os = new FileOutputStream("./文件部分/测试.txt")){
            os.write('I');//传入一个字符
            os.write(' ');
            byte[] am = {'a','m',' '};//传入一个 byte类型的数组
            os.write(am);
            String str = "a boy.";
            byte[] boy = str.getBytes();//将字符串转换为 数组
            os.write(boy);//再从内存写入到文件中
            String s = "你呢?";
            byte[] b = s.getBytes("utf-8");//使用utf-8将其转换为中文传入
            os.write(b);
            os.flush();//不要忘记 flush
        }
    }

程序运行结束后,文件内容发生改变:


8e759f9317534990a197be0de5630b1d.png


代码2:利用 PrintWriter 这种高效的方法完成输出


    public static void main(String[] args) throws IOException {
        //创建一个文件流实例os 与本地文件 对应
        try (OutputStream os = new FileOutputStream("./文件部分/测试.txt")){
            //这个构造是 把输入的内容存放到os这个实例中,才用utf-8编码
            try(OutputStreamWriter osWriter= new OutputStreamWriter(os,"utf-8")){
                //这个构造 封装了print等输入方法,print到osWrite这个实例中
                try (PrintWriter printWrite = new PrintWriter(osWriter)){
                    printWrite.println("第一行!");
                    printWrite.print("第二行\n");
                    printWrite.flush();
                }
            }
        }
    }

程序运行结束后,文件内容发生改变:


42b51e2dbe4c4e8780afd1f28a52fa78.png

相关文章
|
3月前
|
存储 Linux API
Linux应用开发基础知识——文件IO操作(三)
Linux应用开发基础知识——文件IO操作(三)
69 2
Linux应用开发基础知识——文件IO操作(三)
|
10月前
|
Java 测试技术 Apache
Java IO 与 NIO:高效的输入输出操作探究
输入输出(IO)是任何编程语言中的核心概念,而在Java中,IO操作更是应用程序成功运行的基石。随着计算机系统变得越来越复杂,对IO的要求也日益增加。在本文中,我们将探讨Java IO和非阻塞IO(NIO)的重要性以及如何在Java中实现高效的输入输出操作。
|
10月前
|
存储 数据处理 索引
【100天精通python】Day27:文件与IO操作_CSV文件处理
【100天精通python】Day27:文件与IO操作_CSV文件处理
59 0
|
3月前
|
数据采集 异构计算
LabVIEW编程LabVIEW开发高级数据采集技术 操作数字IO 例程与相关资料
LabVIEW编程LabVIEW开发高级数据采集技术 操作数字IO 例程与相关资料
73 22
|
2月前
|
缓存 NoSQL Redis
redis管道操作(节省网络IO开销)
pipeline中发送的每个command都会被server立即执行,如果执行失败,将会在此后的响应中得到信息;也就是pipeline并不是表达“所有command都一起成功”的语义,管道中前面命令失败,后面命令不会有影响,继续执行。
31 1
|
3月前
|
Java
|
3月前
|
消息中间件 关系型数据库 Kafka
实时计算 Flink版操作报错之在执行任务时遇到了一个IO错误,具体表现为无法从本地主机(localhost)下载文件,该怎么解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
3月前
|
监控 Java
Java一分钟之-NIO:非阻塞IO操作
【5月更文挑战第14天】Java的NIO(New IO)解决了传统BIO在高并发下的低效问题,通过非阻塞方式提高性能。NIO涉及复杂的选择器和缓冲区管理,易出现线程、内存和中断处理的误区。要避免这些问题,可以使用如Netty的NIO库,谨慎设计并发策略,并建立标准异常处理。示例展示了简单NIO服务器,接收连接并发送欢迎消息。理解NIO工作原理和最佳实践,有助于构建高效网络应用。
35 2
|
3月前
|
存储 Go 数据处理
Golang简单实现IO操作
Golang简单实现IO操作
29 1
|
3月前
|
存储 Java 编译器
Java文件IO操作基础
Java文件IO操作基础
35 0