您的位置:首页 > 其它

day21对象流。管道流。RandomAccessFile。DataStream。字节流。常见的编码表。编码解码。联通问题。

2013-05-23 11:22 429 查看
/*
对象流。管道流。RandomAccessFile。DataStream。字节流。常见的编码表。编码解码。联通问题。
*/

/*
ObjectOutputStream:直接操作对象的流。
对象本身存在堆内存中,用流的方式将这个对象存到硬盘上。这叫对象的持久化。
Serializable:序列化的对象才能使用。没有方法的接口,称为标记接口。
序列化的原理就是产生了一个uid.这个uid是根据类中不同的成员算出来的。
静态不能被序列化,原理:静态在方法区,序列化在堆里。
当类改动private,要重新写,才能读。因为一个新的class有新的序列号。
非静态的我们不想被序列化,加上关键字transient。
*/
import java.io.*;
class  ObjectStream
{
public static void main(String[] args) throws Exception
{
//writeObj();
readObj();
}
public static void writeObj()throws Exception
{
ObjectOutputStream oos =
new ObjectOutputStream(new FileOutputStream("obj.txt"));
oos.writeObject(new Person("wangwu",49,"kr"));
oos.close();
}
public static void readObj()throws Exception
{
ObjectInputStream ois =
new ObjectInputStream(new FileInputStream("obj.txt"));
Person p = (Person) ois.readObject();//会抛出类没有找到异常。
System.out.println(p);
ois.close();
}
}
import java.io.*;
class Person  implements Serializable//实现是为了序列化
{
//public static final long serialVersionUID = 42L;自己定义uid,改动后也能操作。
String name;
transient int age;//transient修饰后不能被序列化
Static String country ="cn";//static 静态不能被序列化,写不进去。
Person(String name,int age,String country)
{
this.name = name;
this.age = age;
this.country = country;
}
public String toString()
{
return name +":"+ age+":"+country;
}
}

//PipedStream:管道流//用自己的管道,这个流的特点是先写入,再读。
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class PipedStreamDemo {
public static void main(String[] args) throws IOException
{
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
pos.connect(pis);//二个管道连起来。
Read r = new Read(pis);
Write w = new Write(pos);
new Thread(r).start();
new Thread(w).start();
}
}
class Read implements Runnable
{
private PipedInputStream pis;
Read(PipedInputStream pis)
{
this.pis = pis;
}
public void run()
{
byte[] buf = new byte[1024];
int num = 0;
try {
System.out.println("读取前等待");
num = pis.read(buf);//阻塞式的方法。
System.out.println("读取后。。。");
} catch (IOException e) {
throw new RuntimeException("piped读取失败");
}
System.out.println(new String(buf,0,num));
}
}

class Write implements Runnable
{
private PipedOutputStream pos;
Write(PipedOutputStream pos)
{
this.pos = pos;
}
public void run() {
try {
System.out.println("写入前等待");
Thread.sleep(6000);
pos.write("Piped lai le".getBytes());
} catch (Exception e) {
throw new RuntimeException("piped写入失败");
}
}
}

/*
RandomAccessFile,一个对象里面有读和写二个功能。
该类不是IO体系中子类。而是直接继承自Object

但是它是IO包中成员,因为它具备读和写功能。
内部封装了一个数组,而且通过指针对数组的元素进行操作。
可以通过getFilePointer获取指针位置
同时可以通过seek改变指针的位置。很重要!!!!!
其实完成读写的原理就是内部封装了字节输入流和输出流。

通过构造函数发现该类只能操作文件。还要传入模式。只读r,读写rw等。
而且该对象的构造函数要操作的文件不存在,创建,如果存在,不会覆盖。
*/
import java.io.*;
class RandomAccessFileDemo
{
public static void main(String[] args) throws IOException
{
//ranWrite();
//ranReader();
ranWrite2();
}

public static void ranWrite2()throws IOException//随机向里写。比喻迅雷
{
RandomAccessFile raf = new RandomAccessFile("acc.txt","rw");//rw可以读写。

raf.seek(8*4);//随机读写,还能从指定位置覆盖原来的。
raf.write("一啊".getBytes());
raf.writeInt(99);
raf.seek(8*4);

raf.close();
}

public static void ranReader()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("acc.txt","r");
//raf.write("haha".getBytes());构造函数传入r,就不能写。

raf.seek(8*1);//指针,前后都能指。
//raf.skipBytes(8*1);//跳过,指针不能向回走,只能向下走。

byte[] buf = new byte[4];
raf.read(buf);
String name = new String(buf);
int age = raf.readInt();//一次读32位。

System.out.println("name=" + name);
System.out.println("age=" + age);
raf.close();
}

