Java学习I输入O输出流初见

今天下午复习了IO输入输出流,就让小编来带领大家感受IO输入输出的内容吧。(以下是概念性内容,如果不想看就跳过,不BB直接看代码)。

在Java中,Everything is Object!所以在文件中,也不例外!在Java中,可以用 File 类来表示一个与硬盘上文件联系!!!

注意: 1、File仅代表一个联系,可能文件存在,也可能不存在; 2、这里的文件可以是文件,也可以是文件夹;

IO流介绍

对于任何程序设计语言而言,输入输出( I/O )系统都是比较复杂的而且是比较核心的部分。程序运行需要数据,数据的获取往往需要跟外部系统进行通信,外部系统可能是文件、数据库、其他程序、网络、IO设备等等 。我们可以发现,外部系统比较 复杂多变,那么我们有必要通过某种手段进行抽象、屏蔽外部的差异。我们希望通过某种技术实现对所有外部系统的输入输出操作, java.io 包为我们提供了相关的API,这就是Java的IO部分。

数据源

data source , 提供原始数据的原始媒介。常见的: 数据库、文件、其他程序、内存、网络连接、IO设备 。

数据源就像水箱,流就像水管中流着的水流,程序就是我们最终的用户。 流是一个比较抽象、动态的概念,是一连串连续动态的数据集合。

IO流的分类图

乍一看,IO流似乎很多,很复杂,但是不用担心,IO流看似复杂,实则很简单,所有的流写法都很像。

处理数据的单元

按处理数据单位分为:字节流和字符流。 处理数据是音频、视频、doc、文本等一切为字节流 ,仅能处理文本的为字符流 。 字节流和字符流的用法几乎完全一致,区别在于它们所操作的数据单元不同,字节流(8 位)、字符流(16 位),字节流主要由 InputStream 和 OutputStream 作为基类,字符流主要由 Reader 和 Writer 作为基类。

流向分类

输入流和输出流两种,从节点到 java 内存叫输入流, 从 java 内存到节点 叫输出流。Java 的输入流主要由 InputStream 和 Reader 作为基类,输出流主要由 OutputStream 和 Writer 作为基类。 (以程序为中心就非常好理解)

输入流:数据源 -> 程序

输出流:程序 -> 目的地

功能分类

节点流处理流

直接从/向一个特定的I/0设备(磁盘、网络等)读写数据的流称为节点流,也常被称为低级流。

处理流则对于一个已存在的节点流进行连接或封装 , 常被称为高级流(装饰器设计模式)。处理流为增强、提升性能的,本身不具备 接操作节点的能力。如扩音器,就是放大声音的。

节点流处于io操作的第一线,所有操作必须通过他们进行;

处理流可以对其他流进行处理(提高效率或操作灵活性)。

节点流:可以直接从数据源或目的地读写数据。

处理流:不直接连接到数据源或目的地,是处理流的流。通过对其他流的处理提高程序的性能。

架构图

FileOutputStream 用于写入诸如图像数据之类的原始字节的流。要写入字符流,请 考虑使用 FileWriter。

使用流抽象的概念,屏蔽了实际的 I/O设备中处理数据的细节。

IO操作步骤(重点)

在进行任何操作之前,首先要明确目的(读还是写),找准源头(读取),找准目的地(写出)。

1.建立联系:这一步骤是为了获取流,如果此时是文件,则需要将文件抽象到内存形成对象。后期也可以是其他的数据源。

2.选择流:从读写、数据单元和功能方面考虑。输入|输出,字节|字符,结点流|处理流。

3.执行操作:该读就读,该写就写。考虑是一次性完成还行需要循环。

4.释放资源:程序中打开的文件 IO 资源不属于内存中的资源,垃圾回收无法回收,需要手动关闭。

记住以上4个重点就可开始敲代码。

抽象类:InputStream 和 Reader

这个是 InputStream 中常用的方法

在Reader中常用如下几个方法

由上面两张图可以看出两个基类的功能基本相似,在读取文件时返回结果为 -1 时表明到了输入流的结束点。 InputStream 和 Reade 都是抽象的,不能直接创建它们的实例,可以使用它们的子类。

字节文件节点输入输出流

