java13 InputStream,Reader

流的方向:
1.输入流:数据源到程序(InputStream,Reader读进来)。
2.输出流:程序到目的地(OutPutStream,Writer写出来)。
处理数据单元:
字节流:按照字节读取数据(InputStream,OutPutStream)。
字符流:按照字符读取数据(Reader,Writer)
功能不同:
节点流:可以直接从数据源或目的地读写数据。
处理流:不直接连接到数据源或者目的地,是处理流的流,通过对其他流的处理提高程序的性能。


处理流:增强功能,提供性能,处理流在节点流之上。


一、缓冲流
1)针对字节有字节缓冲流
BufferedInputStream readLine()
BufferedOutPutStream
2)针对字符有字符缓冲流
BufferedReader newLine()
BufferedWriter


/**
 * 字节流文件拷贝+缓冲流 ,以后使用建议加上缓冲流提高性能。
 * 节点流上面包一层缓冲流。
 */
public class BufferedByteDemo {
    public static void main(String[] args) {
        
    }
    /**
     * 文件的拷贝
     * @param  源文件路径
     * @param  目录文件路径
     * @throws FileNotFoundException,IOException
     * @return 
     */
        public static void copyFile(String srcPath,String destPath) throws FileNotFoundException,IOException {
            //1、建立联系 源(存在且为文件) +目的地(文件可以不存在)  
            File src =new File(srcPath);
            File dest =new File(destPath);
            if(! src.isFile()){ //不是文件或者为null
                System.out.println("只能拷贝文件");
                throw new IOException("只能拷贝文件");
            }
            //2、选择流,利用缓冲流提高性能,
            InputStream is =new BufferedInputStream(new FileInputStream(src));
            OutputStream os =new BufferedOutputStream( new FileOutputStream(dest));
            //3、文件拷贝   循环+读取+写出
            byte[] flush =new byte[1024];
            int len =0;
            //读取
            while(-1!=(len=is.read(flush))){
                //写出
                os.write(flush, 0, len);
            }
            os.flush(); //强制刷出            
            //关闭流
            os.close();
            is.close();
        }
}



/**
 * 字符缓冲流 +新增方法(不能发生多态),字符流外面包一层缓冲流。
 */
public class BufferedCharDemo {
    public static void main(String[] args) {
        //创建源 仅限于 字符的纯文本
        File src =new File("E:/xp/test/1.java");
        File dest =new File("e:/xp/test/2.txt");
        //选择流
        BufferedReader reader =null;        
        BufferedWriter wr =null;
        try {
            reader =new BufferedReader(new FileReader(src));
            wr =new BufferedWriter(new FileWriter(dest));
            //读取操作
            /*
            char[] flush =new char[1024];
            int len =0;
            while(-1!=(len=reader.read(flush))){
                wr.write(flush, 0, len);
            }*/
            //新增方法的操作
            String line =null;
            while(null!=(line=reader.readLine())){//line每次为一行内容
                wr.write(line);
            //wr.append("\r\n");
                wr.newLine(); //换行符号
            }            wr.flush();//强制刷出,流关闭的时候也可以刷出,这里是养成良好的编程习惯。
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("源文件不存在");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("文件读取失败");
        }finally{
            try {
                if (null != wr) {
                    wr.close();
                }
            } catch (Exception e2) {
            }
            try {
                if (null != reader) {
                    reader.close();
                }
            } catch (Exception e2) {
            }
        }
    }
}




二、转换流:字节流转为字符流,作用是为了处理乱码(编码集、解码集)。
1.编码与解码的概念:
解码:二进制(计算机只认二进制)解码成字符(人只懂字符)。
编码:字符编码成二进制。
文件都是二进制,读进程序(转成字符)就是解码,写出去就是编码(转成二进制写出到另一个文件)。
2.乱码问题:(解码的时候要知道原先的编码的字符集)
1)编码与解码字符集不统一。
2)字节缺少,长度丢失。


public class ConverDemo01 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        test1();
        
        //解码(把二进制的中国转成中国让你看得懂,默认gbk),byte->char
        String str ="中国";
        //编码,字符转字节,char->byte
        byte[] data =str.getBytes();//data=[-42, -48, -71, -6]
        //字节数不完整
        System.out.println(new String(data,0,3));//String(byte[] bytes, int offset, int length)通过byte数组构建一个String,输出中?
    }
    /**
     * 编码与解码字符集必须相同,否则乱码
     * @throws UnsupportedEncodingException 
     */
    public static void test1() throws UnsupportedEncodingException{
        //解码(把二进制的中国转成中国让你看得懂,默认gbk), byte -->char
                String str ="中国"; //gbk 
                //编码,字符转字节, char -->byte
                byte[] data =str.getBytes();//data=[-42, -48, -71, -6]
                //编码与解码字符集同一
                System.out.println(new String(data));//中国
                data =str.getBytes("utf-8"); //设定编码字符集,data=[-28, -72, -83, -27, -101, -67]
                //不同一出现乱码
                System.out.println(new String(data));//涓浗
                //编码
                byte[] data2 = "中国".getBytes("utf-8");//data2=[-28, -72, -83, -27, -101, -67]
                //解码
                str=new String(data2,"utf-8");//中国
                System.out.println(str);
    }
}




