黑马程序员-io流输入与输出的若干总结

来源:互联网 发布:base64 encode php 编辑:程序博客网 时间:2024/06/05 22:47

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------


概述:

流就是字节序列的抽象概念,能被连续读取数据的数据源和能被连续写入数据的接收端就是流,流机制是Java及C++中的一个重要机制,通过流我们可以自由地控制文件、内存、IO设备等数据的流向。而IO流就是用于处理设备上的数据,如:硬盘、内存、键盘录入等。IO流根据处理类型的不同可分为字节流和字符流,根据流向的不同可分为输入流和输出流。

 

字节流和字符流:

字符流,因为文件编码的不同,就有了对字符进行高效操作的字符流对象,它的原理就是基于字节流读取字节时去查了指定的码表。它和字节流的区别有两点:1.在读取数据的时候,字节流读到一个字节就返回一个字节,字符流使用了字节流读到一个或多个字节(一个中文对应的字节数是两个,在UTF-8码表中是3个字节)时,先去查指定的编码表,再将查到的字符返回;2.字节流可以处理所有类型的数据,如jpg、avi、mp3、wav等等,而字符流只能处理字符数据。所以可以根据处理的文件不同考虑使用字节流还是字符流,如果是纯文本数据可以优先考虑字符流,否则使用字节流。

 

IO体系,所具备的基本功能就是读和写:

1.字符流

 Reader(读)

  Writer(写)

 Reader

  InputStreamReader

  FileReader:用于处理文件的字符读取流对象

 Writer

 OutputStreamWriter

  FileWriter:用于处理文件的字符写入流对象

 

其实很容易就可以看出来,IO体系中的子类名后缀绝大部分是父类名称,而前缀则是体现子类特有功能的名称。

 Reader中常见的方法:

 int read()

读取一个字符,并返回读到的这个字符,读到流的末尾则返回-1。

  int read(char[])

 将读到的字符存入指定的数组中,返回的是读到的字符个数,

 读到流的末尾则返回-1。

 close()

 读取字符其实用的是window系统的功能,就希望使用完毕后,

 进行资源的释放。

 FileReader除了自己的构造函数外没有特有的方法:

 用于读取文本文件的流对象。

 用于关联文本文件。

 构造函数FileReader(String fileName)

 在读取流对象初始化时,必须要指定一个被读取的文件,

 如果该文件不存在则会发生FileNotFoundException异常。

 Writer中常见的方法:

  write()

 将一个字符写入到流中。

 write(char[])

 将一个字符数组写入到流中。

 writer(String)

 将一个字符写入到流中。

  flush()

 刷新流,将流中的数据刷新到目的地中,流还存在。

 close()

 关闭资源,在关闭钱会先调用flush(),刷新流中的数据到目的地。

 FileWriter,除了自己的构造函数外没有特有的方法:

 该类的特点

 用于处理文本文件

 没有默认的编码表

 有临时缓冲

 构造函数,在写入流对象初始化时,必须要有一个存储数据的目的地。

 FileWriter(String fileName),该构造器是干什么用的呢?

 调用系统资源

 在指定位置创建一个文件,如果该文件已经存在则被覆盖。

 FileWriter(String filename,Boolean append),这构造器的作用是?

 当传入的boolean类型的值为true时,会在指定文件末尾处进行数据的续写。



一、FileWriter
1、用于操作文件的Writer子类对象,FileWriter。后缀名是父类名,前缀名是该流对象的功能

import java.io.*;  

class Demo{  

    public static void main(String args[]) throws Exception{  

        //创建一个FileWriter对象,该对象一被初始化,就必须要明确被操作的文件  

        //而且该文件会被创建到指定目录下,如果该目录下已有同名的文件,将被覆盖。  

        //其实该步就是明确数据要存放的目的地  

        FileWriter fw = new FileWriter("Demo.txt");  

        //调用writer方法,将字符串写入到流中,会产生异常  

        fw.write("abc");  

        //刷新该流的缓冲。将数据刷新到文件中  

        fw.write("def");  

        fw.flush();  

        //关闭刘子源,但是关闭之前会刷新一次内部的缓冲的数据。,将数据刷到目的地中,和flush区别,flush(),刷新后,流可以继续使用,close刷新后,会将流关闭。  

        //操作完,必须关闭  

        fw.close();  

    }  

