标签:
用于操作字节数组的流对象
ByteArrayInputStream:在构造的时候需要接收数据源,而且数据源是一个字节数组。
ByteArrayOutputStream: 在构造时,不用定义数据目的地,
因为该对象中已经封装流一个可变长度的字节数组,该数组就为数据目的地。
因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭,
而且其不会产生IO异常。
这种方法是用流的思想操作数组。
注意:用于操作字符数组和操作字符串的流对象,基本与ByteArrayStream相同,详见说明书。
import java.io.*; class EByteArrayDemo{ public static void main(String[] args){ ByteArrayInputStream bis = //数据源 new ByteArrayInputStream("ABCDEFD".getBytes()); ByteArrayOutputStream bos = //数据目的地 new ByteArrayOutputStream (); int by = 0 ; while ((by=bis.read())!=-1){//将源数据长度赋予by,并判断是执行到文件末尾 bos.write(by); //将输入流中的字节数组存入输出流中的字节数组 } System.out.println(bos.size()); //打印输出流的长度 System.out.println(bos.toString()); //打印输出流的字符串形式 } }
//DataStream可以用于操作基本数据类型的流对象。
//局限性,使用时必须按照文件的类型,依次取出。
import java.io.*; class EDataStreamDemo { public static void main(String[] args) throws IOException { writeData(); readData(); } public static void readData() throws IOException { DataInputStream dis = new DataInputStream (new FileInputStream("d:\\demodata.txt")); //该方法必须按存入的顺序取出。 int num = dis.readInt(); //读取整数 boolean b = dis.readBoolean(); //读取Boolean类型数据 double d = dis.readDouble(); //读取Double类型数据 String utf = dis.readUTF(); //读取UTF编码数据 System.out.println("num="+num); System.out.println("b="+b); System.out.println("d="+d); System.out.println("UTF="+utf); dis.close(); } public static void writeData() throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream("d:\\demodata.txt")); dos.writeInt(234); dos.writeBoolean(true); dos.writeDouble(4323.355); dos.writeUTF("你好"); dos.close(); } }
管道流
PipedInputStream PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用。
思路:
1.创建Read类,覆写run方法,在run方法中实现文件读取并存储到s字符串中并打印出来。
2.创建Write类,覆写run方法,在run方法中实现文件的写入
3.分别创建输入和输出线程然后开启。
import java.io.*; class EPipedStreamDemo{ public static void main(String[] args) throws IOException{ PipedInputStream in = new PipedInputStream(); //定义输入流 PipedOutputStream out = new PipedOutputStream();//定义输出流 in.connect(out); //将输出流与输入流连接 Read r = new Read(in); //建立输入流的Read对象 Write w = new Write (out); //建立输出流的Write对象 (new Thread(r)).start(); //分别建立输入流和输出流的线程并开启 (new Thread(w)).start(); } } class Read implements Runnable{ //定义Read类实现Runnable接口 private PipedInputStream in; Read(PipedInputStream in){ //将输入流传入 this.in = in; } public void run(){ //在run方法中覆写读取操作 try{ byte [] byt = new byte[1024]; //定义字节数组 int len = in.read(byt); //将读取的内容写入字节数组 String s = new String(byt ,0 ,len); //将字节数组转为字符串 System.out.println(s); //打印读取的数据 in.close(); } catch (IOException e){ //定义IO异常的处理方法 throw new RuntimeException("管道读取流运行失败"); } } } class Write implements Runnable{ //定义Write实现Runnable接口 private PipedOutputStream out; Write(PipedOutputStream out){ //将输出流传入 this.out = out ; } public void run(){ //在run方法中覆写写入操作 try{ out.write("piped lai la".getBytes());//写入字符串的字节数据 out.close(); } catch (IOException e){ //定义IO异常处理方法 throw new RuntimeException("管道输出流运行失败"); } } }
操作对象的流
ObjectInputStrea ObjectOutputStream
需求:
实现操作对象流对对象的永久存储和数据读取。
思路:
1.定义Person类封装属性
2.定义对象输出流与目标文件关联,并向其写入Person对象数据
3.定义对象输入流与目标文件关联,并读取其中存储的Person对象数据
import java.io.*; class Person implements Serializable{ //注意实现接口 private String name; //定义成员变量 private int age; Person (String name ,int age){ //定义构造函数 this.name = name; this.age = age; } public String toString(){ //覆写toString方法 return name+":"+age; } } class EObjectStreamDemo{ public static void main(String[] args) throws Exception{ writeObj(); //调用写入对象方法 readObj(); //调用读取对象方法 } public static void readObj() throws Exception{ //定义读取对象方法 ObjectInputStream ois = //将对象输出流与文件相关联 new ObjectInputStream(new FileInputStream("d:\\person.txt")); Person p =(Person)ois.readObject(); //依次读取文件中的对象数据,注意强转为Person对象 System.out.println(p); //在控制台上打印对象 ois.close(); } public static void writeObj() throws Exception{ //定义写入对象方法 ObjectOutputStream oos = //将输出流与文件相关联 new ObjectOutputStream(new FileOutputStream("d:\\person.txt")); oos.writeObject(new Person("lili",39)); //输出新对象 oos.close(); } }
RandomAccessFile:随机读取流
该类不算是IO体系的子类,而是直接继承自Object
但是他是IO包中的成员,因为他具备读写功能。
可以通过getFilePointer获取指针位置。
同时可以seek改变指针的位置
其完成读写的原理就是在内部封装流字节输入流和输出流。
通过构造函数可以看出,本类只能操作文件,及固定模式
模式: r 只读 :不会创建文件,只会读取已存在文件,如果文件不存在就会报异常。
rw 读写:该对象的构造函数要操作的文件不存在,会自动创建;如果存在不会覆盖。
import java.io.*; class ERandomDemo{ public static void main(String[] args) throws IOException{ //writeR(); writeRR(); readR(); } public static void readR() throws IOException{ //关联文件和随机读取流,模式处写"r",表示只读 RandomAccessFile raf = new RandomAccessFile("d:\\demoRandom.txt","r"); byte[] byt = new byte[4];//设置的姓名4个字节,年龄4个字节,所以设置4个字节的数组 //调整指针位置,只能往后移动 raf.seek(8); //跳过指定的字节数 //raf.skipByte(int n); raf.read(byt); //将数据写入字节数组 String name = new String(byt); int age = raf.readInt();//读取整数操作 System.out.println("name:"+name); System.out.println("age:"+age); raf.close(); } //重点掌握,该方法通过同时多线程分别输入不同位段,实现多线程输入(类似迅雷等下载软件的方法) //仅该方法可以实现多线程多端输入。 public static void writeRR() throws IOException{ RandomAccessFile raf = new RandomAccessFile("d:\\demoRandom.txt","rw"); raf.seek(8*2); raf.write("周期".getBytes()); raf.writeInt(33); raf.close(); } public static void writeR() throws IOException{ RandomAccessFile raf = new RandomAccessFile("d:\\demoRandom.txt","rw"); raf.write("mik1".getBytes()); //注意,使用writeInt(),而不用write() //因为write()写入时只会使用1个字节,数字过大时会出现数据丢失 //writeInt()写入时占用4个字节。注意:1个中文2个字节 raf.writeInt(31); raf.write("mik2".getBytes()); raf.writeInt(32); raf.write("mik3".getBytes()); raf.writeInt(33); raf.close(); } }
转换流的编码表
编码:字符串变成字节数组
String-->byte[]: str.getBytes(charsetName)
解码:字节数组变成子符数组
byte[]-->String: new String(byte[],charsetName)
注意:1.GBK码的中文用utf-8解码后源码会变。因为他们都识别中文且中文码不同,
一种识别中文的码表转成不识别中文的码表就不会出现这种能情况。
2.GBK码的"联通"字符符合utf-8的编码形式。
import java.io.*; import java.util.*; class FTransDemo{ public static void main(String[] args) throws IOException{ writeTran(); readTran(); } public static void writeTran() throws IOException{ BufferedWriter bfws = //定义转换输出流与文件关联 new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:\\demotrans.txt"),"GBK")); bfws.write("你好"); //写入"你好" bfws.close(); } public static void readTran() throws IOException{ BufferedReader bfrs = //定义转换输入流与文件关联 new BufferedReader(new InputStreamReader(new FileInputStream("d:\\demotrans.txt")/*,"utf-8"*/)); char [] byt = new char [1024];//定义字符数组 int len =0; while((len=bfrs.read(byt))!=-1){//将缓冲区内的数据写入字符数组,并判断是否已到文件末尾 String s1 = new String(byt,0,len);//将字符数组转换为字符串 //打印按照指定码表的编码 System.out.println(Arrays.toString(s1.getBytes("GBK"))); System.out.println(Arrays.toString(s1.getBytes("utf-8"))); System.out.println(s1); } bfrs.close(); } }
IO流应用实例
需求:有5个学生,每个学生有3门课的成绩
从键盘中输入以上数据(包括姓名,3门课的成绩)
输入格式如:张三,30,40,60,计算出总成绩
并把学生信息和计算出的总分高低顺序存放在磁盘文件中"stud.txt"中
1.描述学生对象
2.定义一个可操作的学生对象工具类。
思想:
1.通过键盘获取一行数据,并将该行中的信息取出封装成学生对象。
2.因为学生有很多,那么久需要存储,使用到集合,因为要对学生的总分排序
所以用TreeSet存储。
3.将集合的信息写入到一个文件中。
import java.io.*; import java.util.*; public class StudentSort { public static void main(String[] args) throws NumberFormatException, IOException { // TODO Auto-generated method stub TreeSet<Student> stuSet = (TreeSet<Student>) StudentInfo.getStudent(); for (Student s : stuSet){ System.out.println(s+","+s.getSum()); } } } class Student implements Comparable<Student>{ private String name; //定义学生的属性 private int math,cn,en; private int sum; Student (String name, int math,int cn,int en){//定义构造函数 this.name = name; this.math = math; this.cn = cn; this.en = en; sum = math + cn + en; } public int compareTo(Student s){ //覆写排序方法,为先判断总分,再判断名字 int num = new Integer(s.sum).compareTo(new Integer(this.sum)); if(num==0) return s.name.compareTo(this.name); return num; } public int hashCode(){ //覆写hashcode获取方式 return name.hashCode()+sum*78; } public boolean equals (Object obj){ //覆写比较方法,定义姓名总分均相同的对象为同一对象 if(!(obj instanceof Student)) //判断比较对象是否为学生类型 throw new ClassCastException("类型不匹配"); Student s = (Student) obj; //将比较对象向下转型为Student return this.name.equals(s.name) && this.sum==s.sum; } public String toString(){ //覆写头String方法 return "student "+name+":"+math+","+cn+","+en; } public String getName(){ return name; } public int getSum(){ return sum; } } class StudentInfo{ public static Set<Student> getStudent() throws NumberFormatException, IOException{ BufferedReader bufr = //将输入流与键盘关联 new BufferedReader(new InputStreamReader(System.in)); String line = null; TreeSet stuSet = new TreeSet(); 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])); stuSet.add(stu); } return stuSet; //返回学生的集合 } }
在控制台上输入
输出结果
标签:
原文地址:http://www.cnblogs.com/myblog-cl/p/4746655.html