----------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! -----------
黑马程序员_java基础篇操作对象ObjectStream,管道流,随机存储Day5(下)
在了解怎样操作对象之前,我们先解释一下我们经常忽视的JVM中的堆区, 栈区, 方法区.
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
当我们了解了这些时,我们就可以继续我们的流操作了
(一)对于操作对象的流ObjectInputStream
对象是存在堆中的,堆的对象会封装一些数据,当我们用ObjectInputStream
去操作对象时,如下:
Peoson p=new Peoson("ouyang","2","hk");
ObjectOutputStream obj=newObjectOutputStream(new FileOutputStream("d:/ouyang.txt"));
obj.writeObject(p);
一定要将操作对象序列化,为什么要序列化?这样保证操作对象的唯一性, 序列化是什么?
我们可以看一些代码:
public class Peoson implements Serializable就是一个接口,这个接口是没有方法的,通常我们称这样的接口为标记接口.
public static void w()
{
Peoson p=new Peoson("ouyang","2","hk");
try{
ObjectOutputStream obj=new ObjectOutputStream(new FileOutputStream("d:/ouyang.txt"));
obj.writeObject(p);
obj.close();
}catch(Exception e)
{
e.printStackTrace();
}
}
public static void r() throws FileNotFoundException, IOException, ClassNotFoundException
{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("d:/ouyang.txt"));
Peoson p=(Peoson)ois.readObject();
System.out.println(p.getAge()+p.getName()+p.country);
}
由于我们使用了序列化对象,那么如果我们在编译执行以后又修改了原来的类,我们重新读取时,可能会出错,由于序列化的ID变了.所以如果我们想一直让此程序为固定id,我们可以用
public static final long serialVersionUID=42L;定义ID.
这有两个方法,读对象,写对象.注意在Peoson类中的静态变量是不能改写的,当我们试着改写peoson中定义的Static a=1时,我们怎么修改还是为1.如果这个数不是静态变量,我们怎么使其不备修改妮?这样定义 transientint a=1声明序列化的时候不被存储.静态变量是在方法区中的,对象流只能操作堆中的数据。
(二)管道流PipedInputStream,PipedOutputStream
在IO流中涉及到多线程的是管道流,为什么说管道流涉及到多线程呢?因为单线程可能发生死锁,如果一个线程将不知道分配资源给谁,如果给读取PipedInputStream,但没有写入,读取是空的,相反同理。
代码如下:
package Heima;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class Pip {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
PipedInputStream pis=new PipedInputStream();
PipedOutputStream pos=new PipedOutputStream();
pis.connect(pos);
Read r=new Read(pis);
Write w=new Write(pos);
Thread tr=new Thread(r);
Thread tw=new Thread(w);
tr.start();
tw.start();
}
}
class Read implements Runnable
{
private PipedInputStream pis;
Read(PipedInputStream pis)
{
this.pis=pis;
}
public void run() {
// TODO Auto-generated method stub
try {
byte[] b=new byte[1024];
int len=pis.read(b);
String str=new String(b,0,len);
System.out.println(str);
pis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Write implements Runnable
{
private PipedOutputStream pos;
public Write(PipedOutputStream pos)
{
this.pos=pos;
}
public void run() {
// TODO Auto-generated method stub
try
{
System.out.println("成功");
Thread.sleep(2000);
pos.write("sssss".getBytes());
pos.close();
}catch(Exception e)
{
e.printStackTrace();
}
}
(三)随机访问类RandomAccessFile
这是一个神奇的类,直接继承Object,既能读又能写,同时想读哪里指哪里。
注意里面的seek,skipBytes
我们看代码理解的比较清楚:
package Heima;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RamdomAccecc {
/**
*
* 他不是IO体系中的,
* 但是直接继承Object,但是他是IO包的成员,因为他能完成读写
* 可以通过getFilePointer得到指针的位置,可以通过seek改变指针位置
* 内部封装了字节输入流,输出流
* 通过他的构造函数,看出,他只能操作文件,而且操作文件还有模式
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
RandomAccessFile raf=new RandomAccessFile("d:/1.txt","rw");
byte[] b=new byte[4];
raf.write("欧阳".getBytes());
raf.writeInt(23);
raf.write("整的".getBytes());
raf.writeInt(24);
raf.close();
RandomAccessFile raf1=new RandomAccessFile("d:/1.txt","rw");
// raf.write("欧阳".getBytes());
//raf.writeInt(23);
//raf.close();
//raf1.seek(8);//移动指针
raf1.skipBytes(8);//这个只能往后移,但是seek想移哪里,移哪里。
raf1.read(b);
//raf1.readInt();
System.out.println(new String(b,0,4)+raf1.readInt());
}
}
----------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! -----------