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); } }
相关文章推荐
- JAVA基础学习day22--IO流四-对象序列化、管道流、RandomAccessFile、DataStream、ByteArrayStream、转换流的字符编码
- JAVA基础学习(二十二)--IO流四-对象序列化、管道流、RandomAccessFile、DataStream、ByteArrayStream、转换流的字符编码
- Java基础——对象序列化+管道流+RandomAccessFile+操作基本数据类型的DataStream等
- IO流__【对象的序列化】【管道流】【RandomAccessFile】【DataStream】【ByteArrayStream等】
- 黑马程序员_IO流四(对象的序列化,管道流,RandomAccessFile,DataStream,ByteArrayStream)
- Java基础---Java---IO流-----对象的序列化、管道流、RandomAccessFile、数据类型的流对象DataStream、ByteArrayStream
- 黑马程序员——Java基础---IO(二)---对象流、管道流、RandomAccessFile、数据流、数组流、字符编码
- Java基础---Java---IO流-----对象的序列化、管道流、RandomAccessFile、数据类型的流对象DataStream、ByteArrayStream
- 黑马程序员_IO流4_(对象的序列化,管道流,RandomAccessFile,DataStream,ByteArrayStream)
- IO流5(IO包中的其他类,ObjectStream,管道流,RandomAccessFile,DataStream,ByteArrayStream)
- 黑马程序员——41,打印流,合并流,对象序列化,管道流,RandomAccessFile
- 黑马程序员--IO流(操作对象、管道流、RandomAccessFile)
- 黑马程序员_十七 【对象序列化】【管道流】【RandomAccessFile 类】等IO其他类
- 黑马程序员—异常+IO流File类+Properties+PrinWriter+合并流+切割文件+对象序列化+管道流+RandomAccessFile+操作基本数据类型的DataStre
- Java基础 管道流 RandomAccessFile DataStream ByteArrayStream 字符编码
- 黑马程序员---Java 编码解码的案例及特殊类RandomAccessFile
- 10.26的总结, 管道流用法, RandomAccessFile, DataStream 有待深入.
- 黑马程序员_Java第21天知识总结对象流_管道流_RandomAccessFile_数据流_字节数组流
- java--io流-打印流,序列流,操作对象,管道流,RandomAccessFile,操作字节数组
- JAVA之旅(三十)——打印流PrintWriter,合并流,切割文件并且合并,对象的序列化Serializable,管道流,RandomAccessFile,IO其他类,字符编码