    public static void sop(Object obj){  

        System.out.println(obj.toString());  

    }  

}  


 二:文本文件读取方式

1:intread() 

         读取单个字符。

2:int read(char[]cbuf) 

         将字符读入数组。

import java.io.*;  

class Demo{  

    public static void main(String args[]) throws Exception{  

        FileReader fr = new FileReader("Demo.txt");  

        //定义一个字符串数组,用于存储到的字符  

        //该 read(char[])返回的是读到的字符个数  

        char[] buf = new char[1024];  

        int num = 0;  

        while((num = fr.read(buf))!=-1){  

            System.out.println(num+"..."+new String(buf,0,num));  

        }  

    }  


 

三、拷贝文本文件
复制的原理,其实就是将一个文件的数据存储到另一个文件中
//复制文件


/* 

    1、在D盘创建一个文件,用于存储C盘文件中的数据 

    2、定义读取流和C盘文件关联 

    3、通过不断的读写完成数据存储 

    4、关闭资源 

*/  

import java.io.*;  

class Demo{  

    public static void main(String args[]) throws Exception{  

        copy_2();  

          

    }  

    public static void copy_1() throws Exception{  

        //创建目的地  

        FileWriter fw = new FileWriter("Demo_copy.java");  

        //与已有文件关联  

        FileReader fr = new FileReader("Demo.java");  

        int ch = 0;  

        while((ch = fr.read())!=-1){  

            fw.write(ch);  

        }  

        fw.close();  

        fr.close();  

    }  

    public static void copy_2() throws IOException{  

        //创建目的地  

        FileWriter fw = null;  

        //与已有文件关联  

        FileReader fr = null;  

        try{  

            fw = new FileWriter("Demo_copy.java");  

            fr = new FileReader("Demo.java");  

            char[] buf = new char[1024];  

            int len = 0;  

            while((len=fr.read(buf))!=-1){  

                fw.write(buf,0,len);  

            }  

        }catch(IOException e){  

            throw new RuntimeException("读写失败");  

        }finally{  

            if(fr!=null)  

                try{  

                    fr.close();  

                }catch(IOException e){  

                      

                }  

            if(fw!=null)  

                try{  

                    fw.close();  

                }catch(IOException e){  

                      

                }  

        }  

    }  

}  



四、BufferedReader
    readLine() 读取一个文本行。返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null ,所有要手动写入换行



/* 

字符读取流缓冲区: 

该缓冲区提供了一个一次读一行的方法 readLine ,方便于对文本数据的获取 

当返回 null 时,表示读到文件的末尾 

readLine() 方法返回的时候只返回回车符之前的数据内容,并不返回回车符 

*/  

import java.io.*;  

class Demo{  

 public static void main(String args[]) throws IOException{  

 //创建一个读取流对象和文件相关联  

   FileReader fr = new FileReader("Demo.java");  

 //为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数  

   BufferedReader bufr = new BufferedReader(fr);  

   String s1 = bufr.readLine();  

   System.out.println(s1);  

 }  

}  


五、LineNumberReader
跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int)和 getLineNumber(),它们可分别用于设置和获取当前行号。


import java.io.*;  

class Demo{  

    public static void main(String args[]) throws IOException{  

        FileReader fr = new FileReader("Demo.java");  

        LineNumberReader lnr = new LineNumberReader(fr);  

        String line = null;  

        lnr.setLineNumber(2);  

        while((line=lnr.readLine())!=null){  

            System.out.println(lnr.getLineNumber()+":"+line);  

        }  

        lnr.close();  

    }  

}   



六、字节流File读写操作


/* 

    字符流 

    FileReader 

    FileWriter 

    BufferedReader 

    BufferedWriter 

     

    字节流 

    InputStream    OutputStream 

     

*/  

  

  

