—————————— ASP.Net+Android+IOS开发、.Net培训、期待与您交流!——————————
ObjectInputStream
ObjectOutputStream
流构造的时候,必须有一个目的
直接操作对象数据的流
对象序列化(持久化)
要被流操作的对象必须实现Serialziable接口,否则会抛
NOSerializableException 没有序列化异常,
同时应该自定义SerivalVersionUID,给类一个固定标识符
public static final ServialVersionUID=78L;
InvaildClassException 无效类异常
静态不能被序列化,只能序列化堆内存的,不能序列化方法区的
,不想成员变量被序列化可以加上transient关键字
建议输出流的文件命名: 类名.Object
接口中没有方法称为标志接口
常用方法:
writeObject(); //写入对象
readObject(); //读取返回Object
管道流:
PipedInputStream
PipedOutputStream
输入和输出可以直接进行连接,涉及到多线程
connect();连接流
集合中涉及到IO的是Properties
IO中涉及到多线程的是PipeInputStream,PipeOutputStream
RandomAccessFile类
随机访问文件的读取和写入
该类不算是IO体系中的子类,而是直接继承Object,但是它是IO包中的
成员,因为他具备读和写功能,内部封装了一个数组,而是通过指针对数组
元素进行操作,可以通过getFilePointer获取指针位置,同时可以通过seek
改变指针位置.
其实完成读的原理就是内部封装了输入流和输出流,通过构造函数可以看出
该类只能操作文件,而且操作文件还有模式
r 只读
wr可读可写等
seek();//设置指针,前后都能跳
skipBytes();//跳过字节,只能往后跳
而且该对象的构造函数要操作的文件不存在会自动创建,如果存在则
不会覆盖,如果模式为r只读,不会创建文件,会去读取一个已存在的文件
如果该文件不存在,则会出现异常.如果模式为rw,文件不存在,会自动
创建,不会覆盖文件
可以实现数据的分段写入
DataInputStream与DataOutputStream
可以用来操作基本数据类类型的流对象
//注意, 写入的UTF-8修改版, 正常UTF-8无法读取
writeUTF();
readUTF();
字节数组流:
ByteArrayInputStream
在构造时需要接受数据源,数据源是一个字节数组
ByteArrayOutputStream
在构造时不用定义数据目的,因为该对象中内部已经封装了可变长度的字节数组
因为这两个对象操作的是数组,没有使用底层资源,所以不用进行close关闭
,不会抛任何IOException,除了writeTo(OutputStream);
toByteArray();//变成字节数组
size();//缓冲区大小
toString();//变成字符串形式
writeTo();//写出到字节输出流
设备:内存就是数组流
用流的读写思想操作数组,,
字符数组流:
CharArrayInputStream与CharArrayInputStream
字符串流:
StringReader与StringWriter
字符编码:
常见的编码表:
ASCII:美国标准信息交换码 一个字节7位表示
ISO8859-1:拉丁码表,欧洲码表 一个字节8位表示 最高位1
GB2312中国的中文编码表,两个字节表示 每个字节最高位1
GBK 中国的编码表升级,融合了更多的中文字符等
Unicode:国际标准码表,融合了多种文字,所有文字都有两个字节表示,
java使用的就是Unicode, char字符
UTF-8:最多用三个字节表示
编码:字符串变成字节数组
str.getBytes();//可以指定编码
解码:字节数组变成字符串
new String();//构造时可以指定编码
例如:
String s="你好";
byte []b=s.getBytes("GBK");
如果指定的编码不存在会报UnsupportedEncodingException 不支持的编码异常
乱码,编一次,解一次
UTF-8标识头,标识一开始读几个字节,最多三个
一个字节:0
两个字节:110 0
三个字节:1110 10 10
/*
练习题
*/
—————————— ASP.Net+Android+IOS开发、.Net培训、期待与您交流!——————————
ObjectInputStream
ObjectOutputStream
流构造的时候,必须有一个目的
直接操作对象数据的流
对象序列化(持久化)
要被流操作的对象必须实现Serialziable接口,否则会抛
NOSerializableException 没有序列化异常,
同时应该自定义SerivalVersionUID,给类一个固定标识符
public static final ServialVersionUID=78L;
InvaildClassException 无效类异常
静态不能被序列化,只能序列化堆内存的,不能序列化方法区的
,不想成员变量被序列化可以加上transient关键字
建议输出流的文件命名: 类名.Object
接口中没有方法称为标志接口
常用方法:
writeObject(); //写入对象
readObject(); //读取返回Object
/*
人类 对象持久化
*/
import java.io.Serializable;
public class Person implements Serializable
{
private static final long serialVersionUID=1314L;
private String name;
transient private int age; //被transient修饰不能序列化
static String city; //静态不能序列化
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
public Person(String name, int age,String city){
this.name=name;
this.age=age;
this.city=city;
}
}
/*
ObjectInputStream
ObjectOutputStream
直接操作对象数据的流
演示两个特殊方法:
writeObject();
readObject();
*/
import java.io.*;
class Demo1
{
public static void main(String[] args) throws Exception
{
//write();
read();
}
public static void read()throws Exception{
//从Person.object 中读取对象数据
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("Person.object"));
//返回Object需要强转
Person p=(Person)ois.readObject();
Person p1=(Person)ois.readObject();
//无法读取static数据 所以返回null
// System.out.println(p.getName()+""+p.city);
//被transient修饰的变量 返回0
System.out.println(p.getName()+""+p.getAge());
ois.close();
}
public static void write()throws IOException{
//写入对象数据 到Person.object
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("Person.object"));
oos.writeObject(new Person("张三",15,"张角"));
oos.writeObject(new Person("李四",50,"捏么"));
oos.close();
}
}
管道流:
PipedInputStream
PipedOutputStream
输入和输出可以直接进行连接,涉及到多线程
connect();连接流
集合中涉及到IO的是Properties
IO中涉及到多线程的是PipeInputStream,PipeOutputStream
/*
管道流
PipeInputStream
PipeOutputStream
演示
connect() 连接流
涉及到多线程
*/
import java.io.*;
class Demo2
{
public static void main(String[] args)throws Exception
{
PipedInputStream pis=new PipedInputStream();
PipedOutputStream pos=new PipedOutputStream();
pis.connect(pos);
new Thread(new Read(pis)).start();
Thread.sleep(6000);
new Thread(new Write(pos)).start();
}
}
class Read implements Runnable
{
private PipedInputStream pis;
public Read(PipedInputStream pis)throws IOException{
this.pis=pis;
}
public void run(){
try
{
byte []buf=new byte[1024];
int len=0;
while((len=pis.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
}
catch (IOException e)
{
System.out.println(e.getMessage());
}finally
{
try
{
if(pis!=null)
pis.close();
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
}
}
class Write implements Runnable
{
private PipedOutputStream pos;
public Write(PipedOutputStream pos){
this.pos=pos;
}
public void run(){
try
{
pos.write("我是管道流 我来le ".getBytes());
}
catch (IOException e)
{
System.out.println(e.getMessage());
}finally
{
try
{
if(pos!=null)
pos.close();
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
}
}
RandomAccessFile类
随机访问文件的读取和写入
该类不算是IO体系中的子类,而是直接继承Object,但是它是IO包中的
成员,因为他具备读和写功能,内部封装了一个数组,而是通过指针对数组
元素进行操作,可以通过getFilePointer获取指针位置,同时可以通过seek
改变指针位置.
其实完成读的原理就是内部封装了输入流和输出流,通过构造函数可以看出
该类只能操作文件,而且操作文件还有模式
r 只读
wr可读可写等
seek();//设置指针,前后都能跳
skipBytes();//跳过字节,只能往后跳
而且该对象的构造函数要操作的文件不存在会自动创建,如果存在则
不会覆盖,如果模式为r只读,不会创建文件,会去读取一个已存在的文件
如果该文件不存在,则会出现异常.如果模式为rw,文件不存在,会自动
创建,不会覆盖文件
可以实现数据的分段写入
/*
RandomAccessFile 类
getFilePointer();//获取指针
skipBytes();//跳过字节
seek(); 设置指针
实现多线程分段输出
*/
import java.io.*;
class Demo3
{
public static void main(String[] args)throws Exception
{
//读取
RandomAccessFile raf=new RandomAccessFile("g.mp3","rw");
//写入
RandomAccessFile raf1=new RandomAccessFile("gg.mp3","rw");
//三个线程进行分段写入
//seek 设置指针位置 实现分段功能
new Thread(new Thread1(raf,raf1,0)).start();
new Thread(new Thread1(raf,raf1,2097152)).start();
new Thread(new Thread1(raf,raf1,4194304)).start();
}
}
//多线程
class Thread1 implements Runnable
{
private RandomAccessFile raf;
private RandomAccessFile raf1;
private int skip;
public Thread1(RandomAccessFile raf,RandomAccessFile raf1,int skip){
this.raf=raf;
this.raf1=raf1;
this.skip=skip;
}
//run方法
public void run(){
try
{
byte []buf=new byte[1024*1024*2];
int len=0;
len=raf.read(buf);
raf1.write(buf,0,len);
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
finally
{
try
{
if(raf!=null)
raf.close();
if(raf1!=null)
raf1.close();
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
}
}
DataInputStream与DataOutputStream
可以用来操作基本数据类类型的流对象
//注意, 写入的UTF-8修改版, 正常UTF-8无法读取
writeUTF();
readUTF();
/*
DataInputStream
DataOutputStream
操作基本数据类型的流对象
*/
import java.io.*;
class Demo4
{
public static void main(String[] args)throws Exception
{
//write();
//read();
DataOutputStream dos=new DataOutputStream(new FileOutputStream("utf.txt"));
//使用utf-7修改版写输入
dos.writeUTF("你好");
dos.close();
DataInputStream dis=new DataInputStream(new FileInputStream("utf.txt"));
/*
//不能使用默认GBK的编码读 会乱码
byte bu[]=new byte[10];
int len=dis.read(bu);
sop(new String(bu,0,len));
*/
//只能使用ReadUTF才能读出来
sop(dis.readUTF());
dis.close();
}
public static void read()throws IOException{
DataInputStream dis=new DataInputStream(new FileInputStream("type.txt"));
//读的时候要按照写的顺序
sop(dis.readBoolean());
sop(dis.readByte());
//等等
dis.close();
}
public static void write()throws IOException{
DataOutputStream dos=new DataOutputStream(new FileOutputStream("type.txt"));
// void writeBoolean(boolean v)
// 将一个 boolean 值以 1-byte 值形式写入基础输出流。
dos.writeBoolean(true);
// void writeByte(int v)
// 将一个 byte 值以 1-byte 值形式写出到基础输出流中。
dos.writeByte(102);
// void writeBytes(String s)
// 将字符串按字节顺序写出到基础输出流中。
dos.writeBytes("bytes");
// void writeChar(int v)
// 将一个 char 值以 2-byte 值形式写入基础输出流中,先写入高字节。
dos.writeChar(97);
// void writeChars(String s)
// 将字符串按字符顺序写入基础输出流。
dos.writeChars("chars");
// void writeDouble(double v)
// 使用 Double 类中的 doubleToLongBits 方法将 double 参数转换为一个 long 值,然后将该 long 值以 8-byte 值形式写入基础输出流中,先写入高字节。
dos.writeDouble(4454.12);
// void writeFloat(float v)
// 使用 Float 类中的 floatToIntBits 方法将 float 参数转换为一个 int 值,然后将该 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。
dos.writeFloat(12.14f);
// void writeInt(int v)
// 将一个 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。
dos.writeInt(12121);
// void writeLong(long v)
// 将一个 long 值以 8-byte 值形式写入基础输出流中,先写入高字节。
dos.writeLong(4444444);
dos.close();
}
public static void sop(Object o){
System.out.println(o);
}
}
字节数组流:
ByteArrayInputStream
在构造时需要接受数据源,数据源是一个字节数组
ByteArrayOutputStream
在构造时不用定义数据目的,因为该对象中内部已经封装了可变长度的字节数组
因为这两个对象操作的是数组,没有使用底层资源,所以不用进行close关闭
,不会抛任何IOException,除了writeTo(OutputStream);
toByteArray();//变成字节数组
size();//缓冲区大小
toString();//变成字符串形式
writeTo();//写出到字节输出流
设备:内存就是数组流
用流的读写思想操作数组,,
/*
ByteArrayInputStream
ByteArrayOutputStream
字节数组流
只要不使用WriteTo();
其他方法都不操作底层数据 不会发生异常
*/
import java.io.*;
class Demo5
{
public static void main(String[] args)
{
String s="不管还有多少明天";
System.out.println("字节输入读取流\n");
ByteArrayInputStream bis=new ByteArrayInputStream(s.getBytes());
byte []bb=new byte[1024];
int ch=0;
while((ch=bis.read(bb,0,1024))!=-1){ //读取
System.out.println(new String(bb,0,ch));
}
System.out.println("\n字节数组写入流");
ByteArrayOutputStream bos=new ByteArrayOutputStream();
bos.write(12); //写入字节
bos.write(5);
bos.write(56);
byte []bu=bos.toByteArray();//转成字节数组
for (byte b : bu )
{
System.out.println(b);
}
System.out.println(bos.size());//获取缓冲区大小
}
}
字符数组流:
CharArrayInputStream与CharArrayInputStream
字符串流:
StringReader与StringWriter
字符编码:
常见的编码表:
ASCII:美国标准信息交换码 一个字节7位表示
ISO8859-1:拉丁码表,欧洲码表 一个字节8位表示 最高位1
GB2312中国的中文编码表,两个字节表示 每个字节最高位1
GBK 中国的编码表升级,融合了更多的中文字符等
Unicode:国际标准码表,融合了多种文字,所有文字都有两个字节表示,
java使用的就是Unicode, char字符
UTF-8:最多用三个字节表示
编码:字符串变成字节数组
str.getBytes();//可以指定编码
解码:字节数组变成字符串
new String();//构造时可以指定编码
例如:
String s="你好";
byte []b=s.getBytes("GBK");
如果指定的编码不存在会报UnsupportedEncodingException 不支持的编码异常
乱码,编一次,解一次
UTF-8标识头,标识一开始读几个字节,最多三个
一个字节:0
两个字节:110 0
三个字节:1110 10 10
/*
字符编码
编码
解码
*/
import java.io.*;
import java.util.*;
class Demo6
{
public static void main(String[] args)throws Exception
{ /*
String s="你好";
byte []b=s.getBytes();
byte []b1=s.getBytes("gbk");
byte []b2=s.getBytes("iso8859-1");
byte []b3=s.getBytes("utf-8");
sop(Arrays.toString(b));
//使用编码会引发UnsupportedEncodingException
System.out.println("\n b的多种解码格式 \n");
sop(new String(b));
sop(new String(b,"gbk"));
sop(new String(b,"utf-8")); //no ???
sop(new String(b,"iso8859-1"));//no ????
System.out.println("\n b1的多种解码格式 \n");
sop(new String(b1));
sop(new String(b1,"gbk"));
sop(new String(b1,"utf-8")); //no ???
sop(new String(b1,"iso8859-1"));//no ????
System.out.println("\n b2的多种解码格式 \n");
sop(new String(b2)); //no ??
sop(new String(b2,"gbk")); //no ??
sop(new String(b2,"utf-8"));//no ??
sop(new String(b2,"iso8859-1"));//no ??
System.out.println("\n b3的多种解码格式 \n");
sop(new String(b3)); // no 浣犲ソ
sop(new String(b3,"gbk"));// no 浣犲ソ
sop(new String(b3,"utf-8"));
sop(new String(b3,"iso8859-1"));//no ??????
*/
/*
默认字符串编码是gbk 使用的是系统默认的
*/
/*
String s="你好";
byte []b=s.getBytes("gbk");
String str=new String(b,"utf-8");
sop(str); // ???
byte bb[]=str.getBytes("utf-8");
sop(new String(bb,"gbk"));//锟斤拷锟?
*/
/* */
String s="你好";
byte []b=s.getBytes("utf-8");
String str=new String(b,"gbk");
sop(str); // 浣犲ソ
//在编一次,在解一次
byte bb[]=str.getBytes("gbk");
sop(new String(bb,"utf-8")); //你好
/*
String s="你好";
byte []b=s.getBytes("iso8859-1");
String str=new String(b,"utf-8");
sop(str); // ??
byte bb[]=str.getBytes("utf-8");
sop(new String(bb,"iso8859-1"));//??
*/
}
public static void sop(Object o){
System.out.println(o);
}
}
/*
练习题
*/
/*
练习
有五个学生,每个学生都有三门成绩
键盘录入
格式:张三,40,50,60
计算他们的总成绩, 按总分高低排序输出到stu.txt
*/
import java.util.*;
import java.io.*;
class Demo7
{
public static void main(String[] args)throws Exception
{
//反转比较器
Comparator<Student> cmp=Collections.reverseOrder();
//获取集合
TreeSet<Student> ts=set(cmp);
toText(ts);
}
//将数据录入存储到集合 不使用比较器
public static TreeSet<Student> set()throws Exception{
return set(null);
}
//将数据录入存储到集合 使用比较器
public static TreeSet<Student> set(Comparator<Student> cmp)throws Exception{
TreeSet<Student> ts=new TreeSet<Student>();
if(cmp!=null)
ts=new TreeSet<Student>(cmp);
//反转比较器 进行排序 Collection.reverseOrder()
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=br.readLine())!=null){
if("over".equals(line))
break;
String info[]=line.split(",");
ts.add(new Student(info[0],new Integer(info[1]),new Integer(info[2]),new Integer(info[3])));
}
br.close();
return ts;
}
//写到硬盘文件 stud.txt
public static void toText(TreeSet<Student> ts)throws IOException{
//写入流
PrintWriter pw=new PrintWriter(new FileOutputStream("stud.txt"));
Iterator<Student> it=ts.iterator();
while(it.hasNext()){
Student s=it.next();
pw.println(s.toString());//目的是流 所以自动刷新
}
pw.close();
}
}
//学生类,自身具备成绩比较性
class Student implements Comparable<Student>
{
private String name; //姓名
private int Yuwen; //语文
private int Shuxue; //数学
private int Yingyu; //英语
private int sum; //总分
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setYuwen(int Yuwen){
this.Yuwen=Yuwen;
}
public int getYuwen(){
return Yuwen;
}
public void setShuxue(int Shuxue){
this.Shuxue=Shuxue;
}
public int getShuxue(){
return Shuxue;
}
public void setYingyu(int Yingyu){
this.Yingyu=Yingyu;
}
public int getYingyu(){
return Yingyu;
}
public int getSum(){
return Yuwen+Shuxue+Yingyu;
}
//构造函数
public Student(String name, int Yuwen, int Shuxue, int Yingyu){
this.name=name;
this.Yuwen=Yuwen;
this.Shuxue=Shuxue;
this.Yingyu=Yingyu;
}
//复写 hashCode
public int hashCode(){
return (this.getName().hashCode())+(getSum()*13);
}
//复写 equals
public boolean equals(Object obj){
if(! (obj instanceof Student))
throw new ClassCastException("类型转换异常");
Student s=(Student)obj;
return (this.getName().equals(s.getName()))&&this.getSum()==s.getSum();
}
//复写compareTo
public int compareTo(Student s){
int num=new Integer(this.getSum()).compareTo(new Integer(s.getSum()));
if(num==0)
return this.getName().compareTo(s.getName());
return num;
}
//复写
public String toString(){
return "Student["+name+" "+Yuwen+" "+Shuxue+" "+Yingyu+" "+getSum()+" ]";
}
}
/*
lisi,10,20,30
wanwu,50,60,40
zhaoliu,100,50,60
wangwu,45,78,32
woziji,100,100,99
*/
—————————— ASP.Net+Android+IOS开发、.Net培训、期待与您交流!——————————