ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。

ObjectInputStream 确保从流创建的图形中所有对象的类型与 Java 虚拟机中显示的类相匹配。使用标准机制按需加载类。

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。

writeObject 方法用于将对象写入流中。所有对象(包括 String 和数组)都可以通过 writeObject 写入。可将多个对象或基元写入流中。必须使用与写入对象时相同的类型和顺序从相应 ObjectInputstream 中读回对象。

还可以使用 DataOutput 中的适当方法将基本数据类型写入流中。还可以使用 writeUTF 方法写入字符串。

对象的默认序列化机制写入的内容是:对象的类,类签名,以及非瞬态和非静态字段的值。其他对象的引用(瞬态和静态字段除外)也会导致写入那些对象。可使用引用共享机制对单个对象的多个引用进行编码,这样即可将对象的图形恢复为最初写入它们时的形状。  

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ObjectStreamDemo {

	public static void main(String [] args)throws Exception{
		writeObj();
		readObj();
	}
	public static void readObj()throws Exception{//这里抛的是Exception,而不是IOException,因为readObject()
		ObjectInputStream ois=new ObjectInputStream(new FileInputStream("c:\\obj.txt"));
		Person p=(Person) ois.readObject();
		System.out.println(p);
		ois.close();
	}

	public static void writeObj()throws IOException{
		ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("c:\\obj.txt"));//一般在实际应用当中,后缀名存的都是.object
		oos.writeObject(new Person("wangda",39,"USA"));//写完后就存在硬盘上,打印的结果还是cn,原因见person表
		oos.close();
	}

}

某个要序列化的对象不能实现,java.io.scrialable接口

Serializable这是一个接口

对象被存到文件里了,就被持久化

当某一个类被修改后,这个时候序列号就发生了改变,我们再对该文件进行读取时,就会发生异常。序列号就是根据成员变量来产生的。

import java.io.Serializable;

public class Person implements Serializable {//实现Serializable

    public static final long serialVersionUID =421;//这个uid就是指定了该类的序列号,下面改动类的方法属性都能使以后可以读写
	String name;
	transient int age;//对于非静态的成员,也不想将其序列化的话,可以加上关键字修饰。虽然还在堆内存当中,但是还是不能被序列化
	static String country="cn";//静态是不能被序列化的,它在方法学里面。而对象是在堆里面。能把堆里面的数据序列化,而不能把其他里面的东西序列化
	Person(String name,int age,String country){
		this.name=name;
		this.age=age;
		this.country=country;
	}
	public String toString(){
		return name+":"+age+":"+country;
	}

}

从这个管道写,从这个管道就可以读到,两根管子可以对接到一起。

管道输入流应该连接到管道输出流,管道输入流提供要写入管道输出流的所有数据字节,通常:数据由某个线程从PipedInputStream取,并由其他线程将其写入到相应的PipedOutPutStream,不建议对这两个对象尝试使用单个线程,因为这样可能死锁,管道输入流包含一个缓冲区,可在缓冲区限定的范围将读操作和写操作分开。如果向连接管道流输出流提供的数据字节的线程不再存在,则认为该管道流已损坏。涉及多线程技术的IO流。

import java.io.PipedInputStream;
import java.io.PipedOutputStream;

//使用多线程,一个是读,一个是写
 class Read implements Runnable{
	private PipedInputStream in;
	Read(PipedInputStream in) {
		this.in=in;
	}

	public void run(){

		try {
			System.out.println("读取前..没有数据阻塞");
			byte[] buf=new byte[1024];
			int len=in.read();
			System.out.println("读取后..阻塞结束");
			String s=new String(buf,0,len);//把int转化成字符串
			System.out.println(s);//打印管道流里面读取到的数据
			in.close();
		} catch (Exception e) {
			throw new RuntimeException("管道读取流失败");
		}
	}
}

 class Write implements  Runnable {
	private PipedOutputStream out;
	Write(PipedOutputStream out){
		this.out=out;
	}

	public void run() {
		try {
			System.out.println("开始写入数据,等待2s..");
			Thread.sleep(2000);
			out.write("zheshishenme".getBytes());
			out.close();
		} catch (Exception e) {
			throw new RuntimeException("管道输出流失败");
		}
	}
}

public class PipedStream {

	public static void main(String [] args) throws Exception{

		PipedInputStream in=new PipedInputStream();//管道读取流
		PipedOutputStream out=new PipedOutputStream();//管道输出流

		in.connect(out);//把这两个流给接上
		Read r=new Read(in);
		Write w=new Write(out);
		new Thread(r).start();//这两个线程没有先后顺序,是随机性的
		new Thread(w).start();

	}
}

DataOutputStream:

数据输出流允许应用程序以适当方式将基本 Java数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。 

DataInputStream:

数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。对于多线程访问不一定是安全的。 线程安全是可选的,它由此类方法的使用者负责。 



import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
 * 记事本显示的是字符,它对应查字符编码表
 * @author hjl
 *
 */
