黑马程序员__其他对象、输入输出

day18-day21

1. System类

  • System类不能被实例化, 类中的方法和属性都是静态的
  • out标准输出 :控制台,in标准输入:键盘
  //获取系统信息
    public static void  getpro()
    {
        Properties pro = System.getProperties();
        
        for (Object obj : pro.keySet())
        {
            String str = (String)pro.get(obj);
            System.out.println(obj+"--"+str);     
        }    
    }    

2. Runtime 类

  • Runtime类没有提供构造函数,有非静态方法。 使用了单例设计模式
  • 提供了 getRuntime() 方法获取本来对象
    public static void getRun() throws Exception
    {
        Runtime rt = Runtime.getRuntime();
        Process p=null;
        try
        {
            //执行xx程序
            p = rt.exec("C:\Program Files (x86)\Tencent\QQ\Bin\QQ.exe");
            //用xx程序打开xxx文件
            p = rt.exec("notepad.exe 1.java");
        }
        catch(Exception e){ System.out.println("hah"); }
        //Thread.sleep(4000);
        //p.destroy();        
    }

3. Date类

//import java.text.*;
    public static void date()
    {
        Date d = new Date();
        System.out.println(d);
        //自定义时间模式封装到DateFormat对象中
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 E hh:mm:ss");
        //调用format方法格式Date对象 
        System.out.println(sdf.format(d));
    }

4. Calendar 类

    public static void  cal()
    {
        Calendar c = Calendar.getInstance(); //抽象类,获取实例
        
        //c.add(Calendar.YEAR,4); //按时间位 进行偏移
        //c.set(Calendar.YEAR,2013); //按时间位 设置时间
        //c.set(2011,4,1); //按year,month,day设置时间
                
        System.out.println(c.get(Calendar.YEAR));
        System.out.println(c.get(Calendar.MONTH));
        System.out.println(c.get(Calendar.DAY_OF_MONTH));
        System.out.println(c.get(Calendar.DAY_OF_WEEK));
    }

5.Math 类 lang包

  • Math类的方法都是静态的
    public static void show()
    {
        System.out.println(Math.E);
        
        //幂函数  b是指数 double pow(double a, double b) 
        System.out.println(Math.pow(3,2)); //9
        
        
        // 四舍五入 int round(float a) 
        System.out.println(Math.round(13.545)); //14
            
        
        //double ceil(double a) 返回大于等于参数的最小整数,返回double 值        
        System.out.println(Math.ceil(15.556));  
        //double ceil(double a) 返回小于等于参数的最大整数,返回double 值
        System.out.println(Math.floor(15.556));  

        //随机数 double random()  返回带正号的double值  (0.0<=x<1.0)
        System.out.println(Math.random());
        System.out.println((int) (Math.random()*100) );
    }
    

6. 输入输出流

  • java对数据的操作是通过流的方式,用于操作流的对象都在 io 包中
  • 流 按照数据分为两种: 字节流 字符流
  • 流 按照流向分为:  输入流  输出流 
  • IO流有4个常用基类 : 
  • 字节流抽象基类 :  InputStream  OutputStream  
  • 字符流抽象基类 :  Reader   Writer

FileWriter类的操作:

    public static void filewr() throws Exception
    {
        //创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件
        //而且该文件会被创建到指定目录下,如果该目录下已有同名文件,将被覆盖
        FileWriter fw = new FileWriter("demo.txt" , true);
        
        //将字符串写入到流中 
        fw.write("abvd");
        
        //刷新流对象中缓冲的数据,将数据存到目的地。
        fw.flush();
        
        //关闭流资源,关闭之前刷新一次缓冲的数据,将数据刷到目的地中
        //和flush的区别:flush刷新后,    流可以继续使用;close刷新后,将流关闭。
        fw.close();        
    }
    //传递true参数,代表续写以前存在的文件,否则覆盖以前的文件
    FileWriter fw = new FileWriter("demo.txt" , true);
    
    //Windows系统中,需要
