Java基础——IO流

来源:互联网 发布:指南针软件好用吗 编辑:程序博客网 时间:2024/05/16 10:28

1、IO流
IO流:输入、输出流(针对的是内存和外围设备(硬盘)的数据交换)
外围设备到内存:输入(读)
内存到外围设备:输出(写)
字符流的由来:其实就是字节流读取文字字节数据后,不直接操作而是先指定的编码表,获取对应的文字
再对这个文字进行操作。简单的说:字节流+编码表。

字节流的两个顶层父类:
1、InputStream
2、OutputStream

字符流的两个顶层父类:
1、Reader
2、Writer

如果要操作文字数据,优先考虑字符流,将数据从内存写到硬盘上,要使用字符流中的输出流:Writer

字符流缓冲区:
BufferWriter
newLine():加入换行符
BufferReader
readLine():读取文本的一行
2、字符流的操作代码示例
2.1字符流读写操作

读操作

package cn.itcast.p2.io.filewriter;//读文件的第一种方式import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;public class FileReaderDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub//      1、创建读取字符数据的流对象        /*         * 在创建读取流对象时,必须要明确被读取的文件,一定要确定该文件是存在的         * 用一个读取流关联一个已存在文件         *          *          * */        FileReader fr=new FileReader("demo.txt");        int ch;//      用Reader中的read方法读取字符//      int ch=fr.read();//每次只读取一个字符,而且是二进制(因为存在磁盘上的都是二进制格式的,由于前面int限制,所以返回的十进制数)//      System.out.println(ch);//结果:97,读完之后返回的是-1        while((ch=fr.read())!=-1) {            System.out.println((char)ch);        }    }}
package cn.itcast.p2.io.filewriter;//读文件的第二种方式import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;public class FileReaderDemo2 {    public static void main(String[] args) throws IOException {        FileReader fr=new FileReader("demo.txt");        /*使用read(char[])读取文本文件数据         * 先创建字符数组         *          * */        /*char[]buf=new char[6];        int num=fr.read(buf);//返回读取到字符数,并把字符存储到buf数组中        System.out.println(num+":"+new String(buf));//结果:6:abcd(后面有两空格)        int num1=fr.read(buf);        System.out.println(num1+":"+new String(buf));//结果:6:adfalx(会把之前的覆盖掉)        int num2=fr.read(buf);        System.out.println(num1+":"+new String(buf));//6:ixixlx        int num3=fr.read(buf);        System.out.println(num3+":"+new String(buf));//-1:ixixlx(当读到-1直接返回)*/                      char[]buf=new char[1024];//一般设置1024的整数倍,以免反复执行下面的语句,提高效率        int len;        while((len=fr.read(buf))!=-1) {            System.out.println(new String(buf,0,len));        }    }}

写操作

package cn.itcast.p2.io.filewriter;//写文字到硬盘import java.io.FileWriter;import java.io.IOException;public class FileWriterDemo {    private static final String LINE_SEPARATOR = System.getProperty("line.separator");    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        //创建一个可以往文件中写入字符数据的字符输出流对象        /*         * 既然是往一个文件中写入文字数据,那么在创建对象时,就必须明确该文件(用于存储数据的目的地)         * 如果文件不存在,则会自动创建         * 如果文件存在,则会被覆盖         *          * *///      FileWriter fw=new FileWriter("demo.txt");//      如果构造函数中加入true,可以实现对文件进行续写        FileWriter fw=new FileWriter("demo.txt",true);        /*         * 调用Writer对象中的write(string)方法,写入数据         * 其实数据写入到临时存储缓冲区中         * *///      fw.write("abcde");        fw.write("abcd"+LINE_SEPARATOR+"adfal");//加入换行符        fw.write("xixix");//续写入文件        /*         * 进行刷新,将数据直接写到目的地中         * */        fw.flush();        /*         * 关闭流,关闭资源,在关闭流的时候会先调用flush刷新缓冲区中的数据到目的地         * */        fw.close();    }}

2.1.1 读写实例代码