public static void ranWrite()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("acc.txt","rw");
raf.write("小啊".getBytes());
raf.writeInt(99);//write,写入最低八位,一个字节。//writeInt写入32位。
//write写258,就会出错。
raf.write("二啊".getBytes());
raf.writeInt(90);//写四个字节

raf.close();
}
}
/*
DataStream:可以用于操作基本数据类型的数据的流对象。
DataInputStream和DataOutputStream.
DataOutputStream的构造函数要传入一个OutputStream.
*/

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class DataStreamDemo {

public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//dataWrite();
//dataRead();
//writeUTF();//好像是修改版的UTF-8
//readUTF();
OutputStreamWriter os = new OutputStreamWriter(
new FileOutputStream("data.txt"),"UTF-8");//writeUTF(),类似转换流写入
os.write("你好");
os.close();
}
public static void readUTF() throws IOException
{
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
String s = dis.readUTF();
System.out.println(s);
}
public static void writeUTF() throws IOException
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeUTF("你好");
dos.close();
}
public static void dataRead() throws IOException
{
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
int num = dis.readInt();
boolean b = dis.readBoolean();
Double d = dis.readDouble();
System.out.println("num="+num);
System.out.println("b="+b);
System.out.println("d="+d);
}
public static void dataWrite() throws IOException
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(23);
dos.writeBoolean(true);
dos.writeDouble(889.35);
dos.close();
}
}

/*
直接操作字节数组

ByteArrayInputStream。一建立对象就要有数据源。构造函数要传入字节数组。

ByteArrayOutputStream.在构造时不用定义数据目的,因为该对象内部已经封装了一个
可变长度的数组。这就是数据目的地。
writeTo(OutputStream),特有方法,只有它有异常。

因为这二个流对象都是操作数组,并没有使用系统资源。
不需要关闭。而且关闭后还可以用,不会报IO异常。

在流操作规律讲解时:
源设备:
键盘System.in,硬盘FileStream,内存ArrayStream
目的设备:
控制台System.out,硬盘FileStream,内存ArrayStream

用流的读写思想来操作数组。

类似的类:
CharArrayReader和CharArrayWriter,StringReader和StringWriter
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;

public class ByteArrayStreamDemo {

public static void main(String[] args) {
// 可以改变源,获取数据
ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFGHIJKLMN".getBytes());

ByteArrayOutputStream bos = new ByteArrayOutputStream();
//bos.writeTo(new FileOutputStream("byte.txt"));//把文件一次性的写出。
int ch = 0;
while((ch=bis.read())!=-1)
{
bos.write(ch);//写入内部封装的数组
}
System.out.println(bos.size());
System.out.println(bos);
}
}

/*
常见的编码表:
ASCII:美国标准信息交换码,用一个字节的七位可以表示。
ISO8859-1:拉丁码表。欧洲码表。用一个字节的八位表示。
GB2312:中国的中文编码表。二个字节代表一个文字,高位都是1。
GBK:中国的中文编码表升级,融合了更多的中文和符号。
Unicode:国际标准码,融合了多种文字。
所有文字都用二个字节来表示,java语言就用它。
UTF-8:最多用三个字节来表示一个字符。三个字节代表一个中文。
*/
import java.io.*;
class EncodeStream
{
public static void main(String[] args) throws IOException
{
//writeText();
readText();
}
public static void readText()throws IOException
{
//记住怎么存的,就怎么取。否则会出错。
InputStreamReader isr = new InputStreamReader(new FileInputStream("utf.txt"),"UTF-8");

char buf[] = new char[10]; //这里是字符。
int len = isr.read(buf);

String str = new String(buf,0,len);

System.out.println(str);
}
public static void writeText()throws IOException
{
OutputStreamWriter osw = //默认是GBK编码
new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");

osw.write("你好");
osw.close();
}
}
/*
编码:字符串变成字节数组
String-->byte[],getBytes()。

解码:字节数组变成字符串。
byte[]-->String,new String()的构造函数。

其他码,使用ISO8859-1解码错误,就再按照ISO8859-1编码回去byte[],
再按照怎么编码,就怎么解码。

假如使用GBK编码,使用UTF-8解码错误,但是再用UTF-8就编码不回去。
因为都用负数代表中文。
*/

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class CodeDemo {

public static void main(String[] args) throws UnsupportedEncodingException {

String s = "你好";
byte[] b1 = s.getBytes("UTF-8");//这里是编码
String s1 = new String(b1,"ISO8859-1");//这里解码错误
System.out.println(s1);
System.out.println("这里是怎么编码的"+Arrays.toString(b1));//这里是怎么编码的。

byte[] b2 = s1.getBytes("ISO8859-1");//再编码回去
System.out.println("错误解码编回来的"+Arrays.toString(b2));
String s2 = new String(b2,"UTF-8");//怎么编码,就怎么解码

System.out.println(s2);
}
}
/*
记事本存"联通",默认使用GBK。再打开怎么就没了呢?就这二个字比较特殊。
联通的后八位:11000001-10101010.刚好符合U8的规律。
怎么解决。在前面加一个不是符合U8的汉字,加英文还是不行的,因为还符合U8。
byte[] b = "联通".getBytes();
for(int x = 0;x<b.length;x++)
{
System.out.println(Integer.toBinaryString((b[x])&255));
}

GBK:二个字节代表一个汉字。
UTF-8:三个字节代表一个汉字。其他的字占几位就用几位存。
标识头信息:一个字节的话。第一个为0
二个字节:第一个为110,第二个字节为10开头
三个字节:字节1用1110开头,字节2用10开头,字节3用10开头。
*/