/* 

    需求:想要操作图片数据。据悉要到字节流 

*/  

import java.io.*;  

class Demo{  

    public static void main(String args[]) throws IOException{  

        //writeFile();  

        readFile_3();  

    }  

    //写文件  

    public static void writeFile() throws IOException{  

        FileOutputStream fos = new FileOutputStream("demo.txt");  

        fos.write("ab张c".getBytes());  

        fos.close();  

    }  

    //读文件 第一种方式  

    public static void readFile_1() throws IOException{  

        FileInputStream fis = new FileInputStream("demo.txt");  

        int ch = 0;  

        while((ch=fis.read())!=-1){  

            System.out.println((char)ch);  

        }  

        fis.close();  

    }  

    //读文件 第二种方式  这种适用  

    public static void readFile_2() throws IOException{  

        FileInputStream fis = new FileInputStream("demo.txt");  

        byte[] buf = new byte[1024];  

        int len = 0;  

        while((len = fis.read(buf))!=-1){  

            System.out.println(new String(buf,0,len));  

        }  

        fis.close();  

    }  

    //读文件 第三种方式   这种内存太大  

    public static void readFile_3() throws IOException{  

        FileInputStream fis = new FileInputStream("demo.txt");  

        byte[] buf = new byte[fis.available()];  

        fis.read(buf);  

        System.out.println(new String(buf));  

        fis.close();  

    }  

}  



七、字节流的缓冲区
    BufferedInputStream
    BufferedInputStream


/* 

演示MP3的复制,通过缓冲区 

BufferedInputStream 

BufferedOnputStream 

*/  

import java.io.*;  

public class Demo{  

    public static void main(String args[])throws IOException{  

        long start  = System.currentTimeMillis();  

        copy_mp3();  

        long end  = System.currentTimeMillis();  

    }  

    public static void copy_mp3()throws IOException{  

        BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("C:\\Users\\Public\\Music\\Sample Music\\Kalimba.mp3"));  

        BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("Kalimba.mp3"));  

        int by = 0;  

        while((by=bufis.read())!=-1){  

            bufos.write(by);  

        }   

        bufis.close();  

        bufos.close();  

    }  

}  



八、读取键盘录入
    System.out:对应的是标准输出设备:控制台
    System.in:对应的是标准输入设备:键盘


/* 

需求,通过键盘录入数据。 

当录入一行数据后,就将改行数据进行打印,如果录入数据是over,那么停止录入 

*/  

import java.io.*;  

public class Demo{  

    public static void main(String args[]) throws IOException{  

        InputStream in = System.in;  

        StringBuilder sb = new StringBuilder();  

        while(true){  

            int ch = in.read();  

            if(ch=='\r')  

                continue;  

            if(ch=='\n'){  

                String s = sb.toString();  

                if("over".equals(s))  

                    break;  

                System.out.println(s.toUpperCase());  

                sb.delete(0,sb.length());  

            }else{  

                sb.append((char)ch);  

            }  

        }  

    }  

}  



九、流操作规律
    1、    源:键盘录入
        目的:控制台
    2、    源:键盘
        目的:文件


/* 

需求,通过键盘录入数据。 

当录入一行数据后,就将改行数据进行打印,如果录入数据是over,那么停止录入 

*/  

import java.io.*;  

public class Demo{  

    public static void main(String args[]) throws IOException{  

        //获取键盘录入对象  

        InputStream in = System.in;  

        //将字节流对象转换成字符流对象,使用转换流,InputStreamReader  

        InputStreamReader isr = new InputStreamReader(in);  

        //为了提高效率,将字符进行缓冲区技术高效操作,使用bufferedReader  

        BufferedReader bufr = new BufferedReader(isr);  

          

        //以上可以用一句话代替  

        //BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));  

          

        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("demo.txt"));  

        BufferedWriter bufw = new BufferedWriter(osw);  

          

        //以上可以用一句话代替  

        //BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));  

          

        String line = null;  

