- Unicode无论什么字符都要用两个字节,UTF-8按需要分配空间。
- IO体系的四个抽象基类,InputStream,OutputStream,Reader,Writer。由这四个类派生出来的子类都以其父类名作为子类名的后缀。
- FileWriter对象一被初始化即必须明确要操作的文件。而且该文件会被创建到指定的目录下,如果同名文件已存在,将会被覆盖
- 缓冲区的出现是为了提高流的操作效率,所以在创建缓冲区之前,必须要先有流对象。关闭缓冲区就是在关闭缓冲区中的流对象。BufferedWriter缓冲区提供了一个换行的方法,newLine
--------------------------------------------------------------------------------------------------装饰设计模式---------------------------------------------------------------------------------------------------------
当想要对已有的对象进行功能增强时,可以定义类,将已有的对象传入,基于已有的功能,并提供加强功能。那么自定义的该类就被称为装饰类。例如BufferedWriter。 装饰类通常会通过构造函数接收被装饰的对象。
装饰模式比继承灵活,避免了体系臃肿,降低了类之间的关系。装饰类因为是增强已有对象,具备的功能和已有的功能是相同的,只不过提供了更强的功能。所以装饰类和被装饰类通常都是同属于一个类。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- 用InputStreamReader将字节流转换为字符流使用readLine方法。使用OutputStreamWriter将字符流转换为字节流。
import java.io.*; public class TransStreamDemo { public static void main(String[] args)throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); String str; while((str=br.readLine())!=null) { if(str.equals("over")) break; bw.write(str); bw.newLine(); bw.flush(); } br.close(); } }
- 流操作的基本规律:
1.明确源和目的。
源:InputStream Reader
目的:OutputStream Writer
2.操作的数据是否为纯文本。
是:字符流
否:字节流
3.当体系明确后,再明确要使用具体哪个对象,通过设备来区分。
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台 -
File类用来将文件或文件夹封装成对象
用来对文件和文件夹进行操作
File对象可以作为参数传递给流的构造函数
注意一般不要访问隐藏文件
- 删除一个带内容的目录。删除原理,从里往外删除,用递归。java删除的文件不会进入回收站。
import java.io.*; public class FileDemo { public static void main(String[] args)throws Exception { File file = new File("d:/新建文本文档.txt"); removeDir(file); } public static void removeDir(File dir) { File[] files = dir.listFiles(); if(files != null) for(File file:files) { if(file.isDirectory()) removeDir(file); else file.delete(); } dir.delete(); } }
- Properties是hashtable的子类,也就是说它具备map集合的特点,而且它存储的键值对都是字符串,是集合与IO技术相结合的集合容器。该对象的特点:可以用于键值对形式的配置文件。
import java.io.*; import java.util.*; public class PropertiesDemo { public static void main(String[] args)throws IOException { loadDemo(); } public static void setAndGet() { Properties prop = new Properties(); prop.setProperty("zhangsan", "30"); prop.setProperty("lisi", "39"); String str = prop.getProperty("lisi"); System.out.println(str); Set<String> names = prop.stringPropertyNames(); for(String s:names) System.out.println(s + ":" + prop.getProperty(s)); } public static void loadDemo()throws IOException { Properties prop = new Properties(); prop.setProperty("wangwu", "32"); FileOutputStream fos = new FileOutputStream("D:/info.txt"); prop.store(fos, ""); FileInputStream fis = new FileInputStream("D:/info.txt"); prop.load(fis); System.out.println(prop); } }
试用软件次数Demo
import java.io.*; import java.util.*; public class PropertiesDemo { public static void main(String[] args)throws IOException { Properties prop = new Properties(); File file = new File("D:/info.properties"); if(!file.exists()) file.createNewFile(); FileInputStream fis = new FileInputStream(file); prop.load(fis); String value = prop.getProperty("count"); int count = 0; if(value!=null) count = Integer.parseInt(value); if(count == 0) System.out.println("试运行次数已到,请购买正版!"); else { count --; prop.setProperty("count", new Integer(count).toString()); FileOutputStream fos = new FileOutputStream(file); prop.store(fos, null); } } }
- 打印流提供了打印方法,可以将各种数据类型的数据都原样打印.
PrintStream构造函数可以接收的参数类型:
1.file对象
2.字符串路径
3.字节输出流。OutputStream
PrintWriter构造函数可以接收的参数类型:
1.file对象
2.字符串路径
3.字节输出流。OutputStream
4.字符输出流。Writer
import java.io.*; public class PrintDemo { public static void main(String[] args)throws Exception { BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = new PrintWriter(System.out,true); String line = null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; out.println(line); } bufr.close(); out.close(); } }
- SequenceInputStream可用于合并流
切割合并文件Demo:
import java.io.*; import java.util.*; public class SplitDemo { public static void main(String[] args)throws IOException { splitFile(); merge(); } public static void splitFile()throws IOException { FileInputStream fis = new FileInputStream("D:/39756-106.jpg"); FileOutputStream fos =null; int len = 0; int count = 1; byte[] buf = new byte[1024*20]; while((len=fis.read(buf))!=-1) { fos = new FileOutputStream("D:/"+(count++)+".part"); fos.write(buf, 0, len); fos.close(); } fis.close(); } public static void merge()throws IOException { //不用Vector是因为Vector低效 ArrayList<FileInputStream> al = new ArrayList<FileInputStream>(); for(int i = 1;i<=30;i++) { al.add(new FileInputStream("D:/"+i+".part")); } final Iterator<FileInputStream> it = al.iterator(); Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() { public boolean hasMoreElements() { return it.hasNext(); } public FileInputStream nextElement() { return it.next(); } }; SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("D:/2.jpg"); int len = 0; byte[] buf = new byte[1024]; while((len=sis.read(buf))!=-1) { fos.write(buf, 0, len); } fos.close(); sis.close(); } }
- 对象的序列化:
可以使用ObjectOutputStream 实现对对象进行IO操作,要传递的对象参数必须实现Serializable接口,该接口没有函数,只起到标记作用。类的序列号是根据类的成员变量和成员函数生成的,可以使用public static final long serialVersionUID = 4654L的形式自定义UID.静态不能被序列化,因为它不是在堆内存里的,如果非静态成员也不想被序列化吗,只要加上transient关键字即可
<pre name="code" class="java">import java.io.*; public class ObjectStreamDemo { public static void main(String[] args)throws Exception { readObj(); readObj(); } public static void writeObj()throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Person.object")); oos.writeObject(new Person("lisi",39)); oos.close(); } public static void readObj()throws Exception { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Person.object")); Person p = (Person)ois.readObject(); System.out.println(p); ois.close(); } } class Person implements Serializable { String name; int age; Person(String name,int age) { this.name = name; this.age = age; } public String toString() { return name + ":" + age; } }
对象被序列化并不能看得懂 - 管道流 PipedInputStream和PipedOutputStream不建议对这两个对象使用单独线程,可能导致死锁
import java.io.*; public class PipedStreamDemo { public static void main(String[] args)throws IOException { PipedInputStream in = new PipedInputStream(); PipedOutputStream out = new PipedOutputStream(); in.connect(out); Read r = new Read(in); Write w = new Write(out); new Thread(r).start(); new Thread(w).start(); } } class Read implements Runnable { private PipedInputStream in; Read(PipedInputStream i) { this.in = i; } public void run() { try { byte[] buf = new byte[1024]; int len = in.read(buf); String s = new String(buf,0,len); System.out.println(s); } catch(IOException e) { throw new RuntimeException("Read Error"); } } } class Write implements Runnable { private PipedOutputStream out; Write(PipedOutputStream o) { this.out = o; } public void run() { try { out.write("PipedStream Test".getBytes()); out.close(); } catch(IOException e) { throw new RuntimeException("Write Error"); } } }
- RandomAccessFile不算是IO体系中子类而是直接继承自Object。但是它是IO包中成员,因为它具备读写功能,内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获取文件指针。完成读写的原理就是内部封装了字节输入流和输出流。通过构造函数可以看出该类只能操作文件,而且有mode('r','rw','rws','rwd');。如果模式为只读r,不会创建文件,会读取一个已经存在的文件,如果该文件不存在会出现异常,如果模式为rw,该类对象的构造函数操作的文件不存在时会创建,如果存在,不会覆盖。seek方法指定指针位置,skipBytes只能往后跳不能往前跳。该类可以实现多线程下载。
- DataInputStream和DataOutputStream可以用于操作基本数据类型的流对象
- ByteArrayStream不操作底层资源,不会产生IOException,关闭无效。
- 小练习
//需求:从键盘获取学生姓名和三项成绩,按总成绩高低顺序排序,存入stuinfo.txt文件中 import java.io.*; import java.util.*; public class StudentTest { public static void main(String[] args)throws IOException { StudentInfoTool.writeToFile(StudentInfoTool.getStudent()); } } class Student implements Comparable<Student> { private String name; private int math,eng,cn; private int sum; Student(String name, int math,int eng,int cn) { this.math = math; this.cn = cn; this.eng = eng; this.name = name; } public String getName() { return name; } public int getSum() { return cn+eng+math; } public int hashCode() { return name.hashCode() + sum*78; } public boolean equlas(Object obj) { if(!(obj instanceof Student)) throw new RuntimeException("输入的不是学生"); Student s = (Student)obj; return this.name.equals(s.name); } public int compareTo(Student s) { int num = new Integer(this.sum).compareTo(s.sum); if(num == 0) return this.name.compareTo(s.name); return num; } public String toString() { return "Student["+"name:"+name+",math:"+math+",eng:"+eng+",cn:"+cn+"]"; } } class StudentInfoTool { public static Set<Student> getStudent() throws IOException { BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); Set<Student> stus = new TreeSet<Student>(); String line = null; while((line = bufr.readLine())!=null) { if(line.equals("over")) 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 writeToFile(Set<Student> stus)throws IOException { BufferedWriter bufw = new BufferedWriter(new FileWriter("stuinfo.txt")); for(Student stu : stus) { bufw.write(stu.toString()+"\t"); bufw.write(stu.getSum()+""); bufw.newLine(); bufw.flush(); } bufw.close(); } }