package cn.itcast.p2.io.filewriter;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyTextTest {    /*     * 将C盘中的一个文件复制到D盘     * 思路:     * 1、需要读取源     * 2、将读到的原数据写入到目的地     * 3、既然是操作文本数据,使用字符流     * */    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        //1、读取一个已有的文本文件,使用字符读取流和文件相关联        FileReader fr=new FileReader("笔记.txt");        //2、创建一个目的地,用于存储读到数据        FileWriter fw=new FileWriter("copytext_1.txt");        //3、频繁的读写操作        int ch=0;        while((ch=fr.read())!=-1)        {            System.out.println(ch);            fw.write(ch);        }        //4、关闭流资源        fw.close();        fr.close();    }}

读写异常捕捉

package cn.itcast.p2.io.filewriter;//异常处理import java.io.FileWriter;import java.io.IOException;public class IOExceptionDemo {    private static final String LINE_SEPARATOR = System.getProperty("line.separator");    public static void main(String[] args) {        // TODO Auto-generated method stub        FileWriter fw=null;//在外面声明        try {            fw = new FileWriter("demo.txt");//在里面初始化  位置1            fw.write("abcd" + LINE_SEPARATOR + "adfal");//加入换行符  位置2        } catch (IOException e) {            // TODO: handle exception            System.out.println(e.toString());        }finally {            if(fw!=null)//需要判断它是否为空才能进行下面的fw.close()操作,因为位置1抛出异常时(路径不存在),fw就不存在,为此它也会抛异常                            //当有限制时,就可以很明确的捕捉到是否是位置2发生写入异常                try {                fw.close();//如果不再外面声明,此处就会报错,fw变量没被定义            } catch (IOException e) {                // TODO Auto-generated catch block                throw new RuntimeException("关闭失败");            }//        }    }}
package cn.itcast.p2.io.filewriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyTextTest_2 {    private static final int BUFFER_SIZE = 1024;    public static void main(String[] args) {        // TODO Auto-generated method stub        FileReader fr=null;        FileWriter fw=null;        try {            fr=new FileReader("笔记.txt");            fw=new FileWriter("copytest_2.txt");            //创建一个临时容器,用于缓存读取到的字符            char[] buf=new char[BUFFER_SIZE];            //定义一个变量记录读取到的字符数(其实就是往数组里装的字符个数)            int len=0;            while((len=fr.read(buf))!=-1) {                fw.write(buf, 0, len);            }        }        catch(Exception e) {            throw new RuntimeException("读写失败");        }finally {            if(fw!=null)                try {                    fw.close();                }catch(IOException e) {                }            if(fr!=null)                try {                    fr.close();                }catch(IOException e){                }        }    }}

获取文本的行号

package cn.itcast.p2.io.wrapper;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.io.LineNumberReader;public class LineNumberReaderDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        FileReader fr=new FileReader("笔记.txt");        LineNumberReader lnr=new LineNumberReader(fr);        String line=null;//      lnr.setLineNumber(100);//设置文本开始行        while((line=lnr.readLine())!=null)        {            System.out.println(lnr.getLineNumber()+":"+line);//获取文本的行号        }        lnr.close();    }}

2.2字符流缓冲区读写操作

package cn.itcast.p2.io.charstream.test;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyTextByBufTest {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        FileReader fr=new FileReader("buf.txt");        BufferedReader bufr=new BufferedReader(fr);        FileWriter fw=new FileWriter("buf_copy2.txt");        BufferedWriter bufw=new BufferedWriter(fw);        String line=null;        //按行读写        while((line=bufr.readLine())!=null) {            bufw.write(line);            bufw.newLine();            bufw.flush();        }        /*int ch=0;        while((ch=bufr.read())!=-1) {            bufw.write(ch);        }*/        bufw.close();        bufr.close();    }}
package cn.itcast.p2.io.charstream.test;import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;public class BufferWriterDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        FileWriter fw=new FileWriter("buf.txt");        //为了提高写入的效率,使用了字符流的缓冲区        //创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联        BufferedWriter bufw=new BufferedWriter(fw);        //使用缓冲区的写入方法将数据先写入到缓冲区中        bufw.write("abcd");        bufw.newLine();//写入换行符(只是缓冲区对象有),封装的是System.getProperty("line.separator")        bufw.write("afhsdnajkl");         //使用缓冲区的刷新方法将数据刷到目的地中        bufw.flush();        //关闭缓冲区的(其实关闭的就是被缓冲的流对象)        bufw.close();    }}
package cn.itcast.p2.io.charstream.test;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;public class BufferedReaderDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub    demo();     FileReader fr=new FileReader("buf.txt");    BufferedReader bufr=new BufferedReader(fr);    String line=null;    while((line=bufr.readLine())!=null) {        System.out.println(line);//读取文本的一行    }    bufr.close();    }    private static void demo() throws IOException {        // TODO Auto-generated method stub        FileReader fr=new FileReader("buf.txt");        char[]buf=new char[1024];        int len=0;        while((len=fr.read(buf))!=-1) {            System.out.println(new String(buf,0,len));        }        fr.close();    }}

2.2.1自定义缓冲区
自定义类

package cn.itcast.p2.io.charstream.mybuffer;import java.io.FileReader;import java.io.IOException;/* * 自定义的读取缓冲区,其实就是模拟一个BufferedReader * 分析: * 缓冲区中无非就是封装了数组 * 并对外提供了更多的方法对数组进行访问 * 其实这些方法最终操作的都是数组的角标 *  * 缓冲的原理: * 其实就是从源中获取一批数据装进缓冲区中 * 再从缓冲区中不断的取出一个一个数据 *  * 在此次取完后,再从源中继续取一批数据进缓冲区 * 当源中的数据取光时,用-1作为结束标记 * */public class MyBufferReader {    private FileReader r;    //定义一个数组作为缓冲区    private char[]buf=new char[1024];    //定义一个指针用于操作这个数组中的元素,当操作到最后一个元素后,指针归零    private int pos=0;    //定义一个计数器用于记录缓冲区中的数据个数,当该数据减到0,就从源中继续获取数据到缓冲区中    private int count=0;    MyBufferReader(FileReader r) {        this.r=r;    }    /*     * 该方法从缓冲区中一次取一个字符     *      * */    public int myRead() throws IOException {        if(count==0)        {            count=r.read(buf);        }        if(count<0)            return -1;        char ch=buf[pos++];        count--;        return ch;        /*//1、从源中获取一批数据到缓冲区中,需先做判断,只有计数器为0时,才需要从源中获取数据        if(count==0) {            count=r.read(buf);            if(count<-1)                 return -1;            //每次获取数据到缓冲区后,角标归零.            pos=0;            char ch=buf[pos];            pos++;            count--;            return ch;        }else if(count>0) {            char ch=buf[pos];            pos++;            count--;            return ch;        }*/    }    public String myReadLine() throws IOException {        StringBuilder sb=new StringBuilder();        int ch=0;        while((ch=myRead())!=-1) {            if(ch=='\r')                 continue;            if(ch=='\n')                return sb.toString();            sb.append((char)ch);        }        if(sb.length()!=0)//没有这个的话,如果最后一行后面没有回车则最后一行打印不出来            return sb.toString();        return null;    }    public void myClose() throws IOException    {        r.close();    }}

自定义缓冲区应用

package cn.itcast.p2.io.charstream.mybuffer;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;public class MyBufferedReaderDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub//  demo();     FileReader fr=new FileReader("buf.txt");    MyBufferReader bufr=new MyBufferReader(fr);    String line=null;    while((line=bufr.myReadLine())!=null) {        System.out.println(line);//读取文本的一行    }    bufr.myClose();    }    private static void demo() throws IOException {        // TODO Auto-generated method stub        FileReader fr=new FileReader("buf.txt");        char[]buf=new char[1024];        int len=0;        while((len=fr.read(buf))!=-1) {            System.out.println(new String(buf,0,len));        }        fr.close();    }}

3、字节流读写操作
3.1 字节流读写示例

package cn.itcast.p2.io.bytestream.demo;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class ByteStreamDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        demo_write();        demo_read();    }    private static void demo_read() throws IOException {        // TODO Auto-generated method stub        //创建一个读取流对象和指定文件关联        FileInputStream fis=new FileInputStream("bytesdemo.txt");        byte[]buf=new byte[fis.available()];//文件长度,少用,万一文件16个G,导致内存溢出        fis.read(buf);        System.out.println(new String(buf));        //一次读取一个数组长度,建议使用这种        /*byte[] buf=new byte[1024];        int len=0;        while((len=fis.read(buf))!=-1) {            System.out.println(new String(buf,0,len));        }*/        /*//一次读取一个字节        int ch=0;         while((ch=fis.read())!=-1)        {            System.out.println((char)ch);        }*/        fis.close();    }    private static void demo_write() throws IOException {        // TODO Auto-generated method stub//      1、创建字节输出流对象,用于操作文件        FileOutputStream fos=new FileOutputStream("bytesdemo.txt");//      2、写数据,直接写入到了目的地中        fos.write("abcddasf".getBytes());        fos.close();//关闭资源动作    }}

3.2 字节流缓冲区读写示例

package cn.itcast.p2.io.bytestream.demo;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class CopyMp3Test {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        copy_1();        copy_2();    }//使用缓冲区复制音频文件    private static void copy_2() throws IOException {        // TODO Auto-generated method stub        FileInputStream fis=new FileInputStream("0.mp3");        BufferedInputStream bufis=new BufferedInputStream(fis);        FileOutputStream fos=new FileOutputStream("2.mp3");        BufferedOutputStream bufos=new BufferedOutputStream(fos);        int ch=0;        while((ch=bufis.read())!=-1) {            fos.write(ch);         }        bufis.close();        bufos.close();    }    private static void copy_1() throws IOException {        // TODO Auto-generated method stub        FileInputStream fis=new FileInputStream("0.mp3");        FileOutputStream fos=new FileOutputStream("1.mp3");        byte[]buf=new byte[1024];        int len=0;        while((len=fis.read(buf))!=-1) {            fos.write(buf,0,len);        }        fos.close();        fis.close();    }}

4 装饰设计模式
装饰设计模式:
对一组对象的功能进行增强时,就可以使用该模式进行问题的增强

装饰和继承都能事项一样的特点:进行功能的拓展。有什么区别呢?
首先有一个继承体系。
writer
|—TextWriter:用于操作文本
|—MediaWriter:用于操作媒体
想要对操作的动作进行效率的提高。
按照面向对象,可以通过继承对具体的进行功能的扩展
效率提高需要加入缓冲技术

Writer
|—TextWriter:用于操作文本
|—BufferTextWriter:加入了缓冲技术的操作文本对象
|—MediaWriter:用于操作媒体
|—BufferMediaWriter:

如果这个体系进行功能扩展,有多个流对象
那么这个流要提高效率,是不是也要产生子类呢?这时就会发现只为提高功能进行的扩展
导致继承体系越来越臃肿,不够灵活

既然加入的都是同一种技术—缓冲
前一种是让缓冲和具体的对象相结合
可不可以将缓冲进行单独的封装,哪个对象需要缓冲就将那个对象和缓冲关联

class Buffer{
Buffer(TextWriter w)
{}
Buffer(MediaWriter w)
{}
}

装饰类:
class BufferWriter extends Writer{
BufferWriter(Writer w)
{
}
}

Writer
|—TextWriter:用于操作文本
|—MediaWriter:用于操作媒体
|—BufferWriter:用于提高效率
装饰比继承灵活
特点:装饰类和被装饰类都必须所属同一个接口或者父类

举例

package cn.itcast.p2.io.wrapper;public class PersonDemo {    public static void main(String[] args) {        // TODO Auto-generated method stub        Person p=new Person();//      p.chifan();        NewPerson p1=new NewPerson(p);        p1.chifan();        NewPerson2 p2=new NewPerson2();        p2.chifan();    }}class Person{    void chifan() {        System.out.println("吃饭");    }}//这个类的出现是为了增强Person而出现的class NewPerson{    private Person p;    NewPerson(Person p){        this.p=p;    }    public void chifan() {        System.out.println("开胃酒");        p.chifan();        System.out.println("甜点");    }}//继承实现Person的增强class NewPerson2 extends Person{    public void chifan() {        System.out.println("开胃酒");        super.chifan();        System.out.println("甜点");    }}

5、转换流操作

这里写图片描述

5.1 字节流和字符流之间的转换(没有使用转换流)

package cn.itcast.p1.transstream.demo;import java.io.IOException;import java.io.InputStream;/* * 读取一个键盘录入的数据,并打印在控制台上 * 键盘本身就是一个标准的输入设备 * 对于Java而言,对于这种输入设备都有对应的对象 *  * */public class TransStreamDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub//      readKey();        readKey2();    }    private static void readKey2() throws IOException {        // TODO Auto-generated method stub        /*         * 获取用户键盘录入的数据         * 并将数据变成大写显示在控制台上         * 如果用户输入的是over,结束键盘录入         *          * 思路:         * 1、因为键盘录入只读取一个字节,要判断是否是over,需要将读取到的字节拼成字符串         * 2、那就需要一个容器,StringBuilder         * 3、在用户回车之前将录入的数据变成字符串判断即可         *          * *///      1、创建容器        StringBuilder sb=new StringBuilder();//      2、获取键盘读取流        InputStream in=System.in;//      3、定义变量记录读取到的字节,并循环获取        int ch=0;        while((ch=in.read())!=-1) {//          在存储之前需要判断是否是换行标记,因为换行标记不存储            if(ch=='\r')                continue;            if(ch=='\n') {                String temp=sb.toString();                if("over".equals(temp))                    break;                System.out.println(temp.toUpperCase());                sb.delete(0, sb.length());            }            else//          将读取到的字节存储到StringBuilder中                sb.append((char)ch);        }        System.out.println(sb);    }    private static void readKey() throws IOException {        // TODO Auto-generated method stub        InputStream in=System.in;        int ch=in.read();//阻塞式方法,没有数据就一直等        System.out.println(ch);//      in.close();//默认的输入设备和输出设备都不需要关闭,一旦关闭则整个//      InputStream in=System.in;int ch=in.read();就会报错,这个流就不存在了,它是随着系统的关闭而消失的,系统运行而存在的(除非系统关了重启)    }}

5.2 转换流
转换流:
InputStreamReader:字节到字符的桥梁。解码
OutputStreamWriter:字符到字节的桥梁。编码
流的操作规律:
之所以要弄清楚这个规律,是因为流对象太多,开发时不知道用哪个对象合适。
想要知道开发时用到哪些对象,只要通过四个明确即可。

1、明确源和目的(汇)
源:InputStream Reader
目的:OutputStream Writer

2、明确数据是否是纯文本数据
源:是纯文本:Reader
否:InputStream
目的:是纯文本:Writer
否:OutputStream
到这里,就可以明确需求中具体要使用哪个体系

3、明确具体的设备
源设备:
硬盘:File
键盘:System.in
内存:数组(缓冲区)
网络:Socket流
目的设备:
硬盘:File
控制台:System.out
内存:数组
网络:Socket流

4、是否需要其他额外功能
1、是否需要高效(缓冲区);
是,就加上buffer;

例如:
需求1:复制一个文本文件
1、明确源和目的
源:InputStream Reader
目的:OutputStream Writer
2、是否是纯文本
是!
源:Reader
目的:Writer
3、明确具体设备
源:
硬盘:File
目的:
硬盘:File
FileReader fr=new FileReader(“a.txt”)
FileWriter fw=new FileWriter(“b.txt”)
4、需要额外功能吗?
需要,需要高效
BufferedReader bufr=new BufferedReader(new FileReader(“a.txt”));
BufferedWriter bufw=new BufferedWriter(new FileWriter(“b.txt”));

需求2:将键盘输入数据存储到硬盘
1、明确源和目的
源:InputStream Reader
目的:OutputStream Writer
2、明确是否是纯文本
是!
源:Reader
目的:Writer
3、明确具体设备
源:
键盘 System.in
目的地:
硬盘 File
InputStream in=System.in
FileWriter fw=new FileWriter(“a.txt”);
这样做可以完成,但是麻烦,将读取的字节数据转成字符串,再由字符流操作
4、需要额外功能吗?
需要。转换将字节流转成字符流。因为明确源是Reader,这样操作文本数据更加便捷
所以要将已有的字节流转成字符流,使用字节—》字符。InputStreamReader
InputStreamReader isr=new InputStreamReader(System.in);
FileWriter fw=new FileWriter(“b.txt”);
还需要功能吗?
需要高效!
BufferReader bufr=new BufferReader(new InputStreamReader(System.in));
BufferWriter bufw=new BufferWriter(FileWriter(“b.txt”));

需求3:将一个文本文件数据显示在控制台上
1、明确源和目的
源:InputStream Reader
目的:OutputStream Writer
2、明确是否是纯文本
是!
源:Reader
目的:Writer
3、明确具体的设备
源:
硬盘 File
目的:
控制台 System.out

FileReader fr=new FileReader("b.txt");OutputStream out=System.out;4、是否需要额外功能    需要转换.因为一个汉字是两个字节,输出是一个一个字节的输出转换成字符操作更加便捷    FileReader fr=new FileReader("a.txt");    OutputStreamWriter osw=new OutputStreamWriter(System.out);    需要高效    BufferedReader bfr=new BufferedReader(new FileReader("a.txt"));    BufferedReader bfw=new BufferedWriter(new OutputStreamWriter(System.out));

需求4:读取键盘录入数据,显示在控制台上
1、明确源和目的
源:InputStream Reader
目的:OutputStream Writer
2、明确是否是纯文本
是!
源:Reader
目的:Writer

3、明确设备    源:        键盘  System.in    目的地:        控制台 System.out4、是否需要额外功能?    需要转换,因为都是字节流,但是操作的确实文本数据    所以使用字符流操作起来更为便捷    InputStreamReader isr=new InputStreamReader(System.in);    OutputStreamWriter osw=new OutputStreamWriter(System.out);    为了将其高效    BufferReader bufr=new BufferReader(new InputStreamReader(System.in));    BufferWriter bufw=new BufferWriter(new OutputStreamWriter(System.out));5、将一个中文字符串数据按照指定的编码表写入到一个文本文件中    1、目的    OutputStream    writer    2、是纯文本  Writer    3、设备:硬盘 File    FileWriter fw=new FileWriter("a.txt")    fw.write("你好");    注意:既然需求已经明确了指定编码表的动作    那就不可以使用FileWriter,因为FileWriter内部是使用默认的本地编码表    只能使用其父类 OutputStreamWriter    OutputStreamWriter接收一个字节输出流对象,既然是操作文本文件,那么该对象应该是FileOutputStream    OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("a.txt"),编码名字);    需要高效吗?    BufferWriter bufw=new BufferWriter(new OutputStreamWriter(new FileOutputStream("a.txt"),编码名字));

什么时候使用转换流呢?
1、源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁
提高对文本操作的便捷
2、一旦操作文本涉及到具体的指定编码表时,必须使用转换流

5.2.1 字节流转成字符流

package cn.itcast.p1.transstream.demo;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;public class TransStreamDemo_2 {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub//      字节流        InputStream in=System.in;//      将字节转成字符的桥梁,转换流        InputStreamReader isr=new InputStreamReader(in);//      字符流        BufferedReader bufr=new BufferedReader(isr);        String line=null;        while((line=bufr.readLine())!=null) {            if("over".equals(line))                break;            System.out.println(line.toUpperCase());        }    }}

缓冲区+转换流

package cn.itcast.p1.transstream.demo;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;public class TransStreamDemo_3 {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));        BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));        String line=null;        while((line=bufr.readLine())!=null) {            if("over".equals(line))                break;            bufw.write(line.toUpperCase());            bufw.newLine();            bufw.flush();        }    }}

编码问题

这里写图片描述

package cn.itcast.p1.transstream.demo;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.UnsupportedEncodingException;public class TransStreamDemo_5 {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        writeText();        writeText_1();        writeText_2();        readText();        readText_1();    }    private static void readText_1() throws IOException {        // TODO Auto-generated method stub//      用什么编码就用什么解码        InputStreamReader isr=new InputStreamReader(new FileInputStream("gbk_2.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();    }    private static void readText() throws IOException {        // TODO Auto-generated method stub        FileReader fr=new FileReader("gbk_2.txt");//因为编码是gbk,而默认编码是utf-8所以解码的时候乱码        char[] buf=new char[10];        int len=fr.read(buf);        String str=new String(buf,0,len);        System.out.println(str);        fr.close();    }    private static void writeText_2() throws IOException {        // TODO Auto-generated method stub//      用utf-8进行编码其中的文本        OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("u8_1.txt"),"utf-8");        osw.write("你好");        osw.close();    }    private static void writeText_1() throws IOException {        // TODO Auto-generated method stub        OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("gbk_2.txt"),"GBK");        /*         * FileWriter fw=new FileWriter("gbk_1.txt");         * 这句代码和上面的功能是一样的         * FileWriter:其实就是转换流指定了本机默认码表的体现。而且这个转换流的子类对象,可以方便操作文本文件         *              简单说:操作文件的字节流+本机默认的编码表(utf-8)         * 如果操作文本文件需要明确具体的编码。FileWriter就行不通了,它不能改变编码,只能使用转换流了         *          * */        osw.write("你好");        osw.close();    }    private static void writeText() throws IOException {        // TODO Auto-generated method stub        FileWriter fw=new FileWriter("gbk_1.txt");        fw.write("你好");        fw.close();    }}

6、文件操作

6.1 封装成文件对象

package cn.itcast.p2.File.demo;import java.io.File;public class FileDemo {    public static void main(String[] args) {        // TODO Auto-generated method stub        constructorDemo();    }    private static void constructorDemo() {        // TODO Auto-generated method stub//      可以将一个已存在的或者不存在的文件或者目录封装成File文件对象        File file=new File("a.txt");//      以下两种方法和上面一样,只不过下面的将路径和文件名分开了,上面的可以使用绝对路径        /*File f2=new File("c:\\","a.txt");        File f=new File("c:\\");        File f3=new File(f,"a.txt");*///      File.separator表示路径分割符:window下是:\\  Linux下是:\        File f4=new File("c:"+File.separator+"abc"+File.separator+"a.txt");        System.out.println(f4);    }}

6.2 文件的基本操作

package cn.itcast.p2.File.demo;import java.io.File;import java.io.IOException;import java.text.DateFormat;import java.util.Date;public class FileMethodDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        /*         * File对象的常见方法         *  1、获取         *      1.1获取文件名称         *      1.2获取文件路径         *      1.3获取文件大小         *      1.4获取文件修改时间         *  2、创建与删除         *      boolean          *  3、判断         *  4、重命名         *          * *///      getDemo();//      createAndDeleteDemo();//      isDemo();//      renameToDemo();        listRootDemo();    }    private static void listRootDemo() {        // TODO Auto-generated method stub        File file=new File("d:\\");        System.out.println("getFreeSpace:"+file.getFreeSpace());//打印空闲空间        System.out.println("getTotalSpace:"+file.getFreeSpace());//打印总共空间        System.out.println("getUsableSpace:"+file.getFreeSpace());//打印可用空间//      File[]files=File.listRoots();//      for(File file:files)//          System.out.println(file);//打印根目录,即C:\ D:\ E:\  F:\    }    private static void renameToDemo() {        // TODO Auto-generated method stub        File f1=new File("a.txt");        File f2=new File("aa.txt");        boolean b=f1.renameTo(f2);//将a.txt重命名为aa.txt,如果是aa.txt和a.txt是不同的盘,则变成了剪切并重命名,a.txt不存在了,变成了其他盘的aa.txt        System.out.println("b="+b);    }    private static void isDemo() {        // TODO Auto-generated method stub        File f=new File("a.txt");//      boolean b=f.exists();//判断文件是否存在//      System.out.println(b);        System.out.println(f.isDirectory());//判断是否是目录        System.out.println(f.isFile());//判断是否是文件,一般先判断是否存在再判断文件与否,假如不存在,则会返回false    }    private static void createAndDeleteDemo() throws IOException {        // TODO Auto-generated method stub        File file=new File("file.txt");        /*         * 和输出流不一样,如果文件不存在则创建,存在则不创建         * *///      boolean b=file.createNewFile();//创建新文件//      System.out.println("b="+b);        //创建目录        /*File dir=new File("abc");         * File dir1=new File("abc\\d\\d\cc");        boolean b=dir1.mkdirs();//创建多级目录        dir.mkdir();//创建单级目录        System.out.println("b="+b);        System.out.println(dir.delete());//删除目录,里面如果有文件则删不掉,删除多级目录时只删除了最里面的那个目录        */        boolean b=file.delete();//删除文件    }    private static void getDemo() {        // TODO Auto-generated method stub        File file=new File("a.txt");        String name=file.getName();//获取文件名称        String absPath=file.getAbsolutePath();//获取文件绝对路径        String path=file.getPath();//获取相对路径        long len=file.length();//获取文件大小        long time=file.lastModified();//获取最近一次修改时间        Date date=new Date(time);        DateFormat dateFormat=DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);        String str_time=dateFormat.format(date);        System.out.println("parent path:"+file.getParent());//获取文件的父目录        System.out.println(name);        System.out.println(absPath);        System.out.println(path);        System.out.println(len);        System.out.println(time);        System.out.println(str_time);    }}

6.3 过滤文件

过滤器

隐藏文件的过滤器

package cn.itcast.p2.filter;import java.io.File;import java.io.FileFilter;import java.nio.file.Path;public class FilterByHadden implements FileFilter {    @Override    public boolean accept(File pathname) {        // TODO Auto-generated method stub        return !pathname.isHidden();    }}

后缀名的过滤器(.java)

package cn.itcast.p2.filter;import java.io.File;import java.io.FilenameFilter;public class filterByName implements FilenameFilter {    @Override    public boolean accept(File dir, String name) {        // TODO Auto-generated method stub        return name.endsWith(".java");    }}

后缀名的通用过滤器

package cn.itcast.p2.filter;import java.io.File;import java.io.FilenameFilter;public class ShufflxFilter implements FilenameFilter {    private String suffix;    @Override    public boolean accept(File dir, String name) {        // TODO Auto-generated method stub        return name.endsWith(suffix);    }    public ShufflxFilter( String suffix) {        super();        this.suffix=suffix;        // TODO Auto-generated constructor stub    }}

过滤文件的代码示例

package cn.itcast.p2.File.demo;import java.io.File;import cn.itcast.p2.filter.FilterByHadden;import cn.itcast.p2.filter.ShufflxFilter;public class FileListDemo {    public static void main(String[] args) {        // TODO Auto-generated method stub//      listDemo();//      listDemo_2();        listDemo_3();    }    private static void listDemo_3() {        // TODO Auto-generated method stub        File dir=new File("c:\\");        File[]files=dir.listFiles(new FilterByHadden());        for(File file:files) {            System.out.println(file);        }    }    private static void listDemo_2() {        // TODO Auto-generated method stub        File dir=new File("c:\\");//      String[]names=dir.list(new filterByName());//过滤器        String[]names=dir.list(new ShufflxFilter(".java"));//根据自定义后缀名过滤文件        for(String name:names)        {            System.out.println(name);        }    }    private static void listDemo() {        // TODO Auto-generated method stub        File file=new File("c:\\");        /*         * 获取当前目录的文件以及文件夹名称,包含隐藏文件         * 调用list方法的File对象中封装的必须是目录         * 否则会发生NullPointerException异常         * 如果访问的是系统级目录也会发生指针异常         * 如果目录存在但是没有内容,会返回一个数组,但是长度为0         *          * */        String[]names=file.list();//获取当前目录的文件以及文件夹名称,包含隐藏文件        for(String name:names)        {            System.out.println(name);        }    }}

获取目录下的文件

package cn.itcast.p2.File.test;import java.io.File;/* * 需求:对指定目录进行所有内容的列出(包含子目录中的内容) * 也可以理解为深度遍历 *  * */public class FileTest {    public static void main(String[] args) {        // TODO Auto-generated method stub        File dir=new File("I:\\");        listAll(dir,0);    }    private static void listAll(File dir,int level) {        // TODO Auto-generated method stub//      获取指定目录下当前的所有文件夹或者文件对象        File[]files=dir.listFiles();        for(int x=0;x<files.length;x++) {            if(files[x].isDirectory()) {                listAll(files[x],level);            }            else                    System.out.println(getSpace(level)+files[x].getName());        }    }    private static String getSpace(int level) {        // TODO Auto-generated method stub        StringBuilder sb=new StringBuilder();        for(int x=0;x<level;x++) {            sb.append("|--");        }        return sb.toString();    }}

删除目录下的文件

package cn.itcast.p2.File.test;import java.io.File;/* * 删除一个带有内容的目录 * 原理:必须从最里面往外删 *  *  * */public class RemoveDirTest {    public static void main(String[] args) {        // TODO Auto-generated method stub        File dir=new File("");//      dir.delete();        removeDir(dir);    }    private static void removeDir(File dir) {        // TODO Auto-generated method stub        File[]files=dir.listFiles();        for(File file:files) {            if(file.isDirectory()) {                removeDir(file);            }else {                System.out.println(file+":"+file.delete());            }        }        System.out.println(dir+":"+dir.delete());    }}

7 Properties
7.1 Properties基本操作

package cn.itcast.p2.properties;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.util.Properties;import java.util.Set;public class PropertiesDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        /*         * Map         *  |--Hashtable         *      |--Properties:         *          * Properties集合:         * 特点:         * 1、该集合中的键和值都是字符串类型         * 2、集合中的数据保存到流中,或者从流获取(字节流、字符流都行)         *          * 通常该集合用于操作以键值对形式存在的配置文件         *          *          *          * *///      propertiesDemo();//      methodDemo();//      methodDemo_2();//      methodDemo_3();        methodDemo_4();    }    private static void methodDemo_4() throws IOException {        // TODO Auto-generated method stub//      对已有的配置文件中的信息进行修改        /*         * 读取这个文件         * 并将这个文件中的键值数据存储到集合中         * 再通过集合对数据进行修改         * 再通过流将修改后的数据存储到文件中         * */        File file=new File("info.txt");        if(!file.exists()) {            file.createNewFile();        }        FileReader fr=new FileReader(file);//      FileWriter fw=new FileWriter(file);//放到这个位置里面将只有wangwu=16这一条信息//      创建集合存储配置信息        Properties prop=new Properties();//      将流中信息存储到集合中        prop.load(fr);        prop.setProperty("wangwu", "16");//      创建输出流        FileWriter fw=new FileWriter(file);//因为这个file也就是info.txt是新建的(覆盖了之前的info.txt),将集合中的所有信息输出到里头//      将集合中的信息存储到输出流中        prop.store(fw, "modify wangwu");        fw.close();        fr.close();    }    private static void methodDemo_3() throws IOException {        // TODO Auto-generated method stub        Properties prop=new Properties();//      集合中的数据来自于一个文件//      注意:必须保证该文件中的数据是键值对//      需要使用到读取流        FileInputStream fis=new FileInputStream("info.txt");//      使用load方法        prop.load(fis);        prop.list(System.out);    }    private static void methodDemo_2() throws IOException {        // TODO Auto-generated method stub        Properties prop=new Properties();//      存储元素        prop.setProperty("zhangsan", "30");        prop.setProperty("lisi", "31");        prop.setProperty("wangwu", "26");        prop.setProperty("zhaoliu", "20");//      想要将这些集合中的字符串键值信息持久化存储到文件中//      需要关联输出流        FileOutputStream fos=new FileOutputStream("info.txt");//      将集合中数据存储到文件中,使用Store方法        prop.store(fos, "name+age");        fos.close();    }    private static void methodDemo() {        // TODO Auto-generated method stub//      演示Properties集合和流对象相结合的功能        Properties prop=new Properties();//      存储元素        prop.setProperty("zhangsan", "30");        prop.setProperty("lisi", "31");        prop.setProperty("wangwu", "26");        prop.setProperty("zhaoliu", "20");        prop.list(System.out);//将存储的元素打印输出到控制台    }    /*     * Properties集合的存和取     *      *      * */    private static void propertiesDemo() {        // TODO Auto-generated method stub//      创建一个Properties集合        Properties prop=new Properties();//      存储元素        prop.setProperty("zhangsan", "30");        prop.setProperty("lisi", "31");        prop.setProperty("wangwu", "26");        prop.setProperty("zhaoliu", "20");//      修改元素        prop.setProperty("wangwu", "36");//      取出所有元素        Set<String>names=prop.stringPropertyNames();        for(String name:names) {            String value=prop.getProperty(name);            System.out.println(name+":"+value);        }    }}

7.2 Properties案例示例

package cn.itcast.p2.properties;import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.io.FilenameFilter;import java.io.IOException;import java.util.ArrayList;import java.util.List;/* * 获取指定目录下,指定扩展名的文件(包含子目录中的) * 这些文件的绝对路径写入到一个文本文件中 *  * 简单的说,就是建立一个指定扩展名的文件的列表 *  * 思路: * 1、必须进行深度遍历 * 2、要在遍历的过程中进行过滤,将符合条件的内容都存储到容器中 * 3、对容器中的内容进行遍历并将绝对路径写入到文件中 *  *  * */public class Test {    public static void main(String[] args) {        // TODO Auto-generated method stub        File dir=new File("J:\\协同中心");        FilenameFilter filter=new FilenameFilter() {            @Override            public boolean accept(File dir, String name) {                // TODO Auto-generated method stub                return name.endsWith(".xlsx");            }        };        List<File>list=new ArrayList<File>();        getFiles(dir,filter,list);        File destfile=new File(dir,"javalist.txt");        writerToFile(list,destfile);    }    private static void getFiles(File dir,FilenameFilter filter,List<File>list) {        // TODO Auto-generated method stub        File[]files=dir.listFiles();        for(File file:files) {            if(file.isDirectory()) {                getFiles(file,filter,list);            }else {//              对过滤器进行过滤,将符合条件的对象存储到集合中                if(filter.accept(dir, file.getName())) {                    list.add(file);                }            }        }    }    public static void writerToFile(List<File>list,File destFile) {        BufferedWriter bufw=null;            try {                bufw=new BufferedWriter(new FileWriter(destFile));                for(File file:list) {                    bufw.write(file.getAbsolutePath());                    bufw.newLine();                    bufw.flush();                }            } catch (IOException e) {                // TODO Auto-generated catch block                throw new RuntimeException("写入失败");            }finally {                if(bufw!=null)                    try {                        bufw.close();                    }catch(IOException e){                        throw new RuntimeException("关闭失败");                    }            }    }}
package cn.itcast.p2.properties;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.Properties;/* * 定义功能,获取一个应用程序运行的次数,如果超过5次,给出使用次数已到请注册的提示,并终止程序的运行 * 思路: * 1、应该有计数器 * 每次程序启动都需要计数一次,并且是在原有的次数上进行计数 * 2、计数器就是一个变量,程序启动时进行计数,计数器必须存在于内存并进行运算 * 可是程序一结束,计数器就消失了,那么再次启动该程序,计数器又被重新初始化了 * 而我们需要多次启动同一个应用程序,使用的是同一个计数器 * 这就需要计数器的生命周期变长,从内存存储到硬盘文件中 * 3、如何使用计数器呢? *  首先,程序启动时,应该先读取这个用于记录计数器信息的配置文件,获取上一次计数器次数 *  其次,对该次数进行自增,并将自增后的次数重新存储到配置文件中。 * 4、文件中的信息该如何进行存储并体现? * 直接存储次数值可以,但是不明确该数据的含义。所以起名字变得很重要 * 这就有了名字和值的对应,所以可以使用键值对 * 映射关系可以使用map集合搞定,由于又需要读取硬盘上的数据,所以用map+io=properties搞定 *  * */public class PropertiesTest {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        getAppCount();    }     private static void getAppCount() throws IOException {        // TODO Auto-generated method stub//      将配置文件封装成File对象        File confile=new File("count.properties");        if(!confile.exists()) {            confile.createNewFile();        }        FileInputStream fis=new FileInputStream(confile);        Properties prop=new Properties();        prop.load(fis);//      从集合中通过键获取次数        String value=prop.getProperty("time");//      定义计数器,记录获取到的次数        int count=0;        if(value!=null) {            count=Integer.parseInt(value);            if(count>=5) {                System.out.println("使用次数已到,请注册");                throw new RuntimeException();            }        }        count++;//      将改变后的次数重新存储到集合中        prop.setProperty("time", count+"");        FileOutputStream fos=new FileOutputStream(confile);        prop.store(fos, "");        fos.close();        fis.close();    }}

8 其他流
8.1 打印流

package cn.itcast.p2.print.demo;import java.io.FileNotFoundException;import java.io.PrintStream;public class PrintDemo {    public static void main(String[] args) throws FileNotFoundException {        // TODO Auto-generated method stub        /*         * PrintStream:         * 1、提供了打印方法可以对多种数据类型值进行打印,并保持数据的表示形式         * 2、它不抛IOException         *          * 构造函数,接收三种类型的值:         * 1、字符串路径         * 2、File对象         * 3、字节输出流         *          * */        PrintStream out=new PrintStream("print.txt");//      out.write(97);//只将低8为转成字符写入进去        out.print(97);//将97先变成字符保持原样将数据打印到目的地        out.close();    }}
package cn.itcast.p2.print.demo;import java.io.BufferedReader;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;public class PrintWriterDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        /*         * PrintWriter:字符打印流         * 构造函数参数:         * 1、字符串路径         * 2、File对象         * 3、字节输出流         * 4、字符输出流         *          * */        BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));//      PrintWriter out=new PrintWriter(System.out,true);//加了true可以自动刷新(相当于位置1的功能)        PrintWriter out=new PrintWriter(new FileWriter("out.txt"),true);//写入到文件中        String line=null;        while((line=bufr.readLine())!=null) {            if("over".equals(line))                break;            out.println(line.toUpperCase());//          out.flush();//位置1        }        out.close();        bufr.close();    }}

8.2 序列流

package cn.itcast.p2.print.demo;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.Enumeration;public class SequenceInputStreamDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        /*         * 需求:将1.txt 2.txt 3.txt文件中的数据合并到一个文件中         *          * */        /*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();*///      上面方法也可,建议用下面的        ArrayList<FileInputStream>al=new ArrayList<FileInputStream>();        for(int x=1;x<=3;x++) {            al.add(new FileInputStream(x+".txt"));        }        Enumeration<FileInputStream>en=Collections.enumeration(al);//将列表转成枚举        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();    }}

8.2.1 序列流案例示例

文件切割

package cn.itcast.io.p1.splitfile;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.Properties;public class SplitFileDemo {    private static final int SIZE = 1024*1024;    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        //切割文件        File file=new File("J:\\01.mp3");//      splitFile(file);//      文件切割+配置文件        splitFile_2(file);    }    private static void splitFile_2(File file) throws IOException{        // TODO Auto-generated method stub//      用读取流关联源文件        FileInputStream fis=new FileInputStream(file);//      定义一个1M的缓冲区        byte[]buf=new byte[SIZE];//      创建目的        FileOutputStream fos=null;        int len=0;        int count=1;        /*         * 切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数,以方便于合并。         * 这个信息为了进行描述,使用键值对的方式。用到了properties对象         *          * */        Properties prop=new Properties();        File dir=new File("J:\\partfiles");        if(!dir.exists())            dir.mkdirs();        while((len=fis.read(buf))!=-1) {            fos=new FileOutputStream(new File(dir,(count++)+".part"));            fos.write(buf,0,len);            fos.close();        }//      将被切割文件的信息保存到prop集合中        prop.setProperty("partcount", count+"");        prop.setProperty("filename", file.getName());        fos=new FileOutputStream(new File(dir,count+".properties"));//      将prop集合中的数据存储到文件中        prop.store(fos, "save file info");        fos.close();        fis.close();    }    private static void splitFile(File file) throws IOException {        // TODO Auto-generated method stub//      用读取流关联源文件        FileInputStream fis=new FileInputStream(file);//      定义一个1M的缓冲区        byte[]buf=new byte[SIZE];//      创建目的        FileOutputStream fos=null;        int len=0;        int count=1;        File dir=new File("J:\\partfiles");        if(!dir.exists())            dir.mkdirs();        while((len=fis.read(buf))!=-1) {            fos=new FileOutputStream(new File(dir,(count++)+".part"));            fos.write(buf,0,len);        }        fos.close();        fis.close();    }}

文件合并

过滤器

package cn.itcast.io.p1.splitfile;import java.io.File;import java.io.FilenameFilter;public class SuffixFilter implements FilenameFilter {    private String suffix;    @Override    public boolean accept(File dir, String name) {        // TODO Auto-generated method stub        return name.endsWith(suffix);    }    public SuffixFilter(String suffix) {        super();        this.suffix = suffix;    }}

合并

package cn.itcast.io.p1.splitfile;import java.io.File;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.Collections;import java.util.Enumeration;import java.util.Properties;public class MergeFileDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        //合并文件        File dir=new File("J:\\partfiles");//      mergeFile(dir);        mergeFile_2(dir);    }    private static void mergeFile_2(File dir) throws IOException {        // TODO Auto-generated method stub//      获取指定目录下的配置文件对象        File[]files=dir.listFiles(new SuffixFilter(".properties"));        if(files.length!=1)            throw new RuntimeException(dir+",该目录下没有properties扩展名的文件或者不唯一");//      记录配置文件对象        File confile=files[0];//      获取该文件中的信息        Properties prop=new Properties();        FileInputStream fis=new FileInputStream(confile);        prop.load(fis);        String filename=prop.getProperty("filename");        int count=Integer.parseInt(prop.getProperty("partcount"));//      获取该目录下的所有碎片文件        File[]partFiles=dir.listFiles(new SuffixFilter(".part"));        if(partFiles.length!=(count-1)) {            throw new RuntimeException("碎片文件不符合要求,个数不对!应该"+count+"个");        }//      将碎片文件和流对象关联并存储到集合中        ArrayList<FileInputStream>al=new ArrayList<FileInputStream>();        for(int x=1;x<partFiles.length;x++) {            al.add(new FileInputStream(partFiles[x]));        }//      将多个流合并成一个序列流        Enumeration<FileInputStream>en=Collections.enumeration(al);        SequenceInputStream sis=new SequenceInputStream(en);        FileOutputStream fos=new FileOutputStream(new File(dir,filename));        byte[] buf=new byte[1024];        int len=0;        while((len=sis.read(buf))!=-1) {            fos.write(buf, 0, len);        }        fos.close();        sis.close();    }    private static void mergeFile(File dir) throws IOException {        // TODO Auto-generated method stub        ArrayList<FileInputStream>al=new ArrayList<FileInputStream>();        for(int x=1;x<8;x++)        {            al.add(new FileInputStream(new File(dir,x+".part")));        }        Enumeration<FileInputStream>en=Collections.enumeration(al);        SequenceInputStream sis=new SequenceInputStream(en);        FileOutputStream fos=new FileOutputStream(new File(dir,"02.mp3"));        byte[] buf=new byte[1024];        int len=0;        while((len=sis.read(buf))!=-1) {            fos.write(buf, 0, len);        }        fos.close();        sis.close();    }}

8.2.2 对象序列化和反序列化

Person类实现Serializable接口

package cn.itcast.io.p2.bean;import java.io.Serializable;/* * Serializable用于给序列化的类加入ID号 * 用于判断类和对象是否是同一个版本 * transient:非静态数据不想被序列化可以使用这个关键字修饰 *  *  * */public class Person implements Serializable/*标记接口*/{    private static final long serialVersionUID=95271;//如果不自定义这个ID的话,系统会根据类型等自动算出一个ID,但这个根据编译器版本算出有所差异,所以                                                    //可能导致,在不同编译器下序列化的文件,在另一个版本编译器下不能被反序列化(序列化和反序列化的时候它需要校正这个ID)                                                    //为此,如果你将某个对象序列化后,然后将这个类中的private String name;改成public String name它也不能被反序列化,ID号变了    private String name;//  private transient String name;//不会被序列化//  private static int age;//静态数据的值不会被序列化,比如这个反序列化回来就是0(它在静态去,对象在堆区)    private int age;    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;    }    public Person(String name, int age) {        super();        this.name = name;        this.age = age;    }}

对象序列化和反序列化

package cn.itcast.io.p1.splitfile;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import cn.itcast.io.p2.bean.Person;public class objectStreamDemo {    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {        // TODO Auto-generated method stub        writeObject();        readObject();    }    private static void readObject() throws FileNotFoundException, IOException, ClassNotFoundException {        // TODO Auto-generated method stub        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("obj.object"));//      对象的反序列化        Person p=(Person)ois.readObject();        System.out.println(p.getName()+":"+p.getAge());        ois.close();    }    private static void writeObject() throws FileNotFoundException, IOException {        // TODO Auto-generated method stub        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("obj.object"));//      对象序列化,被序列化的对象必须实现Serializable接口        oos.writeObject(new Person("小强",30));        oos.close();    }}

9 其他流的读写

这里写图片描述

9.1 文件随机读写

package cn.itcast.io.p1.splitfile;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandomAccessFile;public class RandomAccessFileDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        /*         * RandomAccessFile不是io体系中的子类         * 特点:         * 1、该对象既能读又能写         * 2、该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素         * 3、可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置         * 4、其实该对象就是将字节输入流和输出流进行了封装         * 5、该对象的源和目的只能是文件(文本文件、媒体文件都可)         *          * */        writeFile();        readFile();        randomWrite();    }private static void randomWrite() throws IOException {        // TODO Auto-generated method stub        RandomAccessFile raf=new RandomAccessFile("ranacc.txt","rw");//      raf.write("赵六".getBytes());//这样的话就覆盖了之前数组里的张三和102(因为文件存在,它不会重新创建,也就是该数组存在,只会覆盖)//      raf.writeInt(102);//      往指定位置写入数据        raf.seek(5*8);//定位指针位置        raf.write("哈哈".getBytes());        raf.writeInt(108);        raf.close();    }private static void readFile() throws IOException {        // TODO Auto-generated method stub        RandomAccessFile raf=new RandomAccessFile("ranacc.txt","r");//      通过seek设置指针的位置//      raf.seek(1*8);//将指针移到第8个字节的位置        byte[]buf=new byte[6];//因为系统编码是utf-8,所以一个汉字是三个字节存储的,为此这里是6,如果变成4,则后面那个字是乱码        raf.read(buf);        String name=new String(buf);        int age=raf.readInt();        System.out.println("name="+name);        System.out.println("age="+age);        System.out.println("pos:"+raf.getFilePointer());//获取指针当前位置        raf.close();    }//  使用RandomAccessFile对象写入一些人员信息,比如姓名和年龄    private static void writeFile() throws IOException {        // TODO Auto-generated method stub        //如果文件不存在,则创建,如果文件存在,不创建        RandomAccessFile raf=new RandomAccessFile("ranacc.txt","rw");        raf.write("张三".getBytes());//写入的是字节//      raf.write(97);//只写低8位        raf.writeInt(908);//都写入        raf.close();    }}

9.2 基本数据类型的读写

package cn.itcast.io.p3.dataStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class DataStreamDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub//      操作基本数据类型的流        writeData();        readData();    }    private static void readData() throws IOException {        // TODO Auto-generated method stub        DataInputStream r=new DataInputStream(new FileInputStream("data.txt"));        System.out.println(r.readUTF());        r.close();    }    private static void writeData() throws IOException {        // TODO Auto-generated method stub        DataOutputStream dis =new DataOutputStream(new FileOutputStream("data.txt"));        dis.writeUTF("你好");//修改版的utf-8,前面有一个标识符        dis.close();    }}

9.3 字节数组读写

package cn.itcast.io.p3.byteStream;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;public class byteStreamDemo {    public static void main(String[] args) {        // TODO Auto-generated method stub        ByteArrayInputStream bis=new ByteArrayInputStream("abcd".getBytes());        ByteArrayOutputStream bos=new ByteArrayOutputStream();        int len=0;        while((len=bis.read())!=-1) {            bos.write(len);        }        System.out.println(bos.toString());    }}

9.4 管道流读写

package cn.itcast.io.p1.piped;import java.io.IOException;import java.io.PipedInputStream;import java.io.PipedOutputStream;public class pipedDemo {    public static void main(String[] args) throws IOException {        // TODO Auto-generated method stub        PipedInputStream input=new PipedInputStream();        PipedOutputStream output=new PipedOutputStream();        input.connect(output);//输入流连接输出流        new Thread(new Input(input)).start();        new Thread(new Output(output)).start();    }}class Input implements Runnable{    private PipedInputStream in;    Input(PipedInputStream in){        this.in=in;    }    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="+s);            in.close();        }catch(Exception e) {        }    }}class Output implements Runnable{    private PipedOutputStream out;    Output(PipedOutputStream out){        this.out=out;    }    public void run() {        try {            out.write("hi,管道来了".getBytes());        }catch(Exception e) {        }    }}

10. 编码解码
10.1 编码解码解析

package cn.itcast.io.p4.encode;import java.io.UnsupportedEncodingException;public class EncodeDemo {    public static void main(String[] args) throws UnsupportedEncodingException {        // TODO Auto-generated method stub        /*         * 字符串--->字节数组:编码         * 字节数组--->字符串:解码         *          * */        String str="你好";//      编码        byte[]buf=str.getBytes();//      byte[]buf=str.getBytes("GBK");//指定为GBK编码//      printBytes(buf);//      解码        String s1=new String(buf);//默认方式解码//      String s1=new String(buf,"utf-8");//指定码表解码        System.out.println("s1="+s1);        errorEncode();    }    private static void errorEncode() throws UnsupportedEncodingException {        // TODO Auto-generated method stub        /*         * 如果编码编错了,解不出来         * 如果编码对了,解错了,有可能有救         * */        String str="你好";        byte[]buf=str.getBytes();        String s1=new String(buf,"iso8859-1");//编码是utf-8,用iso8859-1解码        System.out.println("s1="+s1);//结果:s1=ä½ å¥½        byte[]buf2=s1.getBytes("iso8859-1");//获取源字节        String s2=new String(buf2,"utf-8");        System.out.println("s2="+s2);    }    private static void printBytes(byte[] buf) {        // TODO Auto-generated method stub        for(byte b:buf) {            System.out.println(b);        }    }}

10.2 编码解码案例

package cn.itcast.io.p4.encode;import java.io.UnsupportedEncodingException;public class Test {    public static void main(String[] args) throws UnsupportedEncodingException {        // TODO Auto-generated method stub        /*         * 在java中,字符串"abcd"与字符串"ab你好"的长度是一样,都是四个字节。         * 但对应的字节数不同,一个汉字占两个字节         * 定义一个方法,按照最大的字节数来取字串         * 如:对于"ab你好",如果取三个字节,那么子串就是ab与"你"字的半个         * 那么半个就要舍弃,如果取四个字节就是"ab你",取五个字节还是"ab你"         *          * */        String str="ab你好cd谢谢";        int len=str.getBytes("GBK").length;        for(int x=0;x<len;x++) {            System.out.println("截取"+(x+1)+"个字节结果是:"+cutStringByte(str,x+1));        }    }    private static String cutStringByte(String str,int len) throws UnsupportedEncodingException {        // TODO Auto-generated method stub        byte[]buf=str.getBytes("GBK");        int count=0;        for(int x=len-1;x>=0;x--) {            if(buf[x]<0)                count++;//计算汉字的字节码数            else                break;        }        if(count%2==0)            return new String(buf,0,len,"gbk");//将buf里的从0到len长度的字节码按GBK解码        else            return new String(buf,0,len-1,"gbk");    }}
原创粉丝点击