        while((line = bufr.readLine())!=null){  

            if(line.equals("over")){  

                break;  

            }  

            bufw.write(line.toUpperCase());  

            bufw.newLine();  

            bufw.flush();  

        }  

        bufr.close();  

    }  

}  



    3、需求:想要讲一个文件的数据打印在控制而台上
        源:文件
        目的:控制台


/* 

需求,通过键盘录入数据。 

当录入一行数据后,就将改行数据进行打印,如果录入数据是over,那么停止录入 

*/  

import java.io.*;  

public class Demo{  

    public static void main(String args[]) throws IOException{  

  

  

        //将字节流对象转换成字符流对象,使用转换流,InputStreamReader  

        InputStreamReader isr = new InputStreamReader(new FileInputStream("Demo.java"));  

        //为了提高效率,将字符进行缓冲区技术高效操作,使用bufferedReader  

        BufferedReader bufr = new BufferedReader(isr);  

          

        //以上可以用一句话代替  

        //BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));  

        OutputStream out = System.out;  

        OutputStreamWriter osw = new OutputStreamWriter(out);  

        BufferedWriter bufw = new BufferedWriter(osw);  

          

        //以上可以用一句话代替  

        //BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));  

          

        String line = null;  

        while((line = bufr.readLine())!=null){  

            if(line.equals("over")){  

                break;  

            }  

            bufw.write(line.toUpperCase());  

            bufw.newLine();  

            bufw.flush();  

        }  

        bufr.close();  

    }  

}  




    4、流操作的基本规律:最痛苦的就是流对象有很多,不知道该用那一个
        通过明确来完成。
        (1)、明确源和目的
            源:输入流 InputStream Reader
            目的:输出流 OutputStream Writer
        (2)、操作的数据是否是纯文本
            是:字符流
            不是:字节流
        (3)、当体系明确后,再明月要使用那个具体的对象
            通过设备来进行区分:
               源设备:内存 硬盘 键盘
               目的设备:内存 硬盘 控制盘
    5、需求
        (1)、将一个文本文件中数据存储到另一个文件中。复制文件
            源:
               因为是源,所以使用读取流。IputStream reader
            是不是操作文本文件:
               是,所以使用 Reader
            家下来明确要使用该体系中的那个对象:
               明确设备,硬盘,一个文件,
            Reader体系中可以操作文件的是,FileReader
        FileReader fr = newFileReader("a.txt");
        是否需要提高效率?
           BufferedReader bufr = new BufferedReader(fr);
            
            目的:
               OutputStream Writer
            是否是纯文本
               是:wirter
            设备
               硬盘,一个文件
            Writer体系中可以操作文件的对象 FileWriter
    FileWriter fw = newFileWriter("b.txt");
    是否需要提高效率?
    BufferedWriter bufr = newBufferedWriter(fr);
练习:讲一个图片文件中数据存储到另一个文件中。复制文件。要按照以上格式自己完成三个明确


流操作规律补充:
    1、需求:将键盘录入的数据保存到一个文件中
        这个需求中有源和目的都存在,那么分别分析
        源:InputStreamReader
            是不是纯文本?:是纯文本,用Reader
            是不是设备?:是,键盘,对应的对象是 System.in
            不是选择Reader吗?System.in 对应的不是字节流吗?
            为了操作键盘的文本数据方便,字节流可以转换成字符流,按照字符串操作最方便。
            既然明确了 Reader就将 System.in 转换成 Reader
            用到了Reader体系中的转换流,InputSteamReader
           InputStreamReader isr = InputStreamReader(System.in);
            
            需要提高效率吗?需要,BufferedReader
           BufferedReader bufr = new BufferedReader(isr);
            
        目的:OutputStreamWriter
            是否是纯文本?是,Writer
            是不是设备?是,硬盘,使用,FileWriter
           FileWriter fw = new FileWriter("b.txt");
            需要提高效率吗?需要
           BufferedWriter bufw = new BufferedWriter(fw);
        
    2、扩展
            想要把录入的数据按照指定的编码表(UTF-8),将数据存到文件中,使用转换流,里面可以指定编码
            
            目的:OutputStreamWriter
            是否是纯文本?是,Writer
            是不是设备?是,硬盘,使用,FileWriter
            
            但是存储是,需要加入指定的编码表,而制定的编码表,只有转换流可以指定。
            所以要使用的对象是 OutputStreamWriter.
            而该转换流对象要接收一个字节输出流。而且还可以操作文件的字节输出流,FileOutputStream
            
           OutputStreamWriter osw = new OutputStreamWriter(newFileOutputStream("d.txt"),"UTF-8");
            
            需要高效吗?需要
           BufferedWriter bufw = new BufferedWriter(osw);
            
            所以,记住,转化暖流什么时候使用,字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流
    3、讲一个文本数据打印在控制台上