/*
练习:
定义一个学生类,有属性,名字,数学,语文,英语,总分。
在键盘录入:名字,数学,语文,英语
把这个学生按总分成绩存入一个文件中。
*/
import java.io.*;
import java.util.*;
class Student implements Comparable<Student>
{
private String name;
private int ma,cn,en;
private int sum;
Student(String name,int ma,int cn,int en)
{
this.name = name;
this.ma = ma;
this.cn = cn;
this.en = en;
sum = ma+cn+en;
}

public int compareTo(Student stu)
{
int num = new Integer(this.sum).compareTo(new Integer(stu.sum));
if (num == 0)
{
return this.name.compareTo(stu.name);
}
return num;
}

public String getName()
{
return name;
}
public int getSum()
{
return sum;
}
public int hashCode()
{
return name.hashCode()+sum*78;
}

public boolean equals(Object obj)
{
if (!(obj instanceof Student))
{
throw new ClassCastException("类型不符");
}
Student s = (Student)obj;
return this.name.equals(s.name) && this.sum == s.sum;
}

public String toString()
{
return "Student["+name+","+ma+","+cn+","+en+"]";
}
}

class StudentInfoTool
{
public static Set<Student> getStudents()throws IOException
{
return getStudents(null);
}

public static Set<Student> getStudents(Comparator<Student> cmp)throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
Set<Student> stus =null;
if (cmp == null)
{
stus = new TreeSet<Student>();
}
else
stus = new TreeSet<Student>(cmp);
while ((line = bufr.readLine())!=null)
{
if ("over".equals(line))
{
break;
}
String[] info = line.split(",");
Student stu = new Student(info[0],Integer.parseInt(info[1]),
Integer.parseInt(info[2]),
Integer.parseInt(info[3]));
stus.add(stu);
}
bufr.close();
return stus;

}

public static void write2File(Set<Student> stus)throws IOException
{
BufferedWriter bufw = new BufferedWriter(new FileWriter("infostu.txt"));
for (Student s:stus )
{
bufw.write(s.toString()+"\t");
bufw.write(s.getSum()+"");
bufw.newLine();
bufw.flush();
}
bufw.close();
}
}
public class StudentDemo2
{
public static void main(String[] args) throws IOException
{
Comparator cmp = Collections.reverseOrder();//反转比较器

Set<Student> stus = StudentInfoTool.getStudents(cmp);
StudentInfoTool.write2File(stus);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