/*字节————(解码)————>字符————(编码)————>字节
源文件(二进制文件,字节)————(解码)————>程序(在程序中为字符)————(编码)————>目标文件(二进制文件)*/
/**
 * 转换流: 只能字节转为字符
 * 1、输出流 OutputStreamWriter 编码,
 * 2、输入流 InputStreamReader  解码,读取是解码(字节转为字符),ANSI就是GBK的编码方式。
 * 确保源不能为乱码
 */
public class ConverDemo02 {
    public static void main(String[] args) throws IOException {
        /*BufferedReader br =new BufferedReader(
                new FileReader(new File("E:/xp/test/Demo03.java"))
                );//指定不了解码的字符集,所以只能底层使用字节流,因为字节给你可以解码,字符给你不能解码。*/
        //指定解码字符集
        BufferedReader br =new BufferedReader(//读进程序,1.java的文件的编码使用UTF-8编码的,所以这里的解码要UTF-8。
                new InputStreamReader(//字符流和字节流不能直接操作,所以要用一个转换流。
                    new BufferedInputStream(
                            new FileInputStream( 
                                    new File("E:/xp/test/1.java"))),"UTF-8")
                );
        
        //写出文件 编码
        BufferedWriter bw =new BufferedWriter(
                new OutputStreamWriter(//用于编码的转换流
                    new BufferedOutputStream(    
                    new FileOutputStream(new File("E:/xp/test/2.java")))));
                
        String info =null;
        while(null!=(info=br.readLine())){//读取源文件,每次读一行。
            System.out.println(info);
            bw.write(info);
            bw.newLine();
        }
        bw.flush();
        bw.close();
        br.close();
    }
}




其他流(数据在网络中传输都是通过流,不可能是传字符串):
一、字节数组(其他电脑的内存,服务器的内存):
输入流:ByteArrayInputStream read(byte[] byte int off,int len) + close()
输出流:ByteArrayOutputStream  write(byte[] byte int off,int len)


/**
 * 字节数组 节点流
 * 数组的长度有限 ,数据量不会很大
 * 
 * 文件内容不用太大
 * 1、文件  --程序->字节数组
 * 2、字节数组  --程序->文件
 */
public class ByteArrayDemo01 {
    public static void main(String[] args) throws IOException {
        read(write());        
    }
    /**
     * 输出流  操作与文件输出流 有些不同, 有新增方法,不能使用多态
     * @throws IOException 
     */
    public static byte[] write() throws IOException{
        //目的地,一个字节数组。
        byte[] dest;
        //选择流   不同点
        ByteArrayOutputStream bos =new ByteArrayOutputStream();
        //操作 写出
        String msg ="操作与 文件输入流操作一致";
        byte[] info =msg.getBytes();
        bos.write(info, 0, info.length);//写到bos这个管道里去了
        //获取数据
        dest =bos.toByteArray();
        //释放资源
        bos.close();
        return dest;
    }
    
    /**
     * 输入流  操作与 文件输入流操作一致
     * 读取字节数组(之前是读文件),数组的长度有限,数据量不会很大。
     * @throws IOException 
     */
    public static void read(byte[] src) throws IOException{
        //数据源传入        
        String msg = "输入流  操作与 文件输入流操作一致";
        ///byte[] src = msg.getBytes();
        //选择流
        InputStream is =new BufferedInputStream(
                    new ByteArrayInputStream(
                            src
                        )
                );//跟外界没有联系就不会有检查异常
        //操作
        byte[] flush =new byte[1024];
        int len =0;
        while(-1!=(len=is.read(flush))){
            System.out.println(new String(flush,0,len));
        }
        //释放资源
        is.close();
    }
}






/**
 *1、文件  --通过程序->字节数组
 *1)、文件输入流     
 *        字节数组输出流
 *
 * 2、字节数组  --通过程序->文件
 * 1)、字节数组输入流
 *         文件输出流
 */
public class ByteArrayDemo02 {
    public static void main(String[] args) throws IOException {
        byte[] data =getBytesFromFile("e:/xp/test/1.jpg");//文件  --通过程序->字节数组
        toFileFromByteArray(data,"e:/xp/test/arr.jpg");//字节数组  --通过程序->文件
    }
    /**
     * 2、字节数组  --程序->文件
     */
    public static void toFileFromByteArray(byte[] src,String destPath) throws IOException{
        //创建源src
        //目的地
        File dest=new File(destPath);
        //选择流(不同的文件类型,选择的流不一样)
        //字节数组输入流
        InputStream is =new BufferedInputStream(new ByteArrayInputStream(src));        
        //文件输出流
        OutputStream os =new BufferedOutputStream(new FileOutputStream(dest));
        //操作 不断读取字节数组
        byte[] flush =new byte[1];
        int len =0;
        while(-1!=(len =is.read(flush))){
            //写出到文件中
            os.write(flush, 0, len);
        }
        os.flush();
        //释放资源
        os.close();
        is.close();
    }
    
