Java基础--IO流(四)IO包中的其他流

<span style="font-size:14px;">------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------</span>
对象序列化
一:概念:将堆内存中的对象存入硬盘,保留对象中的数据,称之为对象的持久化(或序列化)。
二:操作对象:ObjectInputStream与ObjectOutputStream,成对使用
注意:被操作的对象需要实现Serializable接口(也称标记接口)
三:方法
构造方法:
public ObjectInputStream(InputStream in)创建从指定 InputStream 读取的 ObjectInputStream。

public ObjectOutputStream(OutputStream out)创建写入指定 OutputStream 的 ObjectOutputStream。

ObjectInputStream:Object readObject();//从ObjcetInputStream中读取对象

ObjectOutputStream: void writeObject(Objcet obj);//将指定对象写入ObjcetOutputStream
四:操作步骤
说明:关于Serializable接口,标记接口,详细参照API
1.写入流对象:
(1)创建对象写入流,与文件关联,即传入目的
ObjectOutputStream oos =  new ObjectOutputStream(new FileOutputStream("obj.txt"));
(2)通过写入writeObject(Object obj)方法,将对象作为参数传入,即可写入文件
oos.writeObject(new Person("lisi0",399,"kr"));
2.读取流对象
(1)创建对象读取流,与文件关联,即传入源
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
(2)通过readObject()方法,读取文件中的对象,并返回这个对象
Person p = (Person)ois.readObject();
注:
(1)静态成员不能被序列化
(2)非静态成员要不被序列化,可以用关键字transient修饰,保证非静态成员保存在堆内存中,不能存入文件中。
示例:day21\ObjectStreamDemo.java

管道流
  --IO流中涉及到多线程的流
PipedInputStream和PipedOutputStream
构造函数:构造的时候将对面的流传入
public PipedInputStream(PipedOutputStream src)创建 PipedInputStream,使其连接到管道输出流 src。
public PipedOutputStream(PipedInputStream snk)创建连接到指定管道输入流的管道输出流。
特点:
1.输入输出可以直接进行连接,不用再借助数组或集合等容器进行临时存储。     
2.一般结合多线程使用。通常,数据由某个线程写入PipedOutputStream对象,并由其他线程从连接的 PipedInputStream 读取。

操作步骤:
        1.要先创建一个读和写的两个类,实现Runnable接口,因为是两个不同的线程,覆盖run方法,注意,需要在内部处理异常。
        2.创建两个管道流,并用connect()方法将两个流连接
        3.创建读写对象,并传入两个线程内,并start执行。
实例:PipedStreamDemo.java!!!

RandomAccessFile类!!!

1.此类的实例支持对随机访问文件的读取和写入,自身具备读写方法。

2.该类不算是IO体系中的子类,而是直接继承Object,但是它是IO包成员,

因为它具备读写功能,内部封装了一个数组,且通过getFilePointer方法获取指针位置,

来对数组的元素进行操作,同时可通过seek方法改变指针的位置。

3.可以完成读写的原理:内部封装了字节输入流和输出流。

4.构造函数:RandomAccessFile(File file,String mode),可已从它的构造函数中看出,

该类只能操作文件(可以传入文件名字符串),而且操作文件还有模式:只读“r”、读写“rw”等四种模式。

注:如果模式为只读r,则不会创建文件,会去读一个已存在的文件,若文件不存在,则会出现异常。

如果模式为读写rw,且该对象的构造函数要操作的文件不存在,会自动创建;如果存在,则不会覆盖。

特有方法:

        1.seek(long pos):调整对象中指针。来进行指定位置的数据读取和写入。数据要有规律。
如果设置的指针位置已有数据,写入时将会将其修改。用seek可以表示随机读写访问。
        2.int skipBytes(int n):跳过指定字节数,不可往前跳
RandomAccessFile中也有对基本数据类型进行读写的方法。还有readLine方法。
 使用步骤:
        1.创建RandomAccessFile对象
        2.将数据写入到指定文件中
        3.读取指定文件中的数据
注意:要单独读取后面的数据,可以使用seek方法调整指针,或skipBytes方法跳过指定字节数,这种通过改变指针位置的方式,取出相应的数据。
示例:RandomAccessFileDemo.java

操作基本数据类型的流对象
凡是操作基本数据类型就用这个类
1.操作基本数据类型的流对象:DataInputStream和DataOutputStream
2.这两个读写对象,可用于操作基本数据类型的流对象,包含读写各种基本数据类型的方法。
方法:
读: 
byte型            byte readbyte()
int型               intreadInt()
boolean型       boolean readBoolean()
double型        doublereadDouble()
String readUTF();//对应writeUTF,读取以UTF-8修改版编码写入的字符串
写:
byte型           writeByte(int b);//将b的低八位写入
int型              writeInt(int n)  
boolean型      writeBoolean(boolean b)    
double型        writeDouble(double d)  
writeUTF(String str);//以与机器无关方式使用UTF-8修改版编码将一个字符串写入基础输出流。
实例:DataStreamDemo.java
提示:一个汉字占用字节数:
gbk--2字节
utf-8--3字节
UTF-8修改版--4字节

