操作对象
ObjectInputStream
ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象。
ObjectOutputStream和ObjectInputStream可以分别为与FileOutputStream和FileInputStream一起使用的对象图提供持久性存储的应用程序。 ObjectInputStream用于恢复先前序列化的对象。 其他用途包括使用套接字流在主机之间传递对象,或者在远程通信系统中进行封送和解组参数和参数。
例如从ObjectOutputStream中的示例中写入的流中读取:
FileInputStream fis = new FileInputStream("t.tmp");
ObjectInputStream ois = new ObjectInputStream(fis);
int i = ois.readInt();
String today = (String) ois.readObject();
Date date = (Date) ois.readObject();
ois.close();
ObjectOutputStream
ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象。
例如,要写一个ObjectInputStream中的示例可以读取的对象:
FileOutputStream fos = new FileOutputStream("t.tmp");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeInt(12345);
oos.writeObject("Today");
oos.writeObject(new Date());
oos.close();
在序列化和反序列化过程中需要特殊
package com.monfolld.ObjectStream;
import com.monfolld.p.bean.Person;
import java.io.*;
public class ObjectStreamDemo {
public static void main(String[] args)throws IOException,ClassNotFoundException{
//writeObj();
readObj();
}
public static void writeObj()throws IOException {
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("obj.object"));
//对象的序列化。被系列化的对象必须实现Serilizable
oos.writeObject(new Person("小强",30));
oos.close();
}
public static void readObj()throws IOException,ClassNotFoundException{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("obj.object"));
//对象的反序列化
Person p=(Person)ois.readObject();
System.out.print(p.getName()+":"+p.getAge());
ois.close();
}
}
package com.monfolld.p.bean;
import java.io.Serializable;
import java.util.Objects;
/*Serializable:用于给被序列化的类加入ID号
* 用于判断类和对象是否是同一个版本*/
public class Person implements Comparable, Serializable {
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
private static final long serialVersionUID=95271;
//private transient String name;非静态数据不想被序列化可以使用这个关键字修饰
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString(){
return name+":"+age;
}
@Override
public int compareTo(Object o){
Person p=(Person)o;
int temp=this.age-p.age;
return temp==0?this.name.compareTo(p.name):temp;
}
}
RandomAccessFile
该类的实例支持读取和写入随机访问文件。 随机访问文件的行为类似于存储在文件系统中的大量字节。 有一种游标,或索引到隐含的数组,称为文件指针 ; 输入操作读取从文件指针开始的字节,并使文件指针超过读取的字节。 如果在读/写模式下创建随机访问文件,则输出操作也可用; 输出操作从文件指针开始写入字节,并将文件指针提前到写入的字节。 写入隐式数组的当前端的输出操作会导致扩展数组。 文件指针可以通过读取getFilePointer
方法和由设置seek
方法。
void writeInt(int v) //将 int写入文件为四个字节,高字节 int 。
void seek(long pos) //设置文件指针偏移,从该文件的开头测量,发生下一次读取或写入。
int readInt() //从该文件读取一个带符号的32位整数。
int read() //从该文件读取一个字节的数据。
package com.monfolld.randomfile;
import java.io.IOException;
public class RandomAccessFile {
public static void main(String[] args)throws IOException{
/*
* RandomAccessFile
* 特点:
* 1.该对象既能读,又能写
* 2.该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素
* 3.可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置
* 4.其实该对象就是将字节输入流和输出流进行封装
* 5.该对象的源或者目的只能是文件,通过构造函数就可以看出*/
writeFile();
readFile();
randomWrite();
}
//使用RandomAccessFile对象写入一些人员信息,比如姓名和年龄
public static void writeFile()throws IOException {
/*如果文件不存在,则创建,如果文件不存在,不创建*/
java.io.RandomAccessFile raf=new java.io.RandomAccessFile("ranacc.txt","rw");
raf.write("张三".getBytes());
raf.writeInt(97);//1001100001结果和raf.write(97)一样,二进制低八位是1100001,结果是a
raf.write("李四".getBytes());
raf.writeInt(98);
raf.close();
}
public static void readFile()throws IOException{
java.io.RandomAccessFile raf=new java.io.RandomAccessFile("ranacc.txt","r");
//通过seek设置指针的位置
raf.seek(1*10);//随机的读取,只要指定指针的位置即可
byte[] buf=new byte[6];
raf.read(buf);
String name=new String(buf);
int age=raf.readInt();
System.out.print("name="+name);
System.out.print("age="+age);
System.out.print("pos:"+raf.getFilePointer());
raf.close();
}
public static void randomWrite()throws IOException{
java.io.RandomAccessFile raf=new java.io.RandomAccessFile("ranacc.txt","rw");
//往指定位置写入数据
raf.seek(3*8);
raf.write("赵六".getBytes());
raf.writeInt(102);
raf.close();
}
}
管道流
PipedInputStream
管道输入流应连接到管道输出流; 管道输入流然后提供写入管道输出流的任何数据字节。 典型地,数据被从一个读PipedInputStream
对象由一个线程并且数据被写入到对应的PipedOutputStream
通过一些其它线程。 不建议尝试从单个线程使用这两个对象,因为它可能会使线程死锁。 管道输入流包含一个缓冲区,在读取操作中将读取操作与限制内的操作相分离。 的管道被认为是broken如果正在提供的数据字节到连接的管道输出流中的线程不再存活。
PipedOutputStream
管道输出流可以连接到管道输入流以创建通信管道。 管道输出流是管道的发送端。 典型地,数据被写入到一个PipedOutputStream
由一个线程对象和数据被从连接读取PipedInputStream
通过一些其它线程。 不建议尝试从单个线程使用这两个对象,因为它可能会使线程死锁。 管被说成是broken如果从连接读取数据字节的螺纹管道输入流不再存活。
package com.monfolld.piped;
import com.sun.org.apache.bcel.internal.generic.NEW;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipedStream {
public static void main(String[] args)throws IOException {
PipedInputStream input=new PipedInputStream();
PipedOutputStream output=new PipedOutputStream();
input.connect(output);
new Thread(new Input(input)).start();
new Thread(new Output(output)).start();
}
}
class Input implements Runnable{
private PipedInputStream in;
Input(PipedInputStream in){
this.in=in;
}
public void run(){
try {
byte[] buf=new byte[1024];
int len=in.read(buf);
String s=new String(buf,0,len);
System.out.print("s="+s);
in.close();
}catch (Exception e){
}
}
}
class Output implements Runnable{
private PipedOutputStream out;
Output(PipedOutputStream out){
this.out=out;
}
public void run(){
try {
out.write("管道".getBytes());
}catch (Exception e){
}
}
}
操作基本数据类型的流对象
DataInputStream
数据输入流允许应用程序以独立于机器的方式从底层输入流读取原始Java数据类型。 应用程序使用数据输出流来写入稍后可以被数据输入流读取的数据。
DataOutputStream
数据输出流使应用程序以便携式方式将原始Java数据类型写入输出流。 然后应用程序可以使用数据输入流来读取数据。
package com.monfolld.datastream;
import java.io.*;
/*操作基本数据类型*/
public class DataStreamDemo {
public static void main(String[] args)throws IOException{
writeData();
readData();
}
public static void readData() throws IOException{
DataInputStream dis=new DataInputStream(new FileInputStream("data.txt"));
String str=dis.readUTF();
System.out.print(str);
}
public static void writeData()throws IOException {
DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeUTF("你好");
dos.close();
}
}
操作字节数组
ByteArrayInputStream
A ByteArrayInputStream
包含一个内部缓冲区,其中包含可以从流中读取的字节。 内部计数器跟踪read
方法要提供的下一个字节。
关闭ByteArrayInputStream没有任何效果。 在关闭流之后,可以调用此类中的方法,而不生成IOException 。
ByteArrayOutputStream
该类实现了将数据写入字节数组的输出流。 当数据写入缓冲区时,缓冲区会自动增长。 数据可以使用toByteArray()
和toString()
。
关闭ByteArrayOutputStream没有任何效果。 该流中的方法可以在流关闭后调用,而不生成IOException 。
package com.monfolld.bytestream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class ByteArrayStreamDemo {
public static void main(String[] args){
ByteArrayInputStream bis=new ByteArrayInputStream("abcdefg".getBytes());
ByteArrayOutputStream bos=new ByteArrayOutputStream();
int ch=0;
while ((ch=bis.read())!=-1){
bos.write(ch);
}
System.out.println(bos.toString());
}
}
编码表
简单编码解码
package com.monfolld.encode;
import java.io.IOException;
public class EncodeDemo {
public static void main(String[] args)throws IOException{
/*字符串->>字节数组 编码
* 字节数组->>字符串 解码*/
String str="你好";
//编码
byte[] buf=str.getBytes("utf-8");
printBytes(buf);
//解码
String s1=new String(buf,"GBK");
System.out.println("s1"+s1);
}
private static void printBytes(byte[] buf){
for (byte b:buf){
System.out.print(b+" ");
}
}
}
按字节截取字符串
package com.monfolld.encode;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class Test {
/*在java中,字符串"abcd"与字符串"ab你好"的长度是一样,都是四个字符
* 但对应的字节数不同,一个汉字占两个字节
* 定义一个方法,按照最大的字节数来取子串
* 如:对于"ab你好",如果取三个字节,那么子串就是ab与"你"字的半个,
* 那么半个就要舍弃。如果去四个字节就是"ab你",取五个字节还是"ab你"*/
public static void main(String[] args)throws IOException,ArrayIndexOutOfBoundsException{
String str="ab琲琲cd琲琲";
int len=str.getBytes("gbk").length;
/*byte[] buf=str.getBytes("gbk");
for (byte b:buf){
System.out.println(b);
}*/
for (int x=0;x<len;x++){
System.out.println("截取"+(x+1)+"个字节结果是:"+cutStringByByte(str,x+1));
}
}
public static String cutStringByByte(String str,int len)throws IOException,ArrayIndexOutOfBoundsException{
byte[] buf=str.getBytes("gbk");
int count=0;
for (int x=len-1;x>=0;x--){
if (buf[x]<0)
count++;
else
break;
}
if (count%2==0)
return new String(buf,0,len,"gbk");
else
return new String(buf,0,len-1,"gbk");
}
}