Java基础<十二>_IO流(下)

来源:互联网 发布:骨性龅牙手术费知乎 编辑:程序博客网 时间:2024/04/29 13:25

IO流(下)

五、File类

    流操作的是数据,而数据最常见的体现形式就是文件,而文件又包含大量的属性信息,并且文件的对象非常多,所以java语言对文件进行了描述,即File类。

    流只能操作文件,不能操作文件夹;File类将文件或者文件夹封装成对象,方便对于文件或文件夹属性信息进行操作,并且File对象可以作为参数传递给流的构造函数,使用非常方便。

    File类常见的方法:

    1、创建:

    boolean  createNewFile():在指定位置创建文件,已存在则不创建,返回false,输出流对象一建立就创建文件,并且文件存在则覆盖。

    boolean  mkdir():创建文件夹;

    boolean  mkdirs():创建多级文件夹。

    2、删除:

    boolean  delete():删除失败返回false;

    void  deleteOnExit():在程序退出时删除指定文件。

    3、判断:

    boolean  exists():文件是否存在;注意:在操作之前必须判断文件是否存在;

    boolean  isFile():是否是文件;

    boolean  isDirectory():是否是目录;

    boolean  isHidden():是否隐藏;

    boolean  isAbsolute():是否是绝对路径;

    4、获取信息:

    getName():获取名称;

    getPath():获取路径;

    getParent():获取父目录;

    getAbsolutePath():获取绝对路径;

    long  length():获取长度;

    listRoots():根目录;

    list():获取文件列表;调用该方法之前,必须保证file对象封装了一个目录,存在;

    递归:函数自己调用自己,称为递归;递归注意:1、限定条件,2、递归次数不能过大,避免内存溢出。

下面代码体现:

1、File类常用方法的简单演示:

1.1:

package itheima.day20;import java.io.File;import java.io.IOException;public class FileDemo {public static void main(String[] args) {//consMethod();//method_1();//method_3();method_4();}//2、创建public static void method_1(){File f = new File("file.txt");try {sop("create:"+f.createNewFile());} catch (IOException e) {throw new RuntimeException("文件创建异常!");}//删除,删除失败,返回falsesop("delete::"+f.delete());//在程序退出时删除指定文件f.deleteOnExit();}//判断public static void method_2(){File f = new File("file2.txt");try {f.createNewFile();} catch (IOException e) {e.printStackTrace();}//判断文件是否可执行sop("canExcute:"+f.canExecute());sop("exists:"+f.exists());File dir  = new File("abc\\aa\\bb\\cc\\dd\\ee");//创建文件夹,多层目录sop("mkdirs:"+dir.mkdirs());}public static void method_3(){//只是封装成一个文件对象而已,未创建File f = new File("file3.txt");//对一个File对象判断是文件或者目录之前,必须判断它是否存在sop("exist"+f.exists());sop("dir:"+f.isDirectory());sop("File:"+f.isFile());}//获取public static void method_4(){File f = new File("abc\\a.txt");//获取封装的路径sop("path:"+f.getPath());//获取绝对路径sop("abspath:"+f.getAbsolutePath());//获取父目录sop("parent:"+f.getParent());}public static void method_5(){File f1= new File("c:\\Test.java");File f2= new File("c:\\hahaha.java");//剪切sop("rename:"+f1.renameTo(f2));}//1、创建File对象public static void consMethod(){//将a.txt封装成为对象,可以将已有的和未出现的文件或者文件夹封装成为对象File f1 = new File("ss.txt");//File.separator:与系统有关的分隔符;父目录+文件名File f2 = new File("c:"+File.separator+"abc","b.txt");//把目录封装成为FileFile d = new File("c:"+File.separator+"abc");File f3 = new File(d,"c.txt");sop("f1:::"+f1);sop("f2:::"+f2);sop("f3:::"+f3);}public static void sop(Object obj){System.out.println(obj);}}
1.2:
package itheima.day20;import java.io.File;import java.io.FilenameFilter;public class FileDemo2 {public static void main(String[] args) {//listRootsDemo();//listDemo();listDemo_3();//listDemo_2();}public static void listRootsDemo(){//C:\;D:\;E:\;F:\;G:\ 机器里面的有效盘符File[] files = File.listRoots();for(File f:files){System.out.println(f);}}public static void listDemo(){File f = new File("c:\\");//获取目录的列表,包含隐藏文件String[] names = f.list();for(String name:names){System.out.println(name);}}public static void listDemo_2(){File dir = new File("c:\\");String [] arr = dir.list(new FilenameFilter(){//文件名过滤器@Overridepublic boolean accept(File dir, String name) {return name.endsWith(".txt");}});for(String name:arr){System.out.println(name);}}public static void listDemo_3(){File dir = new File("c:\\");//文件列表File[] files = dir.listFiles();for(File f:files){System.out.println(f.getName()+"::::"+f.length());}}}

2、列出指定目录下文件或者文件夹,包含目录中的内容:

package itheima.day20;import java.io.File;//列出指定目录下文件或者文件夹,包含目录中的内容//也就是列出指定目录下所有内容public class FileDemo3 {public static void main(String[] args) {File dir = new File("D:\\java\\workspace1\\JavaFoundation");showDir(dir,0);}public static void showDir(File dir,int level){System.out.println(getLevel(level)+dir.getName());level++;File[] files = dir.listFiles();for(int x =0;x<files.length;x++){if(files[x].isDirectory())showDir(files[x],level);elseSystem.out.println(getLevel(level)+files[x]);}}public static String getLevel(int level){StringBuilder sb = new StringBuilder();sb.append("|--");for(int x =0; x<level;x++){//sb.append("|--");sb.insert(0, "|  ");}return sb.toString();}}

3、删除一个带内容的目录:

package itheima.day20;import java.io.File;//删除一个带内容的目录// 删除原理:从里往外删public class RemoveDir {public static void main(String[] args) {File dir = new File("d:\\Test");removeDir(dir);}public static void removeDir(File dir){File[] files = dir.listFiles();for(int x=0;x<files.length;x++){if(files[x].isDirectory()/* && !files[x].isHidden()*/)removeDir(files[x]);elseSystem.out.println(files[x].toString()+"----"+files[x].delete());}System.out.println(dir+"::dir::"+dir.delete());}}

4、将一个指定目录下的java文件的绝对路径,存储到一个文本文件中:

package itheima.day20;import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.util.ArrayList;import java.util.Iterator;import java.util.List;/*将一个指定目录下的java文件的绝对路径,存储到一个文本文件中, * 建立一个java文件列表文件。 * 思路:1、对指定的目录进行递归; * 2、获取递归过程中的java文件路径 * 3、将这些路径存储到集合中 * 4、将集合中的数据写入到一个文件中。 * */public class JavaFileList {public static void main(String[] args) {File dir = new File("d:\\java\\workspace1\\Test");List<File> list = new ArrayList<File>();fileToList(dir,list);File file = new File("javalist.txt");writeToFile(list,file.toString());Iterator<File> it = list.iterator();while(it.hasNext()){System.out.println(it.next());}}public static void fileToList(File dir,List<File> list){File[] files = dir.listFiles();for(File file:files){if(file.isDirectory())fileToList(file,list);else{if(file.getName().endsWith(".java"))list.add(file);}}}public static void writeToFile(List<File> list, String javaListFile){BufferedWriter bufw = null;try {bufw = new BufferedWriter(new FileWriter(javaListFile));for(File f:list){String path = f.getAbsolutePath();bufw.write(path);bufw.newLine();bufw.flush();}} catch (IOException e) {throw new RuntimeException("IO读写异常!");}finally{try {if(bufw!=null)bufw.close();} catch (IOException e) {throw new RuntimeException("文件关闭异常!");}}}}

六、Properties类:

    Properties是hashtable的子类,它具备map集合的特点,并且它里面存储的键值对都是字符串的形式;Properties是集合中和IO技术相结合的容器,该类对象的特点:可以用来存储键值对形式的配置文件,那么加载数据时,需要数据有固定的格式,键=值。

5.0:properties类常用方法的演示:

package itheima.day20;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.FileReader;import java.io.IOException;import java.util.Properties;import java.util.Set;public class PropertiesDemo {public static void main(String[] args) {//setAndGet();method_1();//loadDemo();}public static void loadDemo(){Properties prop = new Properties();try {FileInputStream fis = new FileInputStream("info.txt");prop.load(fis);//System.out.println(prop);//调用Hashtable中的put方法,改变Property中的属性prop.setProperty("wangwu", "15");FileOutputStream fos = new FileOutputStream("info.txt");//存到一个流中,然后存到文件中,持久化prop.store(fos, "heihei");//注释prop.list(System.out);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}//演示如何将流中的数据存储到集合中,想要将info.txt中键值数据存到集合中进行操作。//思路:1、用一个流和info.txt文件关联//  2、读取一行数据,将该行数据用"="进行切割//  3、等号左边作为建,右边作为值,存入到Properties中public static void method_1(){BufferedReader bufr = null;try {bufr = new BufferedReader(new FileReader("info.txt"));String line = null;Properties prop = new Properties();while((line = bufr.readLine())!=null){//System.out.println(line);String[] arr = line.split("=");prop.setProperty(arr[0], arr[1]);}System.out.println(prop);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally{try {if(bufr!=null)bufr.close();} catch (IOException e) {e.printStackTrace();}}}//设置和获取元素public static void setAndGet(){Properties prop = new Properties();//底层调用的是Hashtable的put方法prop.setProperty("zhangsan1", "30");prop.setProperty("zhangsan2", "20");//把map转成Set,再取Set<String> names= prop.stringPropertyNames();for(String s: names){System.out.println(s+":"+prop.getProperty(s));}}}

5、写一个试用软件,如果使用次数已到,那么给出注册提示:

package itheima.day20;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.Properties;//用于记录应用程序运行次数,// 如果使用次数已到,那么给出注册提示//配置文件可以实现应用程序数据的共享public class RunCount {public static void main(String[] args)throws IOException {Properties prop = new Properties();File file = new File("count.ini");//文件不存在,则创建if(!file.exists())file.createNewFile();FileInputStream fis = new FileInputStream(file);//properties与输入流相关联prop.load(fis);    int count = 0;//获取time属性的值String value = prop.getProperty("time");if(value !=null){//将值的字符串形式转成Integercount = Integer.parseInt(value);if(count>5){throw new RuntimeException("哥们,您老人家的大寿已尽,请交钱!!!");}}count++;prop.setProperty("time", count+"");FileOutputStream fos = new FileOutputStream(file);//把properties对象与输出流相关联,存储到指定文件中prop.store(fos, "money");fos.close();fis.close();}}

七、IO中的其他类

    7.1、序列流:SequenceInputStream:用于对多个流进行合并。

6、合并3个输入流为一个输入流:

package itheima.day20;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.Enumeration;import java.util.Vector;//将多个流对象合并成一个流对象public class SequenceDemo {public static void main(String[] args) throws IOException {Vector<FileInputStream> v = new Vector<FileInputStream>();v.add(new FileInputStream("1.txt"));v.add(new FileInputStream("2.txt"));v.add(new FileInputStream("3.txt"));Enumeration<FileInputStream> en = v.elements();//该对象是JDK1.0时出现,合并流对象,输入流SequenceInputStream sis = new SequenceInputStream(en);FileOutputStream fos = new FileOutputStream("4.txt");byte[] buf = new byte[1024];int len =0;while((len = sis.read(buf)) != -1){fos.write(buf,0,len);}fos.close();sis.close();}}

7、切割一个mp3文件:

package itheima.day20;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.ArrayList;import java.util.Enumeration;import java.util.Iterator;//切割文件public class SplitFileDemo {public static void main(String[] args) throws IOException {splitFile();merge();}//切割public static void splitFile() throws IOException{FileInputStream fis = new FileInputStream("1.mp3");FileOutputStream fos = null;byte[] buf = new byte[1024*1024];int len = 0;int count =1;while((len = fis.read(buf)) != -1){//产生一个文件fos = new FileOutputStream((count++)+".part");fos.write(buf,0,len);fos.close();}fis.close();}//合并文件public static void merge() throws IOException{//把这些流对象存到一个ArrayList集合中ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();for(int i=1;i<6;i++){al.add(new FileInputStream(i+".part"));}final Iterator<FileInputStream> it = al.iterator();//匿名内部类,不能访问外部类的局部变量Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){@Overridepublic boolean hasMoreElements() {return it.hasNext();}@Overridepublic FileInputStream nextElement() {return it.next();}};//构造函数为一个Enumeration对象,合并这些流SequenceInputStream sis = new SequenceInputStream(en);FileOutputStream fos = new FileOutputStream("2.mp3");byte[] buf = new byte[1024];int len =0; while((len =sis.read(buf))!=-1){ fos.write(buf, 0, len); fos.flush(); } fos.close(); sis.close();}}

    7.2、管道流:PipedInputStream和PipedOutputStream:可以合并两个流,涉及到多线程。

8、演示管道流:

package itheima.day21;import java.io.IOException;import java.io.PipedInputStream;import java.io.PipedOutputStream;//管道流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 in){this.in = in;}@Overridepublic void run() {byte[] buf = new byte[1024];try {int len = in.read(buf);String s = new String(buf,0,len);System.out.println(s);in.close();} catch (IOException e) {e.printStackTrace();}}}//写出的任务,封装到一个线程中class Write implements Runnable{private PipedOutputStream out;Write(PipedOutputStream out){this.out = out;}@Overridepublic void run() {try {out.write("lai le ,ge men ,heihei ".getBytes());} catch (IOException e) {e.printStackTrace();}}}

    7.3、RandomAccessFile:随机访问,自身具备读写方法,通过skipBytes(int x)和seek(int x)来实现随机访问。

    7.4、PrintWriter和PrintStream:可以直接转换输入流和文件。

代码演示:

package itheima.day20;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;//凡是与流对象相关联的对象,都是比较重要的流对象//打印流:该流提供了打印方法,可以将各种数据类型的数据都原样打印//字节打印流:PrintStream//构造函数可以接收的参数类型://1、file对象  File//2、字符串路径  String//3、字节输出流 OutputStream//字符打印流 PrintWriter//构造函数可以接收的类型://1、file对象  File//2、字符串路径  String//3、字节输出流 OutputStream//4、字符输出流 Writerpublic class PrintStreamDemo {public static void main(String[] args) throws IOException {//字节流转换成字符流,并加入缓冲区技术BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//通用性极强,指定打印目的。并自动刷新,对write方法无效PrintWriter  out = new PrintWriter(System.out,true);String line = null;while((line = bufr.readLine())!=null){if("over".equalsIgnoreCase(line))break;out.println(line.toUpperCase());//out.write(line.toUpperCase());}out.close();bufr.close();}}

    7.5、ObjectInputStream和ObjectOutputStream:操作对象,但被操作的对象需要实现Serializable接口(一个标记接口,没有要覆盖的方法)。

代码演示:

package itheima.day21;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;//直接操作对象的流public class ObjectInputStreamDemo {public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {writeObj();readObj();}//将对内存中的对象存到硬盘上public static void writeObj() throws FileNotFoundException, IOException{//必须关联一个输出流ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.obj"));oos.writeObject(new Person("lisi",45));oos.close();}//读取硬盘上存储的对象public static void readObj() throws FileNotFoundException, IOException, ClassNotFoundException{//必须关联一个输入流ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.obj"));Person p = (Person)ois.readObject();System.out.println(p);ois.close();}}class Person implements Serializable{//序列号是根据成员变量构造出来的static final long serialVersionUID = 42L;//可以自己指定一个ID号private String name;private int age;//transient 不序列化static public String country = "cn";//静态不能序列化,序列化只能是堆内存中的数据Person(String name,int age ){this.name = name;this.age  = age;}public String toString(){return name+"::"+age+":::"+country;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}

    7.6、DataInputStream和DataOutputStream:操作基本数据类型。

    7.7、ByteArrayInputStream与ByteArrayOutputStream:操作字节数组;

         CharArrayReader与CharArrayWriter :操作字符数组;

                   StringReader 与 StringWriter:操作字符串;

八、字符编码

    字符流的出现是为了方便操作字符,字符流 = 字节流+编码;字符流是先获取到一定的字节,然后通过查阅相应的编码表,变成相应的字符,其实计算机中存储的是二进制形式的字节码。

    InputStreamReader、OutputStreamWriter这两个转换流在字符流与字节流的转换时,可以指定特定的编码表,指定编码表的动作可以由构造函数完成,详情可以查阅API ,(UnsupportedEncodingException)。

    编码表:计算机只能识别二进制数据,早期由来是电信号,为了方法计算机的使用,让它识别不同国家的文字,那么将各个国家的文字用特定的数字在计算机中表示,并一一对应,形成了一张映射表,这张现实生活中的文字与计算机中二进制数据一一对应的映射表,称为编码表。

    常见编码表:

    1、ASCII:美国标准信息交换码,用一个字节的7位表示;

    2、ISO8859-1:拉丁码表,欧洲码表;用一个字节的8位表示;

    3、GBK2312:中国的中文编码表;

    4、GBK:中国的中文编码升级版,融合了更多的中文文字符号,两个字节表示;

    5、Unicode:国际标准码,融合了多种文字,两个字节表示;

    6、UTF-8:可以理解为Unicode的优化版,最多用三个字节表示一个字符。

    编码:字符串-->字节数组:String-->byte[]  s.getBytes(charsetName);

    解码:字节数组-->字符串:Byte[]-->String  new String(byte[],charsetName);

    当发生乱码时,可以先解码,然后再重新编码即可。例如:将一个中文用gbk编码,用iso8859-1解码,乱码;解决方式:对乱码进行iso8859-1编码,再用gbk解码即可。

    但:用gbk编码,用utf-8解码,乱码,再用utf-8编码,用gbk解码还是乱码。这是因为:用gbk编码后的数字去查utf-8的码表时utf-8不识别,就直接用一个未知字符来表示,而这个未知字符是3个字节的;原数字码已经变化了,所以还原不回来,乱码。

9、编码演示1:

package itheima.day21;import java.io.UnsupportedEncodingException;import java.util.Arrays;public class EncodeDemo {public static void main(String[] args) throws UnsupportedEncodingException {String s = "你好";byte[] b1 = s.getBytes("GBK");System.out.println(Arrays.toString(b1));//[-60, -29, -70, -61]String s1 = new String(b1,"GBK");System.out.println("s1 = "+s1);//s1 = 你好byte[] b2 = s.getBytes("UTF-8");System.out.println(Arrays.toString(b2));//[-28, -67, -96, -27, -91, -67]String s2 = new String(b2,"UTF-8");System.out.println("s2 = "+s2);//s2 = 你好//”联通“的GBK编码正好符合了UTF-8的解码形式String ss = "联通";//u8加有自己的标识头byte[] by = ss.getBytes("gbk");for(byte b:by){System.out.println(Integer.toBinaryString(b&255));}}}

10、编码演示2:

package itheima.day21;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.UnsupportedEncodingException;public class EncodeStream {public static void main(String[] args) throws IOException {writeText();readText();}public static void writeText() throws IOException{//转换流可以指定编码表OutputStreamWriter osw =new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");osw.write("你好");osw.close();}public static void readText() throws IOException{InputStreamReader isr = new InputStreamReader(new FileInputStream("utf.txt"),"GBK");char[] buf = new char[10];int len = isr.read(buf);String str = new String(buf,0,len);System.out.println(str);isr.close();}}

11、综合练习一枚:

package itheima.day21;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.util.Collections;import java.util.Comparator;import java.util.Set;import java.util.TreeSet;/*有五个学生,每个学生有3们课的成绩,从键盘输入以上数据(姓名,成绩) * 输入格式:zs,56,48,59计算出总成绩 * 并把学生的信息和计算出的总分按高低顺序存放在磁盘文件"stud.txt"中。 * *//*1、描述学生对象 * 2、定义一个可操作学生对象的工具类 * 思想: * 1、通过获取键盘录入一行数据,并将该行中的信息取出封装成为学生对象 * 2、因为学生有很多,那么就需要存储,使用集合,要排序,TreeSet * 3、将集合中的信息写入到一个文件中 * */public class StudentInfoTest {public static void main(String[] args) throws IOException {Comparator<Student> cmp = Collections.reverseOrder();Set<Student> stus = StudentInfoTool.getStudents(cmp);StudentInfoTool.write2File(stus);}}class Student implements Comparable<Student>{private String name;private int math,chinese,english;private int sum;Student(String name,int math,int chinese,int english){this.name = name;this.math = math;this.chinese = chinese;this.english = english;this.sum = math+chinese+english;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getSum() {return sum;}public void setSum(int sum) {this.sum = sum;}@Overridepublic int hashCode() {return name.hashCode()+sum*23;}@Overridepublic boolean equals(Object obj) {if(!(obj instanceof Student))throw new ClassCastException("类型不匹配异常");Student stu = (Student)obj;return this.name.equals(stu.name) && (this.sum == stu.sum);}@Overridepublic String toString() {return "Student [name=" + name + ", math=" + math + ", chinese="+ chinese + ", english=" + english + ", sum=" + sum + "]";}@Overridepublic int compareTo(Student o) {int  num = this.sum - o.sum;if(num==0)return this.name.compareTo(o.name);return num;}}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>();elsestus =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("student.txt"));for(Student stu:stus){bufw.write(stu.toString());bufw.newLine();bufw.flush();}bufw.close();}}