代表换行,Linux中,
代表换行。
    fw.write("abbb
bbvd");

FileReader类的2种读取方式:

    public static void filerr()throws Exception
    {
        //创建一个文件读取流对象,和指定名称的文件关联
        //要保证文件是已经存在的,否则发生异常。
        FileReader fr = new FileReader("demo.txt");
        
        //调用读取流对象的read方法,一次读一个字符,自动往下读
        int ch1 = fr.read();
        int ch = 0;
        while((ch = fr.read())!=-1)
        {
            System.out.println((char)ch);
        }
                
        System.out.println((char)ch1);    
        fr.close();
    }
    public static void filerr2()throws Exception
    {
        FileReader fr = new FileReader("demo.txt");
        
        //定义一个字符数组,用于存储读到的字符
        //read(char[]) 返回读到的字符个数
        char[] buf = new char[64];
        int ch = 0;
        while((ch = fr.read(buf))!=-1)
        {
            System.out.println(new String(buf,0,ch));
        }
        
        fr.close();
    }

7.字符流的缓冲区  BufferedWriter  BufferedReader

  • 在字符流的基础上对流的功能进行了增强
  • 缓冲区的出现是为了提高对数据的读写效率, 创建缓冲区之前, 必须先有流对象。

BufferedWriter:

    public static void bufWr()throws Exception
    {
        //创建一个字符写入流对象
        FileWriter fw = new FileWriter("demo.txt");
    
        //将流对象作为参数传递给缓冲区的构造函数
        BufferedWriter bw = new BufferedWriter(fw);
        bw.write("absgsg");
        //缓冲区有个跨平台的换行方法
        bw.newLine();
        bw.write("absgsg");
        //只要用到缓冲区,就要记得刷新
        bw.flush();
        //关闭缓冲区,就是关闭了流对象
        bw.close();

    }

BufferedReader:

    public static void bufr()throws Exception
    {
        //创建一个字符读取流对象
        FileReader fr = new FileReader("demo.txt");
        //将流对象作为参数传递给缓冲区的构造函数
        BufferedReader br = new BufferedReader(fr);
        
        // String readLine()  读取一个文本行。 返回null时,表示读到文件末尾。 不包含行终止符
        String str = null;
        while((str = br.readLine())!=null)
        {    
            System.out.println(str);
        }
        br.close();
    }
    

8. 设计模式之: 装饰设计模式

当想要对已有对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类。

  • 装饰类通常通过构造方法接收被装饰的对象,基于对象的功能,提供更强的功能。
  • 装饰模式比继承要灵活,避免了继承体系臃肿,降低了类与类之间的关系。
  • 装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能
  • 所以装饰类和被装饰类通常都是属于一个体系的  

 9. LineNumberReader类

    public static void linenr()throws Exception
    {
        FileReader fr = new FileReader("demo.txt");
        LineNumberReader lr = new LineNumberReader(fr);
        String str = null;
        lr.setLineNumber(200);
        while((str = lr.readLine())!=null)
        {    
            System.out.println(lr.getLineNumber()+":"+str);
        }
        
        lr.close();
    }

10.  字符流  InputStream  OutputStream

    public static void outs()throws Exception
    {
        FileOutputStream fos = new FileOutputStream("2.avi");
        FileInputStream fis = new FileInputStream("1.avi");
        
        byte[] buf = new byte[1024];
        int len = 0;
        while((len=fis.read(buf))!=-1)
            fos.write(buf,0,len);
        
        fis.close();
        fos.close();    
    }
    public static void bufio()throws Exception
    {
        BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream("2.avi"));
        BufferedInputStream fis = new BufferedInputStream(new FileInputStream("1.avi"));
        
        byte[] buf = new byte[2048];
        int len = 0;
        while((len=fis.read(buf))!=-1)
            //fos.write(len);
            fos.write(buf,0,len);
        
        fis.close();
        fos.close();    
    }

11.  键盘录入:

  • readLine方法是字符流BufferedReader类中的方法
  • 键盘录入的read方法是字节流InputStream类中的方法
  • 怎样将字节流转换成字符流,再使用字符流缓冲区的readLine方法?
    public static void readin()throws Exception
    {    
        //获取键盘录入对象
        InputStream in = System.in;    
        //将字节流对象转成字符流对象,使用转换流 InputStreamReader
        InputStreamReader isr = new InputStreamReader(in) ;
        //为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader
        BufferedReader br = new BufferedReader(isr);
        String line = null;
        while((line=br.readLine())!=null)
            System.out.println(line);
    }

 System.in  是InputStream类,输入的是字节;

System.out 是PrintStream类的对象,属于OutInputStream的子类,输出的是

