黑马程序员--Java基础之IO流(2)
2013-11-25 19:23
387 查看
黑马程序员--Java基础之IO流(2)
------------------------------------
android培训、java培训、期待与您交流! ----------------------------------
10、IO流--Properties简述
properties 是hashtable的子类,它具备Map集合的特点,而且它里面存储的键值对都是字符串。它是集合和IO技术相结合的集合容器。
该对象的特点:可以用于键值对形式的配置文件。那么在加载数据时,需要数据有固定格式:键=值。
Properties设置和获取元素:
Properties其他方法:
Properties练习:记录应用程序运行次数,如果使用次数已到,那么给出注册提示。代码示例:
11、其他流
*打印流:PrintStream和PrintWriter
*合并流(序列流): SequenceInputStream
*对象的序列化:ObjectOutputStream/ObjectInputStream
ObjectOutputStream,可以将对象由堆内存存储到文件中,实现了对象由内存搬运到硬盘中,被称为对象的持久化存储。
由ObjectOutputStream存储,必须要由ObjectInputStream读取,二者成对出现。
要被持久化存储的对象必须实现Serializable接口,才能被序列化。Serializable接口中没有方法,但是会给该类生成的对象产生一个uid,序列号。序列号是由该对象的成员决定的,所以当成员发生变化时,如变成私有化,再生成的对象,其序列化也会发生变化,当你按之前的序列号读取时会发生notfound异常。
*管道流PipedInputStream PipedOutputStream,写入流(输出流)写入到管道中,输入流直接从管道中将数据读取,不需要中间的文件中转。
* RandomAccessFile随机访问文件,自身具备读写的方法,自身能够读写文件。
*操作基本数据类型的流对象DataInputStream和DataOutputStream。
*用于操作字节数组的流对象:
ByteArrayInputStream:在构造的时候,需要接收数据源,而且数据源是一个字节数组。
ByteArrayOutputStream:在构造的时候,不用定义数据目的地,因为该对象中已经内部封装了可变长度的字节数组。这就是数据的目的地。
因为这两个流对象操作的都是数组,并没有使用系统底层资源,所以不用进行close关闭。即使关闭了,它仍然可以被调用,因此关闭时无效的。
*操作字符数组的流,CharArrayReader和CharArrayWrite。
*操作字符串的流,StringReader和StringWriter。
12、码表简述
常见的编码表:ASCII、ISO8859-1、GB2312、GBK、Unicode、UTF-8。
中文编码为GB2312、GBK。GBK是GB2312的升级版。
国际通用UTF-8。
使用什么编码写入,就用什么编码读出,否则会乱码。
不同的编码表,其编码特点不一样,比如GBK两个字节代码一个字符,且每个字节的第一个位为1,所以都为负数。而utf-8码表有自己的标识头:0开始表示读一个字节;110开始表示读两个字节:110...,10...,;1110表示度三个字节才查表:1110..,10..,10..
有趣现象--联通
当使用记事本存储时,开头为“联通”二字存入时,保存后再打开发现乱码。
原因是,联通二字很奇怪,使用GBK编码时,其字节数字正好符合了utf-8的编码的标识头!记事本会自动将该文件按照utf-8编码保存,所以导致解码错误。
解决办法:只需要文件开头时变成其他汉字,不然“联通”二字在前面就行了。
13、练习
需求:
有五个学生,没个完学生有3门课的成绩,从键盘输入以上数据(包括姓名,三门课成绩),
输入的格式:如:张三,30,40,60 并计算出总成绩。
最后把学生的信息和计算出的总分数按高低顺序存放在磁盘文件“stud.txt”中。
思路:
*描述学生对象。
*定义一个可操作学生对象的工具类。
步骤:
1、通过键盘录入一行数据,并将该行中的信息取出封装成学生对象。
2、因为学生有很多,那么就需要存储,使用到集合,又因为要对学生的总分排序,所以可以使用TreeSet集合。
3、将集合的信息写入到一个文件中。
代码示例:
三、一些注意事项
1、流使用完毕一定要关闭资源。
2、IO流的异常处理try{}catch(){}finally{},关闭资源要放在finally中。
3、记住“”中写目录时,\分隔符要注意转义了,需要写两个:\\。
4、OutputStream中write(byte);方法读的是字节,注意是字节。有时读取文字时是字符型的,需要转换成字节型的,如“abcf”.getBytes();
5、读取时有可能读取的第一个字节(八位)是-1的补码,当自动提升为int型时,还是-1,造成假的结束判断条件,所以需要将提升为int型的字节&255,只取提升之前的后八位。
6、字节流中int available()方法,返回的是操作文件中的字符数,包括回车符\r\n也计算在内,因此可以定义一个刚刚好的缓冲区:
int num = fis.available();byte[] buf = newbyte(num);
但是,很有可能在读取一个很大的文件时,容易超出容量,造成内存溢出。
所以还是建议定义的缓冲数组,大小设定为1024,这是比较折中的方法,好使。
------------------------------------
android培训、java培训、期待与您交流! ----------------------------------
10、IO流--Properties简述
properties 是hashtable的子类,它具备Map集合的特点,而且它里面存储的键值对都是字符串。它是集合和IO技术相结合的集合容器。
该对象的特点:可以用于键值对形式的配置文件。那么在加载数据时,需要数据有固定格式:键=值。
Properties设置和获取元素:
Object setProperty(String key,Stringvalue);//设置键值对 StringgetProperty(String key);//获取键为key的属性 Properties的load方法,load方法是1.6版本之后才有的,将流中的数据加载到Properties集合中:p.load(字节或者字符流);
Properties其他方法:
void list(PrintStream out);//将属性列表输出到指定的输出流,比如:void list(System.out);//输出到控制台 setProperty(””,””)方法改变的是内存的信息,并没有将配置文件的信息修改,要想也将文件中的配置信息也修改,需要使用方法store(OutputStream out, String cements);//第二个参数是注释,加载到文件的最上面,带#号,配置信息中带#号的默认是注释,默认不会加载。先声明一个输出流与该配置文件相关联,然后用store方法将参数流写进去。
Properties练习:记录应用程序运行次数,如果使用次数已到,那么给出注册提示。代码示例:
/* Properties练习 1、用于记录应用程序运行次数 如果使用次数已到,那么给出注册提示 首先要获取配置文件中的计数信息 然后判断,到次数就提示需要注册 */ //注意第一次编写如果有错误,一定要把上一次运行时产生的file对象删除,以免影响修改后代码的结果。!! public static void countTime()throwsIOException { Properties prop = newProperties(); File file = newFile("count.properties"); if(!file.exists())//如果该文件不存在就创建一个,存在则不用创建 file.createNewFile(); FileInputStream fis = newFileInputStream(file); prop.load(fis); String value =prop.getProperty("time");//获取键值为time的信息 int c = 0;//定义一个记数器 if(value != null)//如果值不为空,则取出这个值并加1, { c =Integer.parseInt(value); if(c>=5)//到达上限次数,程序停止运行,且提示注册信息 { System.out.println("免费体验次数已到,请注册后方能使用"); return ; } } c++;//如果取出的值为空,则为零加1, prop.setProperty("time",c+"");//将自增后的值存入原配置文件中 prop.store(newFileOutputStream(file),""); System.out.println("正常运行"); }
11、其他流
*打印流:PrintStream和PrintWriter
*合并流(序列流): SequenceInputStream
*对象的序列化:ObjectOutputStream/ObjectInputStream
ObjectOutputStream,可以将对象由堆内存存储到文件中,实现了对象由内存搬运到硬盘中,被称为对象的持久化存储。
由ObjectOutputStream存储,必须要由ObjectInputStream读取,二者成对出现。
要被持久化存储的对象必须实现Serializable接口,才能被序列化。Serializable接口中没有方法,但是会给该类生成的对象产生一个uid,序列号。序列号是由该对象的成员决定的,所以当成员发生变化时,如变成私有化,再生成的对象,其序列化也会发生变化,当你按之前的序列号读取时会发生notfound异常。
*管道流PipedInputStream PipedOutputStream,写入流(输出流)写入到管道中,输入流直接从管道中将数据读取,不需要中间的文件中转。
* RandomAccessFile随机访问文件,自身具备读写的方法,自身能够读写文件。
*操作基本数据类型的流对象DataInputStream和DataOutputStream。
*用于操作字节数组的流对象:
ByteArrayInputStream:在构造的时候,需要接收数据源,而且数据源是一个字节数组。
ByteArrayOutputStream:在构造的时候,不用定义数据目的地,因为该对象中已经内部封装了可变长度的字节数组。这就是数据的目的地。
因为这两个流对象操作的都是数组,并没有使用系统底层资源,所以不用进行close关闭。即使关闭了,它仍然可以被调用,因此关闭时无效的。
*操作字符数组的流,CharArrayReader和CharArrayWrite。
*操作字符串的流,StringReader和StringWriter。
12、码表简述
常见的编码表:ASCII、ISO8859-1、GB2312、GBK、Unicode、UTF-8。
中文编码为GB2312、GBK。GBK是GB2312的升级版。
国际通用UTF-8。
使用什么编码写入,就用什么编码读出,否则会乱码。
不同的编码表,其编码特点不一样,比如GBK两个字节代码一个字符,且每个字节的第一个位为1,所以都为负数。而utf-8码表有自己的标识头:0开始表示读一个字节;110开始表示读两个字节:110...,10...,;1110表示度三个字节才查表:1110..,10..,10..
有趣现象--联通
当使用记事本存储时,开头为“联通”二字存入时,保存后再打开发现乱码。
原因是,联通二字很奇怪,使用GBK编码时,其字节数字正好符合了utf-8的编码的标识头!记事本会自动将该文件按照utf-8编码保存,所以导致解码错误。
解决办法:只需要文件开头时变成其他汉字,不然“联通”二字在前面就行了。
13、练习
需求:
有五个学生,没个完学生有3门课的成绩,从键盘输入以上数据(包括姓名,三门课成绩),
输入的格式:如:张三,30,40,60 并计算出总成绩。
最后把学生的信息和计算出的总分数按高低顺序存放在磁盘文件“stud.txt”中。
思路:
*描述学生对象。
*定义一个可操作学生对象的工具类。
步骤:
1、通过键盘录入一行数据,并将该行中的信息取出封装成学生对象。
2、因为学生有很多,那么就需要存储,使用到集合,又因为要对学生的总分排序,所以可以使用TreeSet集合。
3、将集合的信息写入到一个文件中。
代码示例:
class Test21_9 { public static void main(String[]args)throws IOException { Set<Student> s =StudentTool.getStu(); StudentTool.storeStu(s); } } //一个学生类,需要继承Comparable接口,因为要存储到TreeSet集合中,要有自己的自然排序 class Studentimplements Comparable<Student> { private String name; private double cn;//这里如果使用int型的会比较方便些 private double ma; private double en; private double sum; Student(String name,double cn,doublema,double en) { this.name = name; this.cn = cn; this.ma = ma; this.en = en; sum = cn+ma+en; } public int compareTo(Student s) { int num = newDouble(this.sum).compareTo(new Double(s.sum)); if(num == 0) { returnthis.name.compareTo(s.name); } return num; } //由于该对象存入的是Set的子集集合,所以为了保证集合元素的唯一性,需要重写hashCode和equals方法。 //先比较hashCode方法的值,如果相等还会比较equals方法的值 public int hashCode() { return name.hashCode() + ((newDouble(sum)).hashCode()*24); } public boolean equals(Object obj) { if(!(obj instanceof Student)) throw new ClassCastException("不是Student的对象"); Student s = (Student)obj; return this.name.equals(s.name)&&(newDouble(this.cn)).equals(s.cn)&&(newDouble(this.ma)).equals(s.ma)&&(new Double(this.en)).equals(s.en); } public String toString() { returnthis.name+","+this.cn+","+this.ma+this.en+" "+this.sum; } public double getSum() { return this.sum; } public String getName() { return this.name; } } //定义一个操作学生对象的工具类 class StudentTool { public static Set<Student>getStu()throws IOException { Set<Student> set = newTreeSet<Student>(); BufferedReader bfr = new BufferedReader(newInputStreamReader(System.in)); String line = null; while((line =bfr.readLine())!=null) { if(line.equals("over")) { break; } String[] arr =line.split(","); Student s = newStudent(arr[0],Double.parseDouble(arr[1]),Double.parseDouble(arr[2]),Double.parseDouble(arr[3])); set.add(s); } bfr.close(); return set; } public static voidstoreStu(Set<Student> set)throws IOException { BufferedWriter bfw = newBufferedWriter(new FileWriter("Stu.txt")); for(Student stu:set) { bfw.write(stu.toString()+"\t"); //bfw.write(stu.getSum()+"\t"); bfw.newLine(); bfw.flush(); } bfw.close(); } }
三、一些注意事项
1、流使用完毕一定要关闭资源。
2、IO流的异常处理try{}catch(){}finally{},关闭资源要放在finally中。
3、记住“”中写目录时,\分隔符要注意转义了,需要写两个:\\。
4、OutputStream中write(byte);方法读的是字节,注意是字节。有时读取文字时是字符型的,需要转换成字节型的,如“abcf”.getBytes();
5、读取时有可能读取的第一个字节(八位)是-1的补码,当自动提升为int型时,还是-1,造成假的结束判断条件,所以需要将提升为int型的字节&255,只取提升之前的后八位。
6、字节流中int available()方法,返回的是操作文件中的字符数,包括回车符\r\n也计算在内,因此可以定义一个刚刚好的缓冲区:
int num = fis.available();byte[] buf = newbyte(num);
但是,很有可能在读取一个很大的文件时,容易超出容量,造成内存溢出。
所以还是建议定义的缓冲数组,大小设定为1024,这是比较折中的方法,好使。
相关文章推荐
- 黑马程序员--Java基础之IO流(1)
- 一个IT屌丝的职业分享
- 高效程序员的45个习惯
- 黑马程序员--Java基础之异常Exception
- 小于等于n的正整数相加等于m的一个算法
- 黑马程序员_客户端提交数据方式
- 黑马程序员_页面生命周期
- 黑马程序员--Java基础加强(7)-----代理和AOP(面向方面编程)
- 黑马程序员--基础加强(6)--- 类加载器
- 黑马程序员--Java基础加强(5)-- 泛型
- 成为优秀程序员的方法就是抛开编程?
- 成为优秀程序员的方法就是抛开编程?
- 黑马程序员--Java基础加强(3)--反射
- 面试:两种include区别
- 陶哲轩(Terence Tao)对从事数学职业的建议
- 近期面试题整理
- 近期面试题整理
- Java程序员应该知道的10个面向对象理论
- 设计模式之——模版方法模式
- 剑指Offer:面试题01---赋值运算符函数