    /**
     * 1、文件  --程序->字节数组
     */
    public static byte[] getBytesFromFile(String srcPath) throws IOException{
        //创建文件源
        File src =new File(srcPath);
        //创建字节数组目的地 
        byte[] dest =null;
        //选择流
        //文件输入流     
        InputStream is =new BufferedInputStream(new FileInputStream(src));
        //字节数组输出流 不能使用多态
        ByteArrayOutputStream bos =new ByteArrayOutputStream();
        //操作   不断读取文件 写出到字节数组流中
        byte[] flush =new byte[1024];
        int len =0;
        while(-1!=(len =is.read(flush))){
            //写出到字节数组流中
            bos.write(flush, 0, len);
        }
        bos.flush();//输出流都要flush一下
        //获取数据
        dest =bos.toByteArray();
        bos.close();
        is.close();        
        return dest;
    }
}



其他流
二、处理流:
1.处理基本类型+字符串(保留数据和类型),是处理流就要借助于节点流(把东西存到哪个地方去),
输入流:DataInputStream(看到InputStream就要字节流不能用字符流) readXxx
输出流:DataOutputStream writeXxx



/**
 * 数据类型(类型只能是基本类型+String)处理流
 * 1、输入流 DataInputStream  readXxx()
 * 2、输出流 DataOutputStream writeXxx()
 * 新增方法不能使用多态
 * java.io.EOFException :没有读取到相关的内容
 */
public class DataDemo01 {
    public static void main(String[] args) {
        try {
            write("e:/xp/test/data.txt");
            //read("e:/xp/test/arr.txt"); //非法内容
            read("e:/xp/test/data.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 从文件读取数据+类型
     * @throws IOException 
     */
    public static void read(String destPath) throws IOException{
        //创建源
        File src =new File(destPath);
        //选择流
        DataInputStream dis =new DataInputStream(
                    new BufferedInputStream(
                                new FileInputStream(src)
                            )
                );
        //操作 读取的顺序与写出一致   必须存在才能读取
        //读取的顺序不一致,数据输出会存在问题
        long num2 =dis.readLong();
        double num1 =dis.readDouble();
        String str =dis.readUTF();
        dis.close();
        System.out.println(num2+"-->"+str);
    }
    /**
     * 数据+类型输出到文件
     * @throws IOException 
     */
    public static void write(String destPath) throws IOException{
        double point =2.5;
        long num=100L;
        String str ="数据类型";
        //创建源
        File dest =new File(destPath);
        //选择流  DataOutputStream
        DataOutputStream dos =new DataOutputStream(
                    new BufferedOutputStream(//OutputStream的子类
                                new FileOutputStream(dest)
                            )
                );
        //操作 写出的顺序 为读取准备,写入到文件data.txt
        dos.writeDouble(point);
        dos.writeLong(num);
        dos.writeUTF(str);        
        dos.flush();
        //释放资源
        dos.close();
    }
}



/**
 * 数据类型(基本+String)处理流
 * 1、输入流 DataInputStream  readXxx()
 * 2、输出流 DataOutputStream writeXxx()
 * 新增方法不能使用多态
 * java.io.EOFException :没有读取到相关的内容
 */
public class DataDemo02 {
    public static void main(String[] args) {
        try {
            byte[] data=write();
            read(data);
            System.out.println(data.length);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 从字节数组读取数据+类型
     * @throws IOException 
     */
    public static void read(byte[] src) throws IOException{
        //字节数组,选择流用字节数组输入流
        DataInputStream dis =new DataInputStream(
                    new BufferedInputStream(
                        new ByteArrayInputStream(src)
                            ));
        //操作 读取的顺序与写出一致   必须存在才能读取
        double num1 =dis.readDouble();
        long num2 =dis.readLong();
        String str =dis.readUTF();
        dis.close();
        System.out.println(num1+"-->"+num2+"-->"+str);
    }
    /**
     * 数据+类型输出到字节数组中,输出到字节数组中用ByteArrayOutputStream。
     * @throws IOException 
     */
    public static byte[] write() throws IOException{
        //目标数组
        byte[] dest =null;
        double point =2.5;
        long num=100L;
        String str ="数据类型";
        //选择流 ByteArrayOutputStream  DataOutputStream
        ByteArrayOutputStream bos =new ByteArrayOutputStream();
        DataOutputStream dos =new DataOutputStream(
                    new BufferedOutputStream(
                            bos
                            )
                );
        //操作 写出的顺序 为读取准备
        dos.writeDouble(point);
        dos.writeLong(num);
        dos.writeUTF(str);        
        dos.flush();
        dest =bos.toByteArray();
        //释放资源
        dos.close();
        return dest;//把double、long、String写入到字节数组dest中。
    }
}

 

posted @ 2015-09-23 21:36  无天666  阅读(322)  评论(0编辑  收藏  举报