输出转换流:

    public static void readin()throws Exception
    {    
        //获取键盘录入对象
        InputStream in = System.in;    
        //将字节流对象转成字符流对象,使用转换流 InputStreamReader
        InputStreamReader isr = new InputStreamReader(in) ;
        //为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader
        BufferedReader br = new BufferedReader(isr);
        
        //out对外输出的是字节流对象,不能直接接收字符流
        OutputStream out = System.out;
        //将字符流转换为字节流对象,使用转换流
        //该转换流不知道把字符输出到哪里,所以传给它参数out
        OutputStreamWriter osw = new OutputStreamWriter(out);
        //装饰类,提高效率
        BufferedWriter bw = new BufferedWriter(osw);
        
        String line = null;
        while((line=br.readLine())!=null)
        {
            bw.write(line);
            bw.newLine();
            bw.flush();   //bw是字符输出流对象,需要刷新才能输出
        }
        bw.close();
        br.close();
    }

简化、常用写法:

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

12.流操作的基本规律

1》明确源和目的:  源==输入流  目的===输出流

2》操作的数据:   字符流    字节流

3》设备:

  • 源设备:    内存  硬盘(文件)  键盘
  • 目的设备: 内存  硬盘(文件)  控制台

转换流的用处在于可以指定编码表! 一般情况下使用的是默认编码表 "GBK",指定的编码表只有转换流可以指定。

使用 System.setIn()    System.setOut()   可以改变系统默认的输入输出方式。

13.将异常输出到文件, 一般用插件 log4j

    public static void excep()throws Exception
    {
        try
        {
            int[] arr = new int[3];
            System.out.println(arr[4]);
        }
        catch(Exception e)
        {
            try
            {
                Date d = new Date();    
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        
                String s = sdf.format(d);
                
                PrintStream ps = new PrintStream("exec.log");
                ps.println(s);
                System.setOut(ps);
            }
            catch(Exception ex)
            {
                throw new RuntimeException("bnnnnn");
            }
            e.printStackTrace(System.out);
        
        }
    
    }

14. File类

  • 用来将文件或文件夹封装成对象,方便对文件与文件夹进行操作
  • File对象可以作为参数传递给流的构造函数
  • 类似于字符串,File类的实例是不能改变的,当然引用可以变
    public static void file()throws Exception
    {
        //将a.txt封装成对象,可以将已有的或没有的文件、文件夹封装成对象
        File f1 = new File("a.txt");
        f1. createNewFile() ;
        //b.txt可能不存在
        File f2 = new File("E:\java","b.txt");
        
        System.out.println(f1.length());
        System.out.println(f2.length());
        
    }
/创建:
//在指定位置创建文件,如果文件已经存在,则不创建,返回false
//和输出流不一样,输出流一定创建文件,会覆盖已有文件
boolean createNewFile()
 boolean mkdir()  //创建一级文件夹
 boolean mkdirs()  //创建多级文件夹


//删除
 boolean delete()
 void deleteOnExit()   //JVM退出时删除文件

//判断
 boolean exists()
 boolean isDirectory() //是否是一个目录。 
 boolean isFile()       //是否是文件
 boolean isAbsolute()  // 判断此路径名是否绝对路径 ,不管文件是否存在       

//获取
 String getName()
 String getParent() //返回文件的父目录,如果此文件对象没有指定父目录,返回null
 String getPath()  //返回相对路径
 String getAbsolutePath()  //返回绝对路径
 long lastModified() 
 long length()  //文件的长度

