Java IO结构各种流详解

花了两天时间研究了一下Java IO的流,对于各种流,加深了一下理解
首先看我做的思维导图

文件流

public class FileIO {
    public static void main(String[] args) throws Exception {
        File file1 = new File(System.getProperty("user.dir") + "/c.txt"); // 找到第一个文件的File
        // 找到目标文件路径
        File file2 = new File(System.getProperty("user.dir") + "/d.txt");
        if (file1.exists()) {
            InputStream input = new FileInputStream(file1); // 输入流
            OutputStream output = new FileOutputStream(file2); // 输出流
            int temp = 0;
            while ((temp = input.read()) != -1) { // 表示还有内容可以继续读
                output.write(temp); // 写入数据
            }
            System.out.println("文件复制成功");
            input.close();
            output.close();
        } else {
            System.out.println("文件不存在");
        }
    }
}

对象流
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
  把Java对象转换为字节序列的过程称为对象的序列化。
  把字节序列恢复为Java对象的过程称为对象的反序列化。
  对象的序列化主要有两种用途:
  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
  2) 在网络上传送对象的字节序列。
java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
  java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。、
  只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式 。
  对象序列化包括如下步骤:
  1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
  2) 通过对象输出流的writeObject()方法写对象。
  对象反序列化的步骤如下:
  1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
  2) 通过对象输入流的readObject()方法读取对象。

public class ObjectIO {

    public static void main(String[] args) throws IOException {
        ObjectInputStream ois=null;
        ObjectOutputStream oos=null;
        try {
              oos=new ObjectOutputStream(new FileOutputStream(System.getProperty("user.dir")+"/obj.txt"));
            Person p=new Person("汤高",20);
            oos.writeObject(p);

            ois=new ObjectInputStream(new FileInputStream(System.getProperty("user.dir")+"/obj.txt"));
            Person pp=(Person) ois.readObject();
            System.out.println("姓名 :"+pp.getName());
            System.out.println("年龄 :"+pp.getAge());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            oos.close();
            ois.close();

        }
    }
}

结果:
姓名 :汤高
年龄 :20

如果我只要对部分属性进行序列化,可以使对象,实现Externalizable接口,并重写两个方法

public class Person2 implements Externalizable{
    private String name;
    private Integer age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Person2(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Person2() {
        super();
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((age == null) ? 0 : age.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person2 other = (Person2) obj;
        if (age == null) {
            if (other.age != null)
                return false;
        } else if (!age.equals(other.age))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
        this.name=(String) in.readObject();

    }
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(this.name);

    }

}
public static void main(String[] args) throws IOException {
        ObjectInputStream ois=null;
        ObjectOutputStream oos=null;
        try {
              oos=new ObjectOutputStream(new FileOutputStream(System.getProperty("user.dir")+"/obj.txt"));
            Person2 p=new Person2("汤高",20);
            oos.writeObject(p);
            ois=new ObjectInputStream(new FileInputStream(System.getProperty("user.dir")+"/obj.txt"));
            Person2 pp=(Person2) ois.readObject();
            System.out.println("姓名 :"+pp.getName());
            System.out.println("年龄 :"+pp.getAge());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            oos.close();
            ois.close();

        }
    }
}

结果
姓名 :汤高
年龄 :null

还有一种办法,用到transient关键字