public class DataStream {

	public static void main(String [] args) throws IOException{
		writeData();
		readData();
		readUTFDemo();
		writeUTFDemo();
	}

	public static void readUTFDemo()throws IOException{
		DataInputStream dis=new DataInputStream(new FileInputStream("uftdate.txt"));
		String s=dis.readUTF();
		System.out.println(s);
		dis.close();

	}

	public static void writeUTFDemo() throws IOException{
		DataOutputStream dos=new DataOutputStream(new FileOutputStream("uftdate.txt"));
		dos.writeUTF("你好");
		dos.close();

	}

	public static void readData() throws IOException{
		DataInputStream dis=new DataInputStream(new FileInputStream("data.txt"));
		int num=dis.readInt();
		boolean b=dis.readBoolean();
		double d=dis.readDouble();
		System.out.println("num="+num);
		System.out.println("b="+b);
		System.out.print("d="+d);
	}

	public static void writeData() throws IOException{
		DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt"));
		dos.writeInt(234);
		dos.writeBoolean(true);
		dos.writeDouble(9888.90877);
	}
}

RandomAccessFile

此类的实例却支持对随机访部文件的读取和写入。随机访问文件的行为类似存储在文件系统中的大型byte数组,存在指向该隐含数组的光标或索引,称为文件指针,输入操作从文件指针开始读取字节,并随着对字节的读取前移此文件指针。如果随机访问文件以读取、写入模式创建,则输出操作也可以,输出操作从文件指针开始写入字节,并随着对字节的写入面前移此文件指针。写入隐含数组的当前未尾之后的输出操作导致该数组扩展,该 文件指针可以通过getFilePointer,并通过seek方法设置。



该类不是算是IO体系中子类

而是直接接继承自Object.

但是它是IO包中成员,因为它具备读和写功能,内部封装了了一个数组,而且通过指针对数组元素进行操作。同时可以通过Seek改变指针的位置

其实完成读写的原理就是内部封装了字节输入流和输出流。

通过构造函数可以看出,该类只能操作文件。

通过调节指针来取数据。随机访问文件

而且操作文件还有模式:只读r,读写等。

如果模式为只读r,不会创建文件,会去读取一个已存在文件,如果该文件不存在,则会出现异常

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

import java.io.*;
/*
RandomAccessFile
该类不是算是IO体系中子类。
而是直接继承自Object。

但是它是IO包中成员。因为它具备读和写功能。
内部封装了一个数组,而且通过指针对数组的元素进行操作。
可以通过getFilePointer获取指针位置,
同时可以通过seek改变指针的位置。

其实完成读写的原理就是内部封装了字节输入流和输出流。

通过构造函数可以看出,该类只能操作文件。
而且操作文件还有模式:只读r,,读写rw等。

如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。
如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖。

*/
class RandomAccessFileDemo
{
	public static void main(String[] args) throws IOException
	{
		writeFile_2();
		readFile();
	}

	public static void readFile()throws IOException
	{
		RandomAccessFile raf = new RandomAccessFile("ran.txt","r");
		//调整对象中指针。
		//raf.seek(8*1);

		//跳过指定的字节数
		raf.skipBytes(8);
		byte[] buf = new byte[4];
		raf.read(buf);

		String name = new String(buf);

		int age = raf.readInt();
		System.out.println("name="+name);
		System.out.println("age="+age);

		raf.close();

	}

	public static void writeFile_2()throws IOException
	{
		RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
		raf.seek(8*0);
		raf.write("周期".getBytes());
		raf.writeInt(103);
		raf.close();
	}

	public static void writeFile()throws IOException
	{
		RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");

		raf.write("李四".getBytes());
		raf.writeInt(97);
		raf.write("王五".getBytes());
		raf.writeInt(99);

		raf.close();
	}
}

DataIntputStream

DataOutputStream:创建一个新的数据输出流,将数据写入指定的基础输出流。

这两个流可以用于操作基本数据类型的数据的流对象。



用于操作字节数组的流对象

 ByteArrayInputStream

ByteArrayOutputStream

因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭。





用于操作字节数组的流对象。





ByteArrayInputStream :在构造的时候,需要接收数据源,。而且数据源是一个字节数组。





ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。

这就是数据目的地。



因为这两个流对象都操作的数组,并没有使用系统资源。

所以,不用进行close关闭。



在流操作规律讲解时:



源设备,

键盘 System.in,硬盘 FileStream,内存 ArrayStream。

目的设备:

控制台 System.out,硬盘FileStream,内存 ArrayStream。



用流的读写思想来操作数据。

import java.io.*;
class ByteArrayStream
{
	public static void main(String[] args)
	{
		//数据源。
		ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFD".getBytes());
		//数据目的
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		int by = 0;

		while((by=bis.read())!=-1)
		{
			bos.write(by);
		}

		System.out.println(bos.size());
		System.out.println(bos.toString());
	//	bos.writeTo(new FileOutputStream("a.txt"));

	}
}