十、File对象功能-创建和删除
1、创建
    boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false
        和输出流不一样棒,输出流对象一建立就创建文件,而且文件已经存在,会覆盖
    boolean mkdir() 创建此抽象路径名指定的目录。 

2、删除
    boolean delete() 删除此抽象路径名表示的文件或目录。
    void deleteOnExit() 在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。 
        当被操作时候,删除不了,所以等虚拟机终止时,删除

3、判断
    boolean canExecute() 测试应用程序是否可以执行此抽象路径名表示的文件。 
    boolean canRead() 测试应用程序是否可以读取此抽象路径名表示的文件。 
    boolean canWrite() 测试应用程序是否可以修改此抽象路径名表示的文件。 
    int compareTo(File pathname)  按字母顺序比较两个抽象路径名 
    boolean exists() 测试此抽象路径名表示的文件或目录是否存在。 
    boolean isAbsolute() 测试此抽象路径名是否为绝对路径名。 
    
    判断类型时候。必须先判断是否存在
    
    boolean isDirectory() 测试此抽象路径名表示的文件是否是一个目录。 
    boolean isFile() 测试此抽象路径名表示的文件是否是一个标准文件。 

4、获取信息
    String getName()
    String getPath
    String getParent()    此抽象路径名指定父目录的路径名字符串;如果此路径名没有指定父目录,则返回null
    String getAbsolutPath
    String getAbsolutFile() 绝对路径对象
    long lastModified()
    long length() 返回由此抽象路径名表示的文件的长度。 
    

    boolean renameTo(File dest)重新命名此抽象路径名表示的文件。


十一、文件列表
static File[] listRoots() 
          列出可用的文件系统根。 
String[] list()  包含隐藏文件
          返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。

文件过滤
String[] list(FilenameFilter filter) 
          返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。 
File[] listFiles(FilenameFilter filter) 
          返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。 


import java.io.*;  

public class Demo{  

    public static void main(String args[])throws IOException{  

        method();  

    }  

    public static void method()throws IOException{  

        File dir = new File("c:\\java");  

        File[] subNames = dir.listFiles();  

        for(File name : subNames){  

            sop(name.getName()+"::"+name.length());  

        }  

    }  

    public static void method2()throws IOException{  

        File dir = new File("c:\\java");  

        String[] subNames = dir.list(new FilenameFilter(){  

            public boolean accept(File dir,String name){  

                return name.endsWith(".java");  

            }  

        });  

        for(String name : subNames){  

            sop(name);  

        }  

    }  

    public static void sop(Object obj){  

        System.out.println(obj.toString());  

    }  

}  


十二、列出目录下所有内容-带层次



列出指定目录下文件或者文件夹,包含子目录中的内容。 

也就是列出指定目录下所有内容 

因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。 

在列出过程中出现还是目录的话,还可以在此调用本功能 

也就是函数自身调用自身, 

这种表现形式,或者编程手法,成为递归 

 

 

递归要注意: 

1、制条件 

2、要注意递归次数,避免内存溢出 


import java.io.*;  

public class Demo{  

    public static void main(String args[])throws IOException{  

        File dir = new File("c:\\java\\test");  

        showDir(dir,0);  

    }  

    public static String getLevel(int level){  

        StringBuilder sb = new StringBuilder();  

        for(int x=0;x<level;x++){  

            sb.append("|   ");  

        }  

        return sb.toString();  

    }  

