--------------------- android培训、java培训、java学习型技术博客、期待与您交流! -------------------
序列化
概述:将已有对象进行本地持久化存储,存入硬盘中,存储后的对象可以进行网络传输,通过ObjectInputStream和ObjectOutputStream进行操作。
常用方法
ObjectInputStream
readObject()//读取ObjectInputStream中读取对象
ObjectOutputStream
writeObject()//将对象写入ObjectOutputStream被写入的对象需要实现Serializable接口
操作步骤
Serializble接口
概述:类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。用于给类指定一个UID,该UID是通过类中的可序列化成员的数值签名运算出来的一个long型的值,只要成员中没有发生变化那么该值每次运算结果都一样,该值用于判断被序列化的对象和类文件是否兼容该接口中没有方法,像这样的接口我们一边称之为标记接口
自定义UID static final long SeriviableUID=42L
注意:静态成员变量,不会被序列化,对于非静态成员,可以通过transient关键字让其不能序列化。没有指定UID的值时,当类中的成员修改后之前序列化的对象无法读取
序列化对象
代码示例
import java.io.*;
//创建Peason类,实现Serializable接口
class Peason implements Serializable
{
//自定义serialVersionUID版本号
public final static long serialVersionUID=32L;
private String name;
transient private int age;
static String country="CN";//静态成员不能序列化
//构造函数
Peason(String name,int age,String id,String country)
{
this.name=name;
this.age=age;
this.country=country;
}
//复写toString方法
public String toString()
{
return name+":"+age+":"+country;
}
}
//序列化测试类
class ObjectStreamDemo
{
public static void main(String[] args)
{
//指定文件
File file =new File("3.txt");
Peason p=new Peason("zhangsan",25);
//序列化指定对象
writeObj(p,file);
//反序列化
readObj(file);
}
//将指定对象序列化到指定文件中
public static void writeObj(Peason p,File file)
{
ObjectOutputStream oos=null;
try {
//创建写入流对象,关流文件
oos=new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(p);//写入对象数据
}
catch (IOException e)
{
throw new RuntimeException("对象写入失败");
}
finally
{
try
{
if(oos!=null)
oos.close();
}
catch (IOException e)
{
throw new RuntimeException("关流失败");
}
}
}
//读取指定文件中的对象,也称反序列化
public static void readObj(File file)
{
ObjectInputStream ois=null;
try
{
//创建读取流对象,关联文件
ois =new ObjectInputStream(new FileInputStream(file));
//读取文件中的对象
Peason p=(Peason)ois.readObject();
System.out.println(p);
}
catch (Exception e)
{
throw new RuntimeException("文件读取对象失败");
}
finally
{
try
{
if(ois!=null)
ois.close();
}
catch (IOException e)
{
throw new RuntimeException("关流失败");
}
}
}
}
管道流
概述:对应对象PipedInputStream PipedOutputStream
特点:管道流对应的输出和输入对象可以进行连接,不需要通过容器来进行临时存储,通常在使用这两个流时,需要加入多线程技术,也就是让读写同时进行。
在多线程内同时运行
代码示例
import java.io.*;
class Read implements Runnable
{
private PipedInputStream in;
Read(PipedInputStream in)
{
this.in=in;
}
//覆盖run方法
public void run()
{
try
{
//用来存储读到的字节
byte[] by=new byte[1024];
System.out.println("读取前。。没有数据阻塞");
//读取流中数据
int len=in.read(by);
System.out.println("读到数据。。阻塞结束");
//将字节数组转换为字符串打印输出
String s=new String(by,0,len);
System.out.println(s);
}
catch (IOException e)
{
throw new RuntimeException("读取数据失败");
}
finally
{
try
{
if(in!=null)
in.close();
}
catch (IOException e)
{
throw new RuntimeException("流关闭失败");
}
}
}
}
class Write implements Runnable
{
private PipedOutputStream out;
Write(PipedOutputStream out)
{
this.out=out;
}
public void run()
{
try
{
System.out.println("开始写入数据,等待3秒后。");
Thread.sleep(3000);
//写入数据到管道流中
out.write("piped shi shem ma?".getBytes());
}
catch (Exception e)
{
throw new RuntimeException("流写入失败");
}
finally
{
try
{
if(out!=null)
out.close();
}
catch (IOException e)
{
throw new RuntimeException("流关闭失败");
}
}
}
}
class PipedStreamDemo
{
public static void main(String[] args)
{
try
{
//创建管道流对象,并关联
PipedInputStream in=new PipedInputStream();
PipedOutputStream out=new PipedOutputStream();
in.connect(out);
//启动线程
new Thread(new Read(in)).start();
new Thread(new Write(out)).start();
}
catch (IOException e)
{
throw new RuntimeException("管道流关联失败");
}
}
}
RandomAccessFile类
概述:该对象并不是流体系中的一员,该对象中封装了字节输出流和字节输入流,还同时封装了一个字节数组缓冲区,通过内部指针来操作数组中的数据
特点:该对象只能操作文件,并且该对象可以进行读和写两种操作
构造方法
RandomAccessFile(File file,String mod)
当传入模式为只读r时,不会自动创建文件,当文件不存在时,会出现异常,当模式为读写rw时,文件不存在就会自动创建文件,文件存在不会覆盖
常用方法
seek(long pos)//指定指针的位置,没有设定指针的情况下,默认是在文件开头处,可以使用seek进行随机访问。
skipBytes()//跳过指定的字节数,只可往后跳,不可往前跳
getFilePointer()//获取指针位置
利用以上方法可以可以完成对文件数据的随机访问,想读哪里就读哪里。实际开发中可用于多线程下载
代码演示
import java.io.*;
class RandomAccessFileDemo
{
public static void main(String[] args)throws IOException
{
//指定文件
File file =new File("ran.txt");
//写数据
writeFile(file);
//读数据
readFile(file);
}
//读取指定文件中的数据
public static void readFile(File file)throws IOException
{
//创建对象
RandomAccessFile raf=new RandomAccessFile(file,"r");
//设置指针位置
raf.seek(8);
//设置跳过的字节数
//raf.skipBytes(8);
//读取四个字节存入
byte[] by=new byte[4];
//读数据
raf.read(by);
//将存入数据的字节数组转换为字符串
String name=new String(by);
//根据写入规律,读取年龄,这里用到了读一个int方法
int age=raf.readInt();
System.out.println("name="+name+"age="+age);
raf.close();//关流
}
//将数据写入指定文件中
public static void writeFile(File file)throws IOException
{
//创建对象
RandomAccessFile raf=new RandomAccessFile(file,"rw");
raf.write("李四".getBytes());
raf.writeInt(23);
raf.seek(8*0);//改变指针
raf.write("张三".getBytes());
raf.writeInt(23);
raf.skipBytes(8*2);//改变指针
raf.write("王五".getBytes());
raf.writeInt(35);
raf.close();//关流
}
}
操作基本数据类型的流
概述:操作基本数据类型对象,DataOutputStream和DataInputStream ,这两个类型的对象,内包含了读写各种基本数据类型的方法
常用方法
操作byte型
readbyte()
writeByte()
操作int型
readInr()
writeInt()
操作boolean
readBoolean()
writeBoolran()
操作double型
readDouble()
writeDouble()
操作long型
readLong()
writeLong()
指定编码为UTF-8修改版进行读写
readUTF()
writeUTF()
代码演示
import java.io.*;
class DataStreamDemo
{
public static void main(String[] args)
{
DataOutputStream dos =
new DataOutputStream(new FileOutputStream("c:\5.txt"));
dos.writeInt(255);
dos.writeBoolean(true);
dos.writeDouble(245.22);
}
}
操作数组的流对象
包括:字节数组
字符数组等
概述:对于操作数组的对象:共性该源是这些流,该目的也是这些流,因此这些流并没有调用系统资源,使用的是内存中的数组,也因此在使用时不需要close。
以字节数组做代码示例
import java.io.*;
class ByteArraysDemo
{
public static void main(String[] args)
{
ByteArrayInputStream bis = new ByteArrayInputStream("字节数组".getBytes());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int by=0
while((by=bis.read())!=-1)
{
bos.write(by);
}
System.out.println(bos.size);
}
}
字符编码
概述:计算机只能识别二进制数据,为了方彪应用计算机,让它可以识别各个国家的文字。就将各个国家的文字用数字来表示,并一一对应,这就是编码。
常见编码表
ASCII:美国标准信息交换码,使用的是1个字节的7位来表示该表中的字符
ISO8859-1:拉丁码表,使用一个字节的8位表示
GBK2312:中文编码表
GBK:GBK2312升级版,加入更多的中文字符,打头的是两个高位为1的两个字节编码为负数。
Unicode:国际编码表,融合多种文字,所有文字都用两个字节来表示
UTF-8:Unicode的升级,对每一个字节都加入了标识头
编码:字符串String转成byte数组的过程,称为编码
解码:字节数组转成字符串的过程,称为解码
编解码注意事项
1、如果编码失败,解码就没意义了。
2、如果编码成功,解码出来的是乱码,,则需对乱码通过再次编码(用解错码的编码表),然后再通过正确的编码表解码。针对于服务器中的IOS8859-1。
3、如果用的是GBK编码,UTF-8解码,此时通过再次编码后解码的方式,就不能成功了,因为UTF-8也支持中文,在UTF-8解的时候,会将对应的字节数改变,所以不会成功。
4中文的联通这两个字的二进制与UTF中的两个字节打头的相投,所以在文本文件中,如果单独写联通时,记事本会用UTF-8来进行解码,就会显示乱码
--------------------- android培训、java培训、java学习型技术博客、期待与您交流! -------------------