IO包中的其他类。

操作基本数据类型

DataInputStream 与DataOutputStream

操作字节数组

ByteArrayInputStream与ByteArrayOutputStream

操作字符数组

charArrayReader与CharArrayWrite

操作字符串

StringReader与StringWriter

这些原理都是一样的。找到源和目的,

append(添加);

Java基础---Java---IO流-----对象的序列化、管道流、RandomAccessFile、数据类型的流对象DataStream、ByteArrayStream的更多相关文章

  1. java基础之IO流(二)之字符流

    java基础之IO流(二)之字符流 字符流,顾名思义,它是以字符为数据处理单元的流对象,那么字符流和字节流之间的关系又是如何呢? 字符流可以理解为是字节流+字符编码集额一种封装与抽象,专门设计用来读写 ...

  2. java基础之IO流(一)字节流

    java基础之IO流(一)之字节流 IO流体系太大,涉及到的各种流对象,我觉得很有必要总结一下. 那什么是IO流,IO代表Input.Output,而流就是原始数据源与目标媒介的数据传输的一种抽象.典 ...

  3. Java基础之IO流整理

    Java基础之IO流 Java IO流使用装饰器设计模式,因此如果不能理清其中的关系的话很容易把各种流搞混,此文将简单的几个流进行梳理,后序遇见新的流会继续更新(本文下方还附有xmind文件链接) 抽 ...

  4. Java基础-Java中23种设计模式之常用的设计模式

    Java基础-Java中23种设计模式之常用的设计模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.设计模式分类 设计模式是针对特定场景给出的专家级的解决方案.总的来说设 ...

  5. java基础---->java中正则表达式二

    跟正则表达式相关的类有:Pattern.Matcher和String.今天我们就开始Java中正则表达式的学习. Pattern和Matcher的理解 一.正则表达式的使用方法 一般推荐使用的方式如下 ...

  6. Java基础-Java中的堆内存和离堆内存机制

    Java基础-Java中的堆内存和离堆内存机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  7. Java基础-Java中的内存分配与回收机制

    Java基础-Java中的内存分配与回收机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一. 二.

  8. Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock)

    Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在学习Java的之前,你可能已经听说过读 ...

  9. Java基础-Java中的并法库之线程池技术

    Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.

  10. Java基础-JAVA中常见的数据结构介绍

    Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...

随机推荐

  1. POJ 2832 How Many Pairs?

    Description You are given an undirected graph G with N vertices and M edges. Each edge has a length. ...

  2. [bzoj4763]雪辉&[bzoj4812][Ynoi2017]由乃打扑克

    来自FallDream的博客,未经允许,请勿转载,谢谢. cut掉部分题面. 给一个n个点的树,点有点权,有m次询问,每次询问多条链的并有多少种不同的点权以及它的mex mex就是一个集合中最小的没有 ...

  3. Codeforces Round #398 (div.2)简要题解

    这场cf时间特别好,周六下午,于是就打了打(谁叫我永远1800上不去div1) 比以前div2的题目更均衡了,没有太简单和太难的...好像B题难度高了很多,然后卡了很多人. 然后我最后做了四题,E题感 ...

  4. CentOS 7 安装MySQL 5.6遇到问题及解决方案

    centos下安装mysql真的没有想象中那么容易,在这里我总结一下遇到的问题 1. ERROR 2002 (HY000): Can’t connect to local MySQL server t ...

  5. C++符号优先级

    C++符号优先级 优先级 操作符 功能 用法 结合性 1 ()[]->.::++-- Grouping operatorArray accessMember access from a poin ...

  6. 浅谈@RequestMapping @ResponseBody 和 @RequestBody 注解的用法与区别

    浅谈@RequestMapping @ResponseBody 和 @RequestBody 注解的用法与区别 Spring 2.5 版本新增了注解功能, 通过注解,代码编写简化了很多:但熟悉注解的使 ...

  7. Map,HashMap,TreeMap

    一.HashMap,TreeMap差别 1.两种常规Map性能 HashMap:适用于在Map中插入.删除和定位元素. Treemap:适用于按自然顺序或自定义顺序遍历键(key). 2.总结 Has ...

  8. zkCli的使用 常用的节点增删改查命令用法

    zkCli的使用 常用的节点增删改查命令用法 1. 建立会话  命令格式:zkCli.sh -timeout 0 -r -server ip:port ./zkCli.sh -server -time ...

  9. python字典无限遍历

    #无限遍历dict,通过key获取value,嵌套字典存在多个相同的key,可获取多个key class getValues(object): def __init__(self): pass #无限 ...

  10. golang 线程与通道

    首先我们来看线程,在golang里面也叫goroutine 在读这篇文章之前,我们需要了解一下并发与并行.golang的线程是一种并发机制,而不是并行.它们之间的区别大家可以上网搜一下,网上有很多的介 ...