    public static void showDir(File dir,int level)throws IOException{  

        sop(getLevel(level)+dir);  

        level++;  

        File[] files = dir.listFiles();  

        for(int x=0;x<files.length;x++){  

            if(files[x].isDirectory()){  

                showDir(files[x],level);  

            }else{  

                sop(files[x]);  

            }  

        }  

    }  

    public static void sop(Object obj){  

        System.out.println(obj.toString());  

    }  

}  


十三、创建java文件列表


/* 

练习, 

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

建立一个java文件列表文件 

 

 

思路: 

1、对指定的目录进行递归 

2、获取递归过程中的java文件路径 

3、将这些路径存储到集合中 

4、将集合中的数据写入到一个文件中 

*/  

import java.io.*;  

import java.util.*;  

public class Demo{  

    public static void main(String args[])throws IOException{  

        File dir = new File("c:\\java");  

        List<File> list = new ArrayList<File>();  

        fileToList(dir,list);  

        File file = new File(dir,"demo.txt");  

        writeToFile(list,file.toString());  

    }  

    public static void fileToList(File dir,List<File> list)throws IOException{  

        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)throws IOException{  

        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 e;  

        }finally{  

            try{  

                if(bufw!=null){  

                    bufw.close();  

                }  

            }catch(IOException e){  

                  

            }  

        }  

    }  

    public static void sop(Object obj){  

        System.out.println(obj.toString());  

    }  

}  



十四、Properties

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

代码如下:


import java.io.*;  

import java.util.*;  

public class Demo{  

    public static void main(String args[])throws IOException{  

        setAndGet();  

    }  

    //设置和获取元素  

    public static void setAndGet(){  

        Properties prop = new Properties();  

        prop.setProperty("zhangsan","30");  

        prop.setProperty("lisi","39");  

        sop(prop.toString());  

        String value = prop.getProperty("lisi");  

        sop(value);  

        prop.setProperty("lisi","98");  

        Set<String> names = prop.stringPropertyNames();  

        for(String s : names){  

            sop(s+":"+prop.getProperty(s));  

        }  

    }  

    public static void sop(Object obj){  

        System.out.println(obj.toString());  

    }  

}  



Properties存取配置文件
    
String getProperty(String key) 
          用指定的键在此属性列表中搜索属性。 
 String getProperty(String key, StringdefaultValue) 
          用指定的键在属性列表中搜索属性。 
 void list(PrintStream out) 
          将属性列表输出到指定的输出流。 
 void list(PrintWriter out) 
          将属性列表输出到指定的输出流。 
 void load(InputStream inStream) 
          从输入流中读取属性列表(键和元素对)。 
 void load(Reader reader) 
          按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 
store(OutputStream out, String comments) 
          以适合使用 load(InputStream)方法加载到 Properties表中的格式,将此Properties表中的属性列表(键和元素对)写入输出流。


十五、PrintWriter
    1、打印流
        PrintWriter 与 PrintStream
            可以直接操作输入流和文件
    2、序列流、
        SequenceInputStream
            对多个流进行合并
    3、操作对象
        ObjectInputStream 与 ObjectOutputStream
            被操作的对象需要实现 Serializale (标记接口);
    4、练习:文件分割程序


/* 

打印流 

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

 

 

字节打印流 

PrintStream 

构造函数可以接受的参数类型 

1、file对象。 

2、字符串路径。String 

3、字节输出流 OutpuStream 

 

 

字符打印流 

PrintWriter 

构造函数可以接受的参数类型 

1、file对象。 

2、字符串路径。String 

3、字节输出流 OutpuStream 

4、字符输出流    Writer 

*/  

import java.io.*;  

public class Demo{  

