您的位置:首页 > 职场人生

黑马程序员--- 学习笔记(第二十一天)

2014-04-15 16:12 267 查看
 —————————— 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培训、期待与您交流!——————————
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息