以下通过实现复制拷贝文件功能来讲解如何使用IO流,首先在桌面上创建 a.txt 和 b.txt,然和在 a.txt 中随意写上什么 ,再来上代码:

    // 定义文件位置
    String str="C:\\Users\\Administrator\\Desktop\\a.txt";
	String strout="C:\\Users\\Administrator\\Desktop\\b.txt";
    //文件映射,建立联系
	File file=new File(str);
	//字节文件节点输入输出流    组合技:拷贝
    //选择流
	InputStream in=new FileInputStream(file);
	OutputStream out=new FileOutputStream(strout);
	byte[]by=new byte[5];
	int len=0;
    //执行操作
	while ((len=in.read(by))!=-1) {
		String str2=new String(by,0,len);
		out.write(by, 0, len);
		System.out.print(str2);
	}
	out.flush();
    //释放资源
	out.close();
	in.close();

运行之后查看 b.txt 中是否有了 a.txt 中的内容。(光理论不实践的同学可能感觉没什么,但实践的同学有可能发现控制台中打印的汉字存在乱码,关于乱码的原因在我之前的文章里也讲过。这个乱码大致原因在于字节流将文件内容读到控制台,和你系统的编码不同所导致的,但复制拷贝的内容并不会出乱码)

字符文件节点输入输出流

//字符文件节点输入输出流
	Reader reader=new FileReader(str);
	Writer writer=new FileWriter(strout);
	char []ch=new char[5];
	int len1 =0;
	while ((len1=reader.read(ch))!=-1) {
		System.out.print(new String(ch,0,len1));
		writer.write(ch, 0, len1);
		
	}
	writer.flush();
	reader.close();
	writer.close();

当你运行字符文件输入输出流成功时会发现,字符流的格式和字节流的格式竟会这么相似,是不是感觉IO用起来不会让人感觉得困难了呢?

缓冲处理类:BufferedInputStream和 BufferedReader

缓冲提高性能: 字节流缓冲流直接套在节点流上即可使用;字符缓冲流 +新增方法 (不能使用多态)。

下面给出 BufferedInputStream 的构造器和常用方法

也给出了 BufferedReader 的构造器和常用方法

注意:父类引用指向子类对象时,不能使用子类新增方法 readLine

    InputStream bfi1=new BufferedInputStream(new FileInputStream(str));
    byte [] by2=new byte[5];
    int len3=0;
    while ((len3=bfi1.read(by2))!=-1) {
		System.out.print(new String(by2,0,len3));
	}
    bfi1.close();

转换处理流: InputStreamReader

转换流:将字节流转为字符流处理乱码(编码集、解码集)。

    Reader reader3=new InputStreamReader(new FileInputStream(str),"UTF-8");
	char []ch3=new char[5];
	int len4=0;
	while ((len4=reader3.read(ch3))!=-1) {
		System.out.print(new String(ch3,0,len4));
		
	}
	reader3.close();

数据处理流:DataInputStream

可以处理基本类型+String,保留数据的类型。前提是读取顺序与写出顺序一致,否则读取数据不正确。

    int a1=456;
	String a2="sadsad";
	DataOutputStream dos=new DataOutputStream(new FileOutputStream(str));
	dos.write(a1);
	dos.writeUTF(a2);;
	dos.flush();
	dos.close();

对象流

上面小编所的流都只能读写字节,字符形式的数据,而java中非常重要并且常见的对象类型的数据,如果想要存储到文件中应该怎么操作呢?这个时候就使用到了对象流。

序列化:是一个用于将对象状态转换为字节流的过程,可以将其保存到磁盘文件中或通过网络发送到任何其他程序。

反序列化:从字节流创建对象的相反的过程称为反序列化。

ObjectOutputStream(序列化)

        首先在使用 ObjectInputStream 和 ObjectOutputStream 的时候,放置在此IO中的对 象,必须要实现Serializable接口!序列化接口(实现了此接口,代表我们的对象支持序列化) 但是实现了Serializable接口之后,其中并没有实现任何方法,对于这种接口,我们 称之为标记接口注意: 要先序列化后反序列化

    ObjectOutputStream ops1=new ObjectOutputStream(new FileOutputStream(str));
	ObjectInputStream ois1=new ObjectInputStream(new FileInputStream(str));
	Student stu=new Student("张三",15,"男");
	Student stu2=new Student("张四",16,"男");
	Student stu3=new Student("张五",17,"男");
	Student stu4=new Student();
    //序列化 
	ops1.writeObject(stu);
	ops1.writeObject(stu2);
	ops1.writeObject(stu3);
    //反序列化
	Object obj=ois1.readObject();
	if (obj instanceof Student) {
		stu4=(Student)obj;
		System.out.println(stu4.toString());
	}
	ois1.close();
	ops1.flush();
	ops1.close();

总结:IO输入输出流体系庞大,但是却很实用,能对程序外部的文件进行基本操作,也是Java基础内容很重要的一部分。

学而不思则罔,思而不学则殆。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值