    public static void main(String args[])throws Exception{  

        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));  

        //PrintWriter out = new PrintWriter(System.out,true);  

        PrintWriter out = new PrintWriter(new FileWriter("demo.txt"),true);  

        String line = null;  

        while((line=bufr.readLine())!=null){  

            if("over".equals(line)){  

                break;  

            }  

            out.println(line.toUpperCase());  

            //out.flush();  

        }  

        out.close();  

        bufr.close();  

    }  

    public static void sop(Object obj){  

        System.out.println(obj.toString());  

    }  

}  



十六、合并流


import java.io.*;  

import java.util.*;  

public class Demo{  

    public static void main(String args[])throws Exception{  

        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();  

        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();  

    }  

    public static void sop(Object obj){  

        System.out.println(obj.toString());  

    }  

}  




十七、管道流
IO包中的其他类
    1、RandomAccessFile
        (1)、随机访问文件,自身具备读写的方法
        (2)、通过skipBytes(int x),seek(int x)来达到随机访问。
    2、管道流
        (1)、PipedInputStream和PipedOutputStream
            (1)、输入输出可以直接进行连接,通过结合线程使用。
    3、public class PipedInputStreamextendsInputStream管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏。 
    4、public class PipedOutputStreamextendsOutputStream可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream读取。不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。如果某个线程正从连接的管道输入流中读取数据字节,但该线程不再处于活动状态,则该管道被视为处于毁坏状态


/* 

谁先执行都可以,因为会阻塞 

*/  

import java.io.*;  

public class Demo{  

    public static void main(String[] args) throws Exception{  

        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();  

    }  

    public static void sop(Object obj){  

        System.out.println(obj);  

    }  

}  

class Read implements Runnable{  

    private PipedInputStream in;  

    Read(PipedInputStream in){  

        this.in = in;  

    }  

    public void run(){  

        try{  

            byte[] buf = new byte[1024];  

            int length = in.read(buf);  

            String s = new String(buf,0,length);  

            System.out.println(s);  

            in.close();  

        }catch(Exception e){  

            throw new RuntimeException("管道读取流失败");  

        }  

    }  

      

}  

class Write implements Runnable{  

    private PipedOutputStream out;  

    Write(PipedOutputStream out){  

        this.out = out;  

    }  

    public void run(){  

        try{  

            Thread.sleep(3000);  

            out.write("piped lai la".getBytes());  

            out.close();  

        }catch(Exception e){  

            throw new RuntimeException("管道输出流失败");  

        }  

    }  

}  



十八、RandomAccessFile
public class RandomAccessFileextendsObjectimplements DataOutput, DataInput, Closeable此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek方法设置。 



/* 

RandomAccessFile 

该类不算是IO体系中的子类 

而是直接继承自Object 

 

 

但是它是IO包中的成员,因为它具备读和写的功能 

内部封装了一个数组,而且通过指针对数组的元素进行操作 

可以通过getFilePointer获取指针位置 

同时可以通过seek改变指针位置 

 

 

其实完成读写的原理就是内部封装了字节输入流,和输出流 

 

 

通过构造函数可以看出,该类只能操作文件,而不能是键盘什么的 

而且操作文件还有格式 r rw 。。。 

 

 

如果模式为只读 r ,不会创建文件,会读取一个已存在文件,如果该文件不存在,则会出现异常 

如果模式为rw,操作的文件不存在,会自动创建,如果存在则不会覆盖 

而且该对象的构造函数要操作的文件不存在,会自动创建,如果存在则不会覆盖 

 

 

*/  

import java.io.*;  

public class Demo{  

    public static void main(String[] args) throws Exception{  

        //write();  

        //read();  

        writeFile_2();  

    }  

    public static void writeFile_2() throws Exception{  

        RandomAccessFile raf = new RandomAccessFile("demo.txt","rw");  

        //raf.seek(32);  

        raf.seek(8);  

        raf.write("周期".getBytes());  

        //raf.writeInt(87);  

        raf.close();  

    }  

    public static void write() throws Exception{  

        RandomAccessFile raf = new RandomAccessFile("demo.txt","rw");  

        raf.write("李四".getBytes());  

        //write写入int的最低八位  

        //raf.write(97);  

        //writeInt写入int 的 全部 4个八位  

        raf.writeInt(97);  

        raf.write("王五".getBytes());  

        raf.writeInt(99);  

        raf.close();  

    }  