操作数组与字符串的流对
一:操作字节数组的流:ByteArrayInputStream和ByteArrayOutputStream
1.close()方法,因为对象并没有调用底层资源,所以不用关闭流资源,即使关闭后,仍可调用。
内部包含缓冲区,相当于以内存作为流操作源和目的,不会产生任何IO异常。 
2.对象中封装了数组

3.构造函数:

        (1)ByteArrayInputStream(byte[] buf): 在构造函数的时候,需要接受数据源,而且数据源是一个字节数据。

        (2)ByteArrayOutputStream:在构造函数的时候,不用定义数据目的,因为该对象中已经在内部封装了可变长度的字节数组,这就是数据的目的地。
4.其实就是用流的思想操作数组
在流操作规律讲解时:
源设备:键盘 System.in,硬盘 FileStream,内存 ArrayStream。
目的设备:控制台 System.out,硬盘FileStream,内存 ArrayStream。
实例:ByteArrayStreamDemo.java
5.特有方法:
ByteArrayOutputStream中:
        writeTo(OutputStream out);//将此 byte 数组输出流的全部内容写入到指定的输出流参数中,这与使用out.write(buf, 0, count)调用该输出流的 write 方法效果一样。
//因为这个方法用到了字节输出流,需要抛IO异常,也是字节数组流中唯一需要抛异常的方法。
        int size();//当前缓冲区的大小

        String toString();//使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。

二:对应的字符数组和字符串

        字符数组流:CharArrayReader和CharArrayWriter
        字符串流:   StringReader和StringWriter

------------------------------------------------------------------------重要------------------------------------------------------
------------------------------------------------------------------------重要------------------------------------------------------
字符编码
一:概述
1.字符流的出现为了方便操作字符。
2.更重要的是加入了编码的转换,即转换流。
3.通过子类转换流来完成。在两个对象进行构造的时候,可以加入字符集(即编码表),可传入编码表的有:
        (1)转换流:InuputStreamReader和OutputStreamWriter
        (2)打印流:PrintStream和PrintWriter,只有输出流
编码表的由来
       计算机只能识别二进制数据,早期由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字。
       就将各个国家的文字用数字来表示,并一一对应,形成一张表。这就是编码表。
常见的编码表:
        (1)ASCII:美国标准信息交换码表。用一个字节的7位表示
        (2)IOS8859-1:拉丁码表;欧洲码表。用一个字节的8位表示
        (3)GB2312:中国的中文编码表()早期
        (4)GBK:中国的中文编码表升级,融合了更多的中文文字字符。打头的是两个高位为1的两个字节编码。为负数
        (5)Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言使用的就是unicode。
        (6)UTF-8:Unicode Transformation Format
最多用三个字节表示一个字符的编码表,根据字符所占内存空间不同,分别用一个、两个、三个字节来编码。
实例:EncodeStream.java
 
二:转换流的编码应用
        1.可以将字符以指定编码格式存储。
        2.可以对文本数据指定编码格式来解读。
        3.指定编码表的动作由构造函数完成。
 
三:编码和解码
1.编码:字符串变成字节数组
        (1)默认字符集: 
              String  --->  byte[]  :srt.getBytes()
        (2)指定字符集:
              String  --->  byte[]  :srt.getBytes(charsetName)
2.解码:字节数组变成字符串
        (1)默认字符集: 
              byte[]  --->  String :new String(byte[])
        (2)指定字符集: 
              byte[]  --->  String :new String(byte[],charsetName)
实例:EncodeDemo.java
EncodeDemo2.java
 
四:对于编码和解码的字符集转换注意事项
        1.如果编码失败,解码就没意义了。
        2.如果编码成功,解码出来的是乱码,,则需对乱码通过再次编码(用解错码的编码表),然后再通过正确的编码表解码。针对于IOS8859-1是通用的。
        3.如果用的是GBK编码,UTF-8解码,此时通过再次编码后解码的方式,就不能成功了,因为UTF-8也支持中文,在UTF-8解的时候,会将对应的字节数改变,所以不会成功。
4.特别注意:对于中文的”联通“,这两个字比较特别,它的二进制位正好是和在UTF-8中两个字节打头的相同,所以在文本文件中,
如果单独写“联通”或者和满足UTF-8编码格式的字符一起保存时,记事本就会用UTF-8来进行解码动作,这样显示的就会是乱码。


练习:StudentInfoTest.java!!!必须掌握!!!
有五个学生,每个学生有3门课的成绩,
从键盘输入以上数据(包括姓名,三门课成绩),
输入的格式:如:zhagnsan,30,40,60计算出总成绩,
并把学生的信息和计算出的总分数高低顺序存放在磁盘文件"stud.txt"中。
步骤:
1,描述学生对象。
2,定义一个可操作学生对象的工具类。
思想:
1,通过获取键盘录入一行数据,并将该行中的信息取出封装成学生对象。
2,因为学生有很多,那么就需要存储,使用到集合。因为要对学生的总分排序。
所以可以使用TreeSet。
3,将集合的信息写入到一个文件中。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值