Java基础---Java---IO流-----对象的序列化、管道流、RandomAccessFile、数据类型的流对象DataStream、ByteArrayStream
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的更多相关文章
- java基础之IO流(二)之字符流
java基础之IO流(二)之字符流 字符流,顾名思义,它是以字符为数据处理单元的流对象,那么字符流和字节流之间的关系又是如何呢? 字符流可以理解为是字节流+字符编码集额一种封装与抽象,专门设计用来读写 ...
- java基础之IO流(一)字节流
java基础之IO流(一)之字节流 IO流体系太大,涉及到的各种流对象,我觉得很有必要总结一下. 那什么是IO流,IO代表Input.Output,而流就是原始数据源与目标媒介的数据传输的一种抽象.典 ...
- Java基础之IO流整理
Java基础之IO流 Java IO流使用装饰器设计模式,因此如果不能理清其中的关系的话很容易把各种流搞混,此文将简单的几个流进行梳理,后序遇见新的流会继续更新(本文下方还附有xmind文件链接) 抽 ...
- Java基础-Java中23种设计模式之常用的设计模式
Java基础-Java中23种设计模式之常用的设计模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.设计模式分类 设计模式是针对特定场景给出的专家级的解决方案.总的来说设 ...
- java基础---->java中正则表达式二
跟正则表达式相关的类有:Pattern.Matcher和String.今天我们就开始Java中正则表达式的学习. Pattern和Matcher的理解 一.正则表达式的使用方法 一般推荐使用的方式如下 ...
- Java基础-Java中的堆内存和离堆内存机制
Java基础-Java中的堆内存和离堆内存机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.
- Java基础-Java中的内存分配与回收机制
Java基础-Java中的内存分配与回收机制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一. 二.
- Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock)
Java基础-Java中的并法库之重入读写锁(ReentrantReadWriteLock) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在学习Java的之前,你可能已经听说过读 ...
- Java基础-Java中的并法库之线程池技术
Java基础-Java中的并法库之线程池技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是线程池技术 二.
- Java基础-JAVA中常见的数据结构介绍
Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...
随机推荐
- bzoj1791: [Ioi2008]Island 岛屿 单调队列优化dp
1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1826 Solved: 405[Submit][S ...
- bzoj1293[SCOI2009]生日礼物 尺取法
1293: [SCOI2009]生日礼物 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2838 Solved: 1547[Submit][Stat ...
- 使用JAXB解析xml文件(一)
1.java中解析xml的几种方式 1.1 JDK原生dom形式 原理:一次性把xml读入内存,在内存中构建成树形结构.优点:对节点操作方便,缺点:需要大量的内存空间,浪费资源 1.2 SAX形式 ...
- 如何理解Spring IOC
Spring IOC 思维导图 要了解控制反转( Inversion of Control ), 我觉得有必要先了解软件设计的一个重要思想:依赖倒置原则(Dependency Inversion Pr ...
- Tinychain 是比特币的一个简易口袋实现
Putting the rough in "rough consensus" Tinychain is a pocket-sized implementation of Bitco ...
- Vue2学习结合bootstrapTable遇到的问题
Vue2学习 项目中在使用bootstrapTable的时候,在table里面会有操作结合vue使用过程中点击相应的操作不会起作用 解决办法 1.把事件绑定到父元素上即可,但要判断什么样的需要点击,用 ...
- npm ERR! Windows_NT 10.0.10586
安装vue脚手架时候一直失败,如图: npm cache clean 管理员下安装: 快捷键 win +x , 按A进入:
- python复杂网络库networkx:绘图draw
http://blog.csdn.net/pipisorry/article/details/54291831 networkx使用matplotlib绘制函数 draw(G[, pos, ax, h ...
- Git之(六)标签管理
发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本.将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来.所以,标签也是版本库的一个快照 ...
- Linux 性能监测:CPU
CPU 的占用主要取决于什么样的资源正在 CPU 上面运行,比如拷贝一个文件通常占用较少 CPU,因为大部分工作是由 DMA(Direct Memory Access)完成,只是在完成拷贝以后给一个中 ...