    public static void read() throws Exception{  

        RandomAccessFile raf = new RandomAccessFile("demo.txt","rw");  

        byte[] buf = new byte[4];  

        //read为读单个字节  readInt()  为读4个字节  

        raf.read(buf);  

        String str = new String(buf);  

        sop(str);  

        //调整对象中指针  

        raf.seek(0);  

        //跳过指定的字节数,只能往后跳,不能往回跳  

        raf.skipBytes(8);  

        int num = raf.readInt();  

        sop(num);  

          

  

  

        raf.close();  

    }  

    public static void sop(Object obj){  

        System.out.println(obj);  

    }  

}  



十九、操作基本数据类型的流对象DataStream
    1、操作基本数据类型
        DataInputStream 与 DataOutputStream
    2、操作字节数
        ByteArrayInputStream与ByteArrayOutputStream
    3、操作字符数组
        CharArrayReader 与 CharArrayWriter
    4、操作字符串
        StringReader 与 StringWriter
        


/* 

DataInputStream 与 DataOutputStream 

可以用来操作基本数据类型的数据流对象 

 


*/  

import java.io.*;  

public class Demo{  

    public static void main(String[] args) throws Exception{  

        //writeData();  

        //readData();  

        writeUTFDemo();  

        readUTFDemo();  

        //writeUTFNormal();  

    }  

    public static void writeData() throws IOException {  

        DataOutputStream dos = new DataOutputStream(new FileOutputStream("demo.txt"));  

        dos.writeInt(234);  

        dos.writeBoolean(true);  

        dos.writeDouble(9887.543);  

        dos.close();  

    }  

    public static void readData() throws IOException {  

        DataInputStream dos = new DataInputStream(new FileInputStream("demo.txt"));  

        sop(dos.readInt());  

        sop(dos.readBoolean());  

        sop(dos.readDouble());  

        dos.close();  

    }  

    public static void writeUTFDemo() throws IOException{  

        DataOutputStream dos = new DataOutputStream(new FileOutputStream("demo.txt"));  

        dos.writeUTF("你好");  

    }  

    public static void readUTFDemo() throws IOException{  

        DataInputStream dis = new DataInputStream(new FileInputStream("demo.txt"));  

        sop(dis.readUTF());  

        dis.close();  

    }  

    public static void writeUTFNormal() throws IOException{  

        OutputStreamWriter dos = new OutputStreamWriter(new FileOutputStream("demo.txt"),"utf-8");  

        OutputStreamWriter dos2 = new OutputStreamWriter(new FileOutputStream("demo.txt"),"gbk");  

        dos.write("你好");  

        dos2.write("我好");  

        dos.close();  

        dos2.close();  

    }  

    public static void sop(Object obj){  

        System.out.println(obj);  

    }  

}  




二十、ByteArrayStream


/* 

用于操作字节数组的流对象 

 

 

ByteArrayInputStream:在构造的时候,需要接收数据源,而且数据源是一个字节数组 

ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组 

这就是数据目的地 

 

 因为这两个流对象都操作的是数组,并没有使用系统资源。 

所以,不用进行close关闭 

  

源设备; 

    键盘(System.in)、硬盘(FileStream)、内存(ArrayStream) 

目的设备 

    控制台(System.out)、硬盘(FileStream)、内存(Array.Stream) 

     

用流的思想来操作数组 

 

 

*/  

import java.io.*;  

public class Demo{  

    public static void main(String[] args) throws Exception{  

        //数据源  

        ByteArrayInputStream bis = new ByteArrayInputStream("abcdefg".getBytes());  

          

        //数据目的  

        ByteArrayOutputStream bos = new ByteArrayOutputStream();  

          

        int by = 0;  

        while((by=bis.read())!=-1){  

            bos.write(by);  

        }  

        sop(bos.size());  

        sop(bos.toString());  

    }  

    public static void sop(Object obj){  

        System.out.println(obj);  

    }  

}  



------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

0 0