public class Person3 implements Serializable{
    /** * */
    private static final long serialVersionUID = 2474657820412854900L;
    private String name;
    private transient Integer age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Person3(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Person3() {
        super();
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((age == null) ? 0 : age.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person3 other = (Person3) obj;
        if (age == null) {
            if (other.age != null)
                return false;
        } else if (!age.equals(other.age))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }



}
public class ObjectIO3 {

    public static void main(String[] args) throws IOException {
        ObjectInputStream ois=null;
        ObjectOutputStream oos=null;
        try {
              oos=new ObjectOutputStream(new FileOutputStream(System.getProperty("user.dir")+"/obj.txt"));
            Person3 p=new Person3("汤高",20);
            oos.writeObject(p);

            ois=new ObjectInputStream(new FileInputStream(System.getProperty("user.dir")+"/obj.txt"));
            Person3 pp=(Person3) ois.readObject();
            System.out.println("姓名 :"+pp.getName());
            System.out.println("年龄 :"+pp.getAge());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            oos.close();
            ois.close();

        }
    }
}

结果同上

合并流
将多个文件合成一个文件

有些情况下,当我们需要从多个输入流中向程序读入数据。此时,可以使用合并流,将多个输入流合并成一个SequenceInputStream流对象
SequenceInputStream会将与之相连接的流集组合成一个输入流并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。 合并流的作用是将多个源合并合一个源。

SequenceInputStream
public SequenceInputStream(Enumeration

public class SequenceInput {

    public static void main(String[] args) {

        try {
            InputStream fis1=new  FileInputStream(System.getProperty("user.dir")+"/a.txt");
            InputStream fis2=new  FileInputStream(System.getProperty("user.dir")+"/b.txt");
            OutputStream os=new FileOutputStream(System.getProperty("user.dir")+"/ab.txt");
            SequenceInputStream sis=new SequenceInputStream(fis1,fis2);

            int temp=0;
            while((temp=sis.read())!=-1){
                os.write(temp);
            }
            sis.close();
            fis1.close();
            fis2.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

a.txt:hello tanggao
b.txt:hello zhousiyuan

结果:ab.txt hello tanggao hello zhousiyuan

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

        Vector<FileInputStream> v = new Vector<FileInputStream>();

        v.add(new  FileInputStream(System.getProperty("user.dir")+"/a.txt"));
        v.add(new  FileInputStream(System.getProperty("user.dir")+"/b.txt"));

        Enumeration<FileInputStream> en = v.elements();

        SequenceInputStream sis = new SequenceInputStream(en);

        FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir")+"/c.txt");
        byte[] buf = new byte[1024];
        int len = 0;
        while((len=sis.read(buf,0,buf.length))!=-1)
        {
            fos.write(buf,0,len);
        }
        fos.close();
        sis.close();

    }
}

管道流
管道流可以实现两个线程之间,二进制数据的传输。管道流就像一条管道,一端输入数据,别一端则输出数据。通常要分别用两个不同的线程来控制它们。如果要进行管道输出,则必须把输出流连在输入流上。

public class Send implements Runnable {

    public PipedOutputStream getPos() {
        return pos;
    }

    private PipedOutputStream pos = null;
    public Send() {
        // 实例化输出流
        pos = new PipedOutputStream();
    }

    @Override
    public void run() {
        String str = "你好,汤高";
        try {
            pos.write(str.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                pos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Receive implements Runnable {
    private PipedInputStream pis=null;

    public Receive() {
        pis = new PipedInputStream();
    }

    public PipedInputStream getPis() {
        return pis;
    }

    @Override
    public void run() {
        byte [] b=new byte[1024];
        int len=0;
        try {
            len=this.pis.read(b);
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                this.pis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("接收的内容为: "+new String(b,0,len));
    }
}
public class PipeIO {

    public static void main(String[] args) {
        Send s=new Send();
        Receive  r=new Receive();

        try {
            s.getPos().connect(r.getPis());
        } catch (IOException e) {
            e.printStackTrace();
        }
        new Thread(s).start();
        new Thread(r).start();

    }
}

结果:
接收的内容为: 你好,汤高

内存操作流

在之前讲解FileInputStream 和 FileOutputStream 的时候所有的操作的目标是文件,那么如果现在假设有一些临时的信息要求通过IO操作的话,那么如果将这些临时的信息保存在文件之中则肯定很不合理,因为操作的最后还要把文件再删除掉,所以此时的IO中就提供了一个内存的操作流,通过内存操作流输入和输出的目标是内存。

在内存操作流中所有的输入和输出都是以内存为操作的源头
ByteArrayOutputStream 是用于从内存向程序输出的
ByteArrayInputStream 是用于从程序向内存写入的
ByteArrayInputStream 的构造方法: public ByteArrayInputStream(byte[] buf)
表示把内容向内存之中写入
ByteArrayOutputStream来讲,其基本的作用就是与OutputStream一样,一个个的读取数据。

public class ByteArrayIO {


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

        String str="汤高,你好";
        ByteArrayInputStream bai=new ByteArrayInputStream(str.getBytes());

        ByteArrayOutputStream  bao=new ByteArrayOutputStream();

        int len=0;
        while((len=bai.read())!=-1){
            char c=(char) len;
            bao.write(Character.toLowerCase(c));
        }
        System.out.println("输出"+bao.toString());
        bai.close();
        bao.close();
    }

}

结果:
输出 hello ,tanggao
字符串变成小写了,全部操作都是在内存中进行的

过滤流–打印流
打印流分两种:PrintStream(字节)、PrintWriter(字符)
打印流是输出信息最方便的类,可以打印任何数据类型

public class PrintIO1 {
    public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps=new PrintStream(new FileOutputStream(System.getProperty("user.dir")+"/print.txt"));
        ps.print("hello ");

        ps.println("汤高");

        ps.print("1+1="+2);

        ps.print("1+1=3 对吗 ?"+false);
ps.close();

    }

}

结果 print.txt内容:
hello 汤高
1+1=21+1=3 对吗 ?false

使用打印流进行格式化

public class PrintIO2 {
    public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps=new PrintStream(new FileOutputStream(System.getProperty("user.dir")+"/print.txt"));
// PrintWriter ps=new PrintWriter(new //FileOutputStream(System.getProperty("user.dir")+"/print.//txt"));

        ps.print("hello ");

        ps.println("汤高");

        ps.print("1+1="+2);

        ps.print("1+1=3 对吗 ?"+false);
        ps.close();

    }

}

结果:
姓名:汤高 年龄:20 分数:99.10 性别:M

过滤流–缓存流
java IO通过缓冲流来提高读写效率,普通的字节、字符流都是一个字节一个字符这样读取的,而缓冲流则是将数据先缓冲起来,然后一起写入或者读取出来。经常使用的是readLine()方法,表示一次读取一行数据。

public class BufferedIO {
    public static void main(String[] args) throws IOException {
         // 指定要读取文件的缓冲输入字节流 
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(System.getProperty("user.dir")+"/tg.jpg"));  
        File file = new File(System.getProperty("user.dir")+"/tg2.jpg");  
        if (file != null) {  
            file.createNewFile();  
        }  
        // 指定要写入文件的缓冲输出字节流 
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));  
        byte[] bb = new byte[1024];// 用来存储每次读取到的字节数组 
        int n;// 每次读取到的字节数组的长度 
        while ((n = in.read(bb,0,bb.length)) != -1) {  
            out.write(bb, 0, n);// 写入到输出流 
        }  
        out.close();// 关闭流 
        in.close();  
    }
}

完成了图片的复制

字节流和字符流的区别
字节流在操作时不会用到缓冲区(内存),是文件本身直接操作的,而字符流用到了缓冲区,通过缓冲区再操作文件

在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。
程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。
字节流与字符流
在java.io包中操作文件内容的主要有两大类:字节流、字符流,两类都分为输入和输出操作。在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream,在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。(这四个都是抽象类)
java中提供了专用于输入输出功能的包Java.io,其中包括:
InputStream,OutputStream,Reader,Writer
InputStream 和OutputStream,两个是为字节流设计的,主要用来处理字节或二进制对象,
Reader和 Writer.两个是为字符流(一个字符占两个字节)设计的,主要用来处理字符或字符串.

字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点
所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件(特别是文本文件)时,也是一个字节一个字节地读取以形成字节序列
字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串; 2. 字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以
字节流是最基本的,所有的InputStrem和OutputStream的子类都是,主要用在处理二进制数据,它是按字节来处理的 但实际中很多的数据是文本,又提出了字符流的概念,它是按虚拟机的encode来处理,也就是要进行字符集的转化 这两个之间通过 InputStreamReader,OutputStreamWriter来关联,实际上是通过byte[]和String来关联 在实际开发中出现的汉字问题实际上都是在字符流和字节流之间转化不统一而造成的

public class BufferReaderIO {
    public static void main(String[] args) {
        write();
        read();
    }

    public static void write() {
        FileWriter fw = null;
        BufferedWriter bw = null;
        // 缓冲字符输出流去写入数据
        try {
            fw = new FileWriter("demo.txt");
            bw = new BufferedWriter(fw);
            bw.write("Hello");
            bw.newLine();// 换行符标记
            bw.write("Java");
            bw.newLine();
            bw.flush();// 把缓冲区里的内容刷新到目的地
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void read() {
        // 读出
        FileReader fr = null;
        BufferedReader br = null;

        try {
            fr = new FileReader("demo.txt");// 节点流
            br = new BufferedReader(fr, 255);// 255为缓冲区的大小
            String str = null;// 用于存储每一次读取出来的数据
            while ((str = br.readLine()) != null) {
                System.out.println(str);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

转换流
java提供将字节流转化为字符流读写方式的OutputStreamWriter和InputStreamReader

public class zhunhuanIO {
    public static void main(String args[]) throws Exception{    //所有异常抛出 
        //写入数据 
        File file=new File("test.txt");    
        Writer writer=null;     //字符输出流 
        writer=new OutputStreamWriter(new FileOutputStream(file));  //字节流变为字符流 
        String str="hello world!!!!";       
        writer.write(str);  //使用字符流输出 
        writer.close();  

        //读取文件 
        File f = new File("test.txt") ;     
        Reader reader = null ;    
        reader = new InputStreamReader(new FileInputStream(f)) ;    // 将字节流变为字符流 
        char c[] = new char[1024] ;    
        int len = reader.read(c) ;  // 读取 
        reader.close() ;    // 关闭 
        System.out.println(new String(c,0,len)) ;    
    }    
}

回退流

回退:给了用户第二次读的机会。
使用InputStream 要使用read() 方法不断读取,是采用顺序的读取方式。回退操作同样分为字节流和字符流,本例还是以字节流为准。

public class PushInputStreamDemo {
    public static void main(String args[]) throws Exception {   // 所有异常抛出
        String str = "www.mldnjava.cn" ;        // 定义字符串
        PushbackInputStream push = null ;       // 定义回退流对象
        ByteArrayInputStream bai = null ;       // 定义内存输入流
        bai = new ByteArrayInputStream(str.getBytes()) ;    // 实例化内存输入流
        push = new PushbackInputStream(bai) ;   // 从内存中读取数据
        System.out.print("读取之后的数据为:") ;
        int temp = 0 ; 
        while((temp=push.read())!=-1){  // 读取内容
            if(temp=='.'){  // 判断是否读取到了“.”
                push.unread(temp) ; // 放回到缓冲区之中
                temp = push.read() ;    // 再读一遍,不写的话就断了
                System.out.print("(退回"+(char)temp+")") ;
            }else{
                System.out.print((char)temp) ;  // 输出内容
            }
        }
    }
}

结果:
读取之后的数据为:www(退回.)mldnjava(退回.)cn

压缩流

压缩一个文件

public class ZipOutputStreamDemo01 {
    public static void main(String args[]) throws Exception { // 所有异常抛出
        File file = new File("a.txt"); // 定义要压缩的文件
        File zipFile = new File("a.zip"); // 定义压缩文件名称
        InputStream input = new FileInputStream(file); // 定义文件的输入流
        ZipOutputStream zipOut = null; // 声明压缩流对象
        zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
        zipOut.putNextEntry(new ZipEntry(file.getName())); // 设置ZipEntry对象
        zipOut.setComment("www.mldnjava.cn"); // 设置注释
        int temp = 0;
        while ((temp = input.read()) != -1) { // 读取内容
            zipOut.write(temp); // 压缩输出
        }
        input.close(); // 关闭输入流
        zipOut.close(); // 关闭输出流
    }
}

压缩一个文件夹

public class ZipOutputStreamDemo02{
    public static void main(String args[]) throws Exception{    // 所有异常抛出
        File file = new File("tg") ;    // 定义要压缩的文件夹
        File zipFile = new File("tg.zip") ; // 定义压缩文件名称
        InputStream input = null ;  // 定义文件输入流
        ZipOutputStream zipOut = null ; // 声明压缩流对象
        zipOut = new ZipOutputStream(new FileOutputStream(zipFile)) ;
        zipOut.setComment("www.tanggao.cn") ;   // 设置注释
        int temp = 0 ;
        if(file.isDirectory()){ // 判断是否是文件夹
            File lists[] = file.listFiles() ;   // 列出全部文件
            for(int i=0;i<lists.length;i++){
                input = new FileInputStream(lists[i]) ; // 定义文件的输入流
                zipOut.putNextEntry(new ZipEntry(file.getName()
                    +File.separator+lists[i].getName())) ;  // 设置ZipEntry对象
                while((temp=input.read())!=-1){ // 读取内容
                    zipOut.write(temp) ;    // 压缩输出
                }
                input.close() ; // 关闭输入流
            }
        }
        zipOut.close() ;    // 关闭输出流
    }
}

ZipFile
是一个专门表示压缩文件的类。
ipFile 在实例化的时候必须接收File 类的实例。此File 类的实例是指向一个压缩 *.zip 文件。

ZipInputStream 结合 ZipFile 就可以完成解压缩文件夹的功能

ZipFile 对象,可以找到每一个ZipEntry 的输入流。但是ZipInputStream 并不能得到每一个输入流,所以需要使用ZipFile,但是ZipInputStream 在取得每一个ZipEntry 的时候,不需要每一个ZipEntry 的名称。

public class ZipInputStreamDemo{
    public static void main(String args[]) throws Exception{    // 所有异常抛出
        File file = new File("tg.zip") ;    // 定义压缩文件名称
        File outFile = null ;   // 输出文件的时候要有文件夹的操作
        ZipFile zipFile = new ZipFile(file) ;   // 实例化ZipFile对象
        ZipInputStream zipInput = null ;    // 定义压缩输入流
        OutputStream out = null ;   // 定义输出流,用于输出每一个实体内容
        InputStream input = null ;  // 定义输入流,读取每一个ZipEntry
        ZipEntry entry = null ; // 每一个压缩实体
        zipInput = new ZipInputStream(new FileInputStream(file)) ;  // 实例化ZIpInputStream
        while((entry = zipInput.getNextEntry())!=null){ // 得到一个压缩实体
            System.out.println("解压缩" + entry.getName() + "文件。") ;
            outFile = new File( entry.getName()) ;  // 定义输出的文件路径
            if(!outFile.getParentFile().exists()){  // 如果输出文件夹不存在
                outFile.getParentFile().mkdir() ;   // 创建文件夹
            }
            if(!outFile.exists()){  // 判断输出文件是否存在
                outFile.createNewFile() ;   // 创建文件
            }
            input = zipFile.getInputStream(entry) ; // 得到每一个实体的输入流
            out = new FileOutputStream(outFile) ;   // 实例化文件输出流
            int temp = 0 ;
            while((temp=input.read())!=-1){
                out.write(temp) ;
            }
            input.close() ;     // 关闭输入流
            out.close() ;   // 关闭输出流
        }
        input.close() ;
    }
}

1、压缩文件中的每一个压缩实体都使用ZipEntry 保存,一个压缩文件中可能包含一个或多个的ZipEntry 对象。
2、在JAVA中可以进行zip、jar、gz、三种格式的压缩支持,操作流程基本上是一样的
3、ZipOutputStream 可以进行压缩输出,但是输出的位置不一定是文件。
4、ZipFile 表示每一个压缩文件,可以得到每一个压缩实体的输入流,得到实体要知道文件名称,不方便
5、ZipInputStream 可以得到每一个实体,但是却无法得到每一个实体的输入流

所以两则结合用完成解压功能

数据操作流:
DataOutputStream 和 DataInputStream
数据输出流会按照一定的格式将数据输出,再通过数据输入流按照一定的格式将数据读入,这样可以方便对数据进行处理
数据写入格式
每一行的数据,通过 “ \n “ 完结,每行中的各个数据之间通过 ” \t “ 完结

public class DataOutputStreamDemo{
    public static void main(String args[]) throws Exception{    // 所有异常抛出
        DataOutputStream dos = null ;           // 声明数据输出流对象
        File f = new File("order.txt") ; // 文件的保存路径
        dos = new DataOutputStream(new FileOutputStream(f)) ;   // 实例化数据输出流对象
        String names[] = {"衬衣","手套","围巾"} ; // 商品名称
        float prices[] = {98.3f,30.3f,50.5f} ;      // 商品价格
        int nums[] = {3,2,1} ;  // 商品数量
        for(int i=0;i<names.length;i++){    // 循环输出
            dos.writeChars(names[i]) ;  // 写入字符串
            dos.writeChar('\t') ;   // 写入分隔符
            dos.writeFloat(prices[i]) ; // 写入价格
            dos.writeChar('\t') ;   // 写入分隔符
            dos.writeInt(nums[i]) ; // 写入数量
            dos.writeChar('\n') ;   // 换行
        }
        dos.close() ;   // 关闭输出流
    }
};

使用DataOutputStream 写入的数据要使用 DataInputStream 读取进来。

public class DataInputStreamDemo{
    public static void main(String args[]) throws Exception{    // 所有异常抛出
        DataInputStream dis = null ;        // 声明数据输入流对象
        File f = new File("order.txt") ; // 文件的保存路径
        dis = new DataInputStream(new FileInputStream(f)) ; // 实例化数据输入流对象
        String name = null ;    // 接收名称
        float price = 0.0f ;    // 接收价格
        int num = 0 ;   // 接收数量
        char temp[] = null ;    // 接收商品名称
        int len = 0 ;   // 保存读取数据的个数
        char c = 0 ;    // '\u0000'
        try{
            while(true){
                temp = new char[200] ;  // 开辟空间
                len = 0 ;
                while((c=dis.readChar())!='\t'){    // 接收内容
                    temp[len] = c ;
                    len ++ ;    // 读取长度加1
                }
                name = new String(temp,0,len) ; // 将字符数组变为String
                price = dis.readFloat() ;   // 读取价格
                dis.readChar() ;    // 读取\t
                num = dis.readInt() ;   // 读取int
                dis.readChar() ;    // 读取\n
                System.out.printf("名称:%s;价格:%5.2f;数量:%d\n",name,price,num) ;
            }
        }catch(Exception e){}
        dis.close() ;
    }
}

其他流
Java IO _System 类对IO的支持
System.out

public class SystemDemo01{  
    public static void main(String args[]){  
        OutputStream out = System.out ;     // 此时的输出流是向屏幕上输出 
        try{  
            out.write("hello world!!!".getBytes()) ;    // 向屏幕上输出 
        }catch(IOException e){  
            e.printStackTrace() ;   // 打印异常 
        }  
        try{  
            out.close() ;   // 关闭输出流 
        }catch(IOException e){  
            e.printStackTrace() ;  
        }  
    }  
}

System.err

public class SystemDemo02{  
    public static void main(String args[]){  
        String str = "hello" ;      // 声明一个非数字的字符串 
        try{  
            System.out.println(Integer.parseInt(str)) ; // 转型 
        }catch(Exception e){  
            System.err.println(e) ;  
        }  
    }  
};  

System.in

public class SystemDemo04{  
    public static void main(String args[]) throws Exception {   // 所有异常抛出 
        InputStream input = System.in ; // 从键盘接收数据 
        byte b[] = new byte[5] ;    // 开辟空间,接收数据 
        System.out.print("请输入内容:") ;    // 提示信息 
        int len = input.read(b) ;   // 接收数据 
        System.out.println("输入的内容为:" + new String(b,0,len)) ;  
        input.close() ; // 关闭输入流 
    }  
}; 

以上大部分都是对字节流做案例,字符流就不做演示了,直接把字节流换为字符流即可

码字不易,转载请指明出处

你可能感兴趣的:(java)