boolean renameTo(File dest)  //文件重命名;当2个文件在不同文件夹,相当于剪切黏贴
1         File f = new File("source\"); //文件夹
2         System.out.println(f.getName()); // source
3         System.out.println(f.getParent()); //返回null
4         System.out.println(f.getPath());   //返回source
5         System.out.println(f.getAbsolutePath()); //返回E:javaworkspaceIOStudysourc
6         System.out.println(f.getAbsoluteFile().getParent()); //返回E:javaworkspaceIOStudy
7         System.out.println(f.lastModified()); //返回最后修改时间 14234602...

关于获取当前路径:

        File f = new File("");
        System.out.println(f); //空白
        System.out.println(f.getAbsoluteFile());//E:javaworkspaceIOStudy
        System.out.println(f.getCanonicalFile());//E:javaworkspaceIOStudy
        
        File f1 = new File(".");
        System.out.println(f1); //.
        System.out.println(f1.getAbsoluteFile());//E:javaworkspaceIOStudy.
        System.out.println(f1.getCanonicalFile());//E:javaworkspaceIOStudy

        File f2 = new File("..");
        System.out.println(f2);   //..
        System.out.println(f2.getAbsoluteFile());//E:javaworkspaceIOStudy..
        System.out.println(f2.getCanonicalFile());//E:javaworkspace
//        对于getCanonicalPath()函数,“."就表示当前的文件夹,而”..“则表示当前文件夹的上一级文件夹
//        对于getAbsolutePath()函数,则不管”.”、“..”,返回当前的路径加上你在new File()时设定的路径
//        至于getPath()函数,得到的只是你在new File()时设定的路径

15. 遍历目录下的文件:

static File[]   listRoots()   // 列出可用的文件系统根。
String[] list()      // 返回一个字符串数组,列出指定目录下所有 文件和目录

    public static void file()throws Exception
    {    
        File[] f2 = File.listRoots();
        String[] s = null;
        for(File f : f2 )
        {
            s = f.list();
            for(String str:s)
                System.out.println(str);
        }        
    }
    //文件列表过滤
    public static void  listFilter()throws Exception
    {
        File f1 = new File("E:\java\day18");
        //匿名内部类定义过滤器
        String[] s = f1.list(new FilenameFilter()
        {
            public boolean accept(File dir, String name) 
            {
                //if(name.matches(".*\.java"))
                //    return true;
                //return false;
                return name.endsWith(".java");
            }            
        }    
        );
        
        for(String str : s )
        {
            System.out.println(str);
        }        
    }
static File[] listRoots()  // 列出可用的文件系统根。 
String[] list()    // 返回一个字符串数组,列出指定目录下所有 文件和目录
String[] list(FilenameFilter filter)  //返回一个字符串数组,使用过滤器
File[] listFiles() //返回文件数组,列出目录中的所有文件、
File[] listFiles(FileFilter filter) // 返回文件数组,使用过滤器
File[] listFiles(FilenameFilter filter) //返回文件数组,使用过滤器


    //递归列出所有文件
    public static void  listAll(File dir)throws Exception
    {
        File[] dirs = dir.listFiles();
        
        for(int x=0;x<dirs.length;x++)
        {
            if(dirs[x].isDirectory())
                listAll(dirs[x]);
            else
                System.out.println(dirs[x]);            
        }        
    }
    
    //删除文件夹下的所有文件和子目录(java的删除是彻底删,不经过回收站)
    public static void  removeDir(File dir)throws Exception
    {
        File[] ds = dir.listFiles();
        for(int x=0;x<ds.length;x++)
        {
            if(ds[x].isDirectory())
                removeDir(ds[x]);
            else    
                System.out.println(ds[x]+"::"+ds[x].delete());
        }
        System.out.println(dir+"::"+dir.delete());
    }
    

 遍历文件夹、创建文件列表:

    
    public static void fileToList(File dir,List <File>  list){
        //迭代遍历整个文件夹,将文件存入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 writeTo(List<File> list){
        //将list内容存入文件中
        try {
            File txt = new File("E:"+File.separator+"java"+File.separator+"recode.log");
            BufferedWriter bw = new BufferedWriter(new FileWriter(txt));
            for(File file : list){
                String path = file.getAbsolutePath();
                bw.write(path);
                bw.newLine();
                bw.flush();
                
            }
            
            bw.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

16. Properties 类  是 Hashtable 的子类

  • 它具备Map集合的特点,它里面存储的键值对都是字符串
  • 是集合中和 IO 技术相结合的集合容器

该对象的特点,可以用于键值形式的配置文件

    //设置和获取
    public static void setAndGet() {
        Properties prop = new Properties();
        //setProperty 设置键-值
        prop.setProperty("zhangsan", "30");
        prop.setProperty("lisi", "40");        
        System.out.println(prop);

        //获取某键的值
        String property = prop.getProperty("lisi");
        System.out.println(property);
        
        //获取所有键值对
        Set<String> names = prop.stringPropertyNames();
        for (String str : names) {
            System.out.println(str+"::"+prop.getProperty(str));
        }
        
    }

加载数据时,需要数据有固定格式: 键=值

    //如何将流中的数据读取到集合中。
    //用一个流和文件关联;  读取一行数据,用“=”切割; 存入Properties集合    
    public static void readPro() throws Exception{
        BufferedReader br = new BufferedReader(new FileReader("source\info.txt"));
        String line = null;
        Properties prop = new Properties();
        
        //这是一种非常粗糙的读取方式,它假设源文件时十分规则的,没有注释、空行之类的东西
        while ((line=br.readLine())!=null) {
            String[] str = line.split("=");
            prop.setProperty(str[0], str[1]);
            
        }
        br.close();
        System.out.println(prop);
    }
    //第2种方式:使用load方法从输入流中读取属性表
    public static void loadPro()throws Exception{
        FileInputStream fis = new FileInputStream("source\info.txt");
        Properties prop = new Properties();
        
        
        //Properties中的load方法是非常智能的方法,可以自动忽略各种空格、注释等噪声
        //以 # 或 ! 开头的会被认为是注释行
        // void load(Reader reader)    void load(InputStream inStream)  
        prop.load(fis);
        
        //System.out.println(prop);
        //list方法可以按规则输出Properties集合
        // void list(PrintStream out)    void list(PrintWriter out)   
        prop.list(System.out);
        
        prop.setProperty("lisi", "23");
        prop.setProperty("zhangwu", "3453");
        
        FileOutputStream fos = new FileOutputStream("source\info.txt");
        
        //store方法是load的逆方法,可以将新的属性表写入到输出流中
        // void store(OutputStream out, String comments)   void store(Writer writer, String comments)   
        prop.store(fos, "mystore");
        
        fos.close();
        fis.close();        
    }

记录软件的运行次数,并同步到Properties文件中:

    public static void runCount()throws Exception{
        Properties prop  = new Properties();
        
        //输入流是无法创建文件的,没有文件抛出异常
        File file = new File("source\info.properties");
        if(!file.exists())
            file.createNewFile();
        
        FileInputStream fis = new FileInputStream(file);
        
        //把文件从流加载到Pro对象
        prop.load(fis);
        
        //计数加 1
        String value = prop.getProperty("time");
        int count=0;
        if(value!=null)
             count = Integer.parseInt(value);
        count++;
        
        prop.setProperty("time", count+"");
        
        //把刷新后的流保存到文件中
        FileOutputStream fos = new FileOutputStream(file);
        prop.store(fos,"");
        
        System.out.println("成功了");
        fos.close();
        fis.close();
    }
    

配置文件信息有 Properties、 XML 2种

java的  org.w3c.com包中的 Document接口用于表示XML文档, 比较麻烦;  有个简单的工具: dom4j

17. 打印流 :  PrintWriter   PrintStream

该流提供了打印方法,可以将各种数据类型的数据都原样打印。

字节打印流 PrintStream:

  • 构造函数可以接收的参数类型: File对象 、 字符串路径fileName、 OutputStream字节输出流 

字符打印流 PrintWriter:

  • 构造函数可以接收的参数类型: File对象 、 字符串路径fileName、 OutputStream字节输出流 、 Writer字符输出流
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //构造函数参数为Writer或OutputStream时, 可以加参数true,自动刷新
        PrintWriter pw = new PrintWriter(System.out,true);
        
        String line = null;
        while((line=br.readLine())!=null){
             pw.println(line);
            // pw.flush();
            //没有设置自动刷新时,这里就要手动刷新了 
        }
        br.close();
        pw.close();

18. 类 SequenceInputStream  合并流

构造函数需要传入 枚举类型,可以先定义 Vector ,  vector.elements()方法传回枚举类型

文件的切割和合并:

public class SplitFile {

    /**
     * @param args
     */
    //文件切割
    public static void splitFile()throws Exception{
        FileInputStream fis = new FileInputStream("source\split.file");
        
        byte[] buf = new byte[1024*1024];
        int len = 0;
        int fileName = 1;
        
        //用于控制分文件的大小
        int fileSizeCount = 0;
        int fileSize = 3;
        
        FileOutputStream fos = null;        
        while( (len=fis.read(buf))!=-1){
            if(fileSizeCount==0)
                fos = new FileOutputStream("source\"+(fileName++)+".part");
            //
            fos.write(buf, 0, len);    
            
            if(fileSizeCount==fileSize){
                fos.close();
            }    
            fileSizeCount = (fileSizeCount+1)%fileSize;
        }    
        
        fis.close();
    }
    
    
    
    //文件融合
    public static void merge()throws Exception{
        ArrayList<FileInputStream> arr = new ArrayList<FileInputStream>();
        
        File source = new File("source\");
        //遍历文件夹下所有文件, 匿名内部类定义过滤器
        File[] files = source.listFiles(new FilenameFilter(){
            public boolean accept(File dir, String name){
                return name.endsWith(".part");
                }
            }
                );
        //使用文件定义输入流,存入ArrayList
        for(File file : files){
            arr.add(new FileInputStream(file));
        }    
        
        //构造序列流,Collections.enumeratio方法返回枚举
        SequenceInputStream sis = new SequenceInputStream( Collections.enumeration(arr));
        
        FileOutputStream fos = new FileOutputStream("merge.pdf");
        //从流中读取数据,写入到输出流中
        byte[] buf = new byte[1024*1024];
        int len;
        while((len=sis.read(buf))!=-1){
            System.out.println(len);
            fos.write(buf,0,len);
        }
        
        fos.close();
        sis.close();
    }

19.