IO流

IO流

一.流的概念和作用

流是一组有序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,;流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观额进行数据操作.

二.File类

File类是java.io包中很重要的一个类;

Flie类的对象可以表示文件,还可以表示目录,在程序中一个Flie类对象可以代表一个文件或目录

File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。

public static void main(String[] args) {

        /*
           File类的构造方法的3种方式
         */
       /* File f = new File("E:/demo.txt");

        String p = "E:\\";
        File f1 = new File(p,"demo.txt");
        File f2 = new File(p,"api");

        File fp = new File("E:\\" );
        File f3 = new File(fp,"demo.txt");
        File f4 = new File(fp,"api");*/

        //File f = new File("demo.txt");
        File f = new File("E:\\demo.txt");//在创建File对象时,不检测文件是否存在
        System.out.println(f.length());//获得文件内容长度,以字节为单位
        System.out.println(f.getParent());
        System.out.println(f.getName());
        System.out.println(f.getAbsolutePath());//获得相对路径的文件绝对路径
        System.out.println(f.exists());//判断文件是否存在

        System.out.println(f.isDirectory());//判断是否是文件夹
        System.out.println(f.isHidden());//判断文件是否为隐藏文件
        System.out.println(f.isAbsolute());//判断路径是否为绝对路径
        System.out.println(f.canWrite());
        System.out.println(f.canRead());
        System.out.println(f.canExecute());
        System.out.println(f.getPath());
        System.out.println(f.lastModified());
        String  ld =  DateUtil.dateToString(f.lastModified(), "yyyy-MM-dd HH:mm:ss");
        System.out.println(ld);
    }
 public static void main(String[] args) {
        /*
        createNewFile()  创建文件
        如果已经存在,就不创建了,返回false
        如果不存在,就创建 返回true
        如果盘符/地址在计算机没有,直接抛出异常
         */
       //File f = new File("E:/demo.txt");
       /* try {
            System.out.println(f.createNewFile());
        } catch (IOException e) {
            e.printStackTrace();
        }*/
        //System.out.println(f.delete());//删除文件,存在返回true,不存在返回false.

         //File f = new File("E:/demo/demo");
         //System.out.println(f.mkdir());//只能创建单级文件夹
         //f.mkdirs();//可以创建多级文件夹
          //f.delete();//删除文件夹,删除时,文件夹中必须为空.


          File f = new File("E:\\api");
          //获取指定目录下的所有子级的文件或目录,以字符串形式返回
        /*  String []  farray =  f.list();
          for (String arr : farray){
              System.out.println(arr);
          }*/

      /*                        //添加过滤条件,筛选文件
        String []  farray =  f.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return StringUtil.subFileType(name).equalsIgnoreCase("chm");
            }
        });

        for (String arr : farray){
            System.out.println(arr);
        }
     */

       File[] fs =   f.listFiles(new FilenameFilter(){
           @Override
           public boolean accept(File dir, String name) {
               return StringUtil.subFileType(name).equalsIgnoreCase("chm");
           }
       });

         for (File ft : fs){
            System.out.println(ft);
         }

         File f1 = new File("E:\\demo.txt");
         File f2 = new File("E:\\demo1.txt");
         f1.renameTo(f2);//重命名
    }

三.IO流的分类

字符流和字节流

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。字节流和字符流的区别:

(1)读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

(2)处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

(3)字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的;而字符流在操作的时候下后是会用到缓冲区的,是通过缓冲区来操作文件,我们将在下面验证这一点。

结论:优先选用字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。

输入流和输出流

对输入流只能进行操作,对输出流只能进行操作,程序中需要根据待传输数据的不同特性而使用不同的流。

Java流的图结构

在这里插入图片描述

三.Java IO流对象

1.字节流

首先,我们得知道InputStreamOutputStream是所有字节流的父类,是一个抽象类

1)FileInputStreamFileOutputStream从本地文件中读取数据
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class StreamDemo1 {


    public static void main(String[] args) {
        /*File f = new File("E:\\demo1.txt");
        FileInputStream in1 = new FileInputStream(f);*/

        try {
            /*
              创建FileInputStream对象,指定要输入(读)的文件,文件不存在,会抛出异常
             */
            FileInputStream in = new FileInputStream("E:\\demo.txt");

                    int  b =    in.read();
                    System.out.println(b);
                    int  b1 =    in.read();
                    System.out.println(b1);
                    int  b2 =    in.read();
                    System.out.println(b2);
                    int  b3 =    in.read();
                    System.out.println(b3);
                    int  b4 =    in.read();
                    System.out.println(b4);
                    int  b5 =    in.read();
                    System.out.println(b5);
                    int  b6 =    in.read();
                    System.out.println(b6);
                    int  b7 =    in.read();
                    System.out.println(b7);
                    //read()  每read()一次,从输入流中读到一个字节 返回,文件内容全部读完后,返回-1.

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }


    }

}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class StreamDemo2 {


    public static void main(String[] args) {
        /*File f = new File("E:\\demo1.txt");
        FileInputStream in1 = new FileInputStream(f);*/
        FileInputStream in =null;
        FileOutputStream out = null;
        try {
            /*
              创建FileInputStream对象,指定要输入(读)的文件,文件不存在,会抛出异常
             */
              in = new FileInputStream("E:\\demo.txt");
            /*
              创建FileOutputStream对象, 自动创建输出的目标文件
             */
             out = new FileOutputStream("F:\\demo.txt");
                    int b = 0;//记录每次读到的字节值
                    while ((b = in.read())!=-1){
                        System.out.println(b);
                        out.write(b);//向指定的文件中输出字节
                    }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally {
             //关闭流对象,释放系统资源
                try {
                    if(in!=null){
                        in.close();
                    }
                    if(out!=null){
                        out.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

        }


    }

}

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class StreamDemo3 {


    public static void main(String[] args) throws IOException {
            /*
              创建FileInputStream对象,指定要输入(读)的文件,文件不存在,会抛出异常
             */
            FileInputStream in = new FileInputStream("E:\\demo.txt");
            /*
              创建FileOutputStream对象, 自动创建输出的目标文件
             */
            FileOutputStream   out = new FileOutputStream("F:\\demo.txt");

                    int b = 0;//记录每次读到的字节值
                    while ((b = in.read())!=-1){
                        out.write(b);//向指定的文件中输出字节
                    }

                //关闭通道,释放资源
                in.close();
                out.close();
        }


}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;

public class StreamDemo4 {


    public static void main(String[] args) throws IOException {
            /*
              创建FileInputStream对象,指定要输入(读)的文件,文件不存在,会抛出异常
             */
            FileInputStream in = new FileInputStream("E:\\demo.txt");
            /*
              创建FileOutputStream对象, 自动创建输出的目标文件
             */
            FileOutputStream   out = new FileOutputStream("F:\\demo.txt");
            /*
                int read()  每次从输入流中读取一个字节  返回字节值  读完返回-1
                int read(byte[] b) 每次从输入流中读取一个byte数组长度个字节,返回数组中实际装入内容个数, 读完返回-1
             */
                  byte[] b  =new  byte[6];//存储读到的内容
                  int length = 0;
                  while((length=in.read(b))!=-1){
                      System.out.println(length);
                       out.write(b, 0,length);//向外写出一个byte数组个字节,从数组指定位置开始,写length个字节
                  }

                //关闭通道,释放资源
                in.close();
                out.close();
        }


}
2)FilterInputStresmFilterOutputStresm

ObjectInputStream 和所有FilterInputStream的子类都是装饰流(装饰器模式的主角)。意思是FileInputStream类可以通过一个String路径名创建一个对象,FileInputStream(String name)。而DataInputStream必须装饰一个类才能返回一个对象,DataInputStream(InputStream in)。

(1)BufferedInputStreamBufferedOutputStream

package day3;

import java.io.*;

public class BufferedStreamDemo {
    public static void main(String[] args) throws IOException {
        //创建输入节点流,直接负责对文件读写的
        FileInputStream in = new FileInputStream("E:\\feige.exe");
        //创建处理对象,内部有一个缓冲数组 默认为8192个字节
        BufferedInputStream bin = new BufferedInputStream(in,2048);

        FileOutputStream out = new FileOutputStream("F:\\feige.exe");
        BufferedOutputStream bout = new BufferedOutputStream(out,2048);
                 /* int b = 0;
                  while((b=bin.read())!=-1){
                       bout.write(b);
                  }*/
        byte [] b = new byte[1024];
        int length  = 0;
        while((length=bin.read(b))!=-1){
            bout.write(b, 0, length);
        }
        bout.flush();//刷新缓冲区
        bout.close();
        bin.close();

    }
}

(2)DataIntputStreamDataOutputStream 数据读取

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
  
public class DataOutputStreamDemo{
   public static void main(String[] args) throws IOException{
       File file = new File("d:" + File.separator +"hello.txt");
       DataInputStream input = new DataInputStream(new FileInputStream(file));
       char[] ch = new char[10];
       int count = 0;
       char temp;
       while((temp = input.readChar()) != 'C'){
           ch[count++] = temp;
       }
       System.out.println(ch);
    }
}
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamDemo{
   public static void main(String[] args) throws IOException{
       File file = new File("d:" + File.separator +"hello.txt");
       char[] ch = { 'A', 'B', 'C' };
       DataOutputStream out = null;
       out = new DataOutputStream(new FileOutputStream(file));
       for(char temp : ch){
           out.writeChar(temp);
       }
       out.close();
    }
}
3)ObjectInputStreamObjectOutputStream对象输入输出流(装饰流)
package day4;

import java.io.*;
import java.util.Date;

/*
对象序列化   使用Serializable接口(接口中没有方法) 一个类实现Serializable接口,
           就可以序列化
 */
public class ObjectStreamDemo implements Serializable {
    /*
    对象输入输出字节流

    对象:内存中的对象
    为什么将对象输出?
      内存中的数据电脑关闭,服务器停止数据就会消失
      有时候,需要将这些数据保存起来(这个过程被称为 对象序列化)
     */
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        //序列化
       /* FileOutputStream out=new FileOutputStream("G:\\data.txt");
          ObjectOutputStream oout=new ObjectOutputStream(out);
              String s="abc";
              Date date=new Date();

              oout.writeObject(s);
              oout.writeObject(date);
              oout.close();*/

        //反序列化
        FileInputStream in=new FileInputStream("G:\\data.txt");
        ObjectInputStream oin=new ObjectInputStream(in);
                  String s=(String) oin.readObject();
                  Date date=(Date) oin.readObject();

                  oin.close();
    }
}

4)ByteArrayInputStreamByteArrayOutputStream 从Byte数组中读取文件

例:使用内存操作流将一个大写字母转化为小写字母

/**
 * 使用内存操作流将一个大写字母转化为小写字母
 * */
import java.io.*;
class hello{
   public static void main(String[] args) throws IOException {
       String str="ROLLENHOLT";
       ByteArrayInputStream input=new ByteArrayInputStream(str.getBytes());
       ByteArrayOutputStream output=new ByteArrayOutputStream();
       int temp=0;
       while((temp=input.read())!=-1){
           char ch=(char)temp;
           output.write(Character.toLowerCase(ch));
       }
       String outStr=output.toString();
       input.close();
       output.close();
       System.out.println(outStr);
    }
}
5)几个特殊的输入流分析

LineNumberInputStream

主要完成从流中读取数据时,会得到相应的行号,至于什么时候分行、在哪里分行是由改类主动确定的,并不是在原始中有这样一个行号。在输出部分没有对应的部分,我们完全可以自己建立一个LineNumberOutputStream,在最初写入时会有一个基准的行号,以后每次遇到换行时会在下一行添加一个行号,看起来也是可以的。好像更不入流了。

PushbackInputStream

其功能是查看最后一个字节,不满意就放入缓冲区。主要用在编译器的语法、词法分析部分。输出部分的BufferedOutputStream 几乎实现相近的功能。

StringBufferInputStream

已经被Deprecated,本身就不应该出现在InputStream部分,主要因为String 应该属于字符流的范围。已经被废弃了,当然输出部分也没有必要需要它了!还允许它存在只是为了保持版本的向下兼容而已。

SequenceInputStream

可以认为是一个工具类,将两个或者多个输入流当成一个输入流依次读取。完全可以从IO 包中去除,还完全不影响IO 包的结构,却让其更“纯洁”――纯洁的Decorator 模式。

2.字符流

Reader 是所有的输入字符流的父类,它是一个抽象类。

Writer 是所有的输出字符流的父类,它是一个抽象类。

1)InputStreamReaderOutputStreamWriter

InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。

OutputStreamWriterOutputStream 到Writer 转换的桥梁,它的子类FileWriter其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似,

转换流的特点:

(1)其是字符流和字节流之间的桥梁

(2)可对读取到的字节数据经过指定编码转换成字符

(3)可对读取到的字符数据经过指定编码转换成字节

何时使用转换流?

当字节和字符之间有转换动作时;

流操作的数据需要编码或解码时。

具体的对象体现:

InputStreamReader:字节到字符的桥梁

OutputStreamWriter:字符到字节的桥梁

这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。

(1)将字节输出流转化为字符输出流

/**
 * 将字节输出流转化为字符输出流
 * */
import java.io.*;
class hello{
   public static void main(String[] args) throws IOException {
       String fileName= "d:"+File.separator+"hello.txt";
       File file=new File(fileName);
       Writer out=new OutputStreamWriter(new FileOutputStream(file));
       out.write("hello");
       out.close();
    }
}

(2)将字节输入流转换为字符输入流

/**
 * 将字节输入流变为字符输入流
 * */
import java.io.*;
class hello{
   public static void main(String[] args) throws IOException {
       String fileName= "d:"+File.separator+"hello.txt";
       File file=new File(fileName);
       Reader read=new InputStreamReader(new FileInputStream(file));
       char[] b=new char[100];
       int len=read.read(b);
       System.out.println(new String(b,0,len));
       read.close();
    }
}
2)BufferedReaderBufferedWriter

BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。

BufferedWriter 是一个装饰器为Writer 提供缓冲功能。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
  
/**
 * 使用缓冲区从键盘上读入内容
 * */
public class BufferedReaderDemo{
   public static void main(String[] args){
       BufferedReader buf = new BufferedReader(
                newInputStreamReader(System.in));
       String str = null;
       System.out.println("请输入内容");
       try{
           str = buf.readLine();
       }catch(IOException e){
           e.printStackTrace();
       }
       System.out.println("你输入的内容是:" + str);
    }
}
3)其他的一些字符流

(1)CharReaderStringReader是两种基本的介质流,它们分别将Char 数组、String中读取数据。PipedReader 是从与其它线程共用的管道中读取数据。

(2)FilterReader是所有自定义具体装饰流的父类,其子类PushbackReader对Reader 对象进行装饰,会增加一个行号。

(3)CharArrayWriterStringWriter是两种基本的介质流,它们分别向Char 数组、String 中写入数据。

(4)PipedWriter 是向与其它线程共用的管道中写入数据,

(5)PrintWriterPrintStream极其类似,功能和使用也非常相似。

四.对象序列化

对象序列化就是把一个对象变为二进制数据流的一种方法。

一个类要想被序列化,就行必须实现java.io.Serializable接口。虽然这个接口中没有任何方法,就如同之前的cloneable接口一样。实现了这个接口之后,就表示这个类具有被序列化的能力。

package day4;

import java.io.*;
import java.util.Date;

/*
对象序列化   使用Serializable接口(接口中没有方法) 一个类实现Serializable接口,
           就可以序列化
 */
public class ObjectStreamDemo implements Serializable {
    /*
    对象输入输出字节流

    对象:内存中的对象
    为什么将对象输出?
      内存中的数据电脑关闭,服务器停止数据就会消失
      有时候,需要将这些数据保存起来(这个过程被称为 对象序列化)
     */
    public static void main(String[] args) throws IOException, ClassNotFoundException {

        //序列化
       /* FileOutputStream out=new FileOutputStream("G:\\data.txt");
          ObjectOutputStream oout=new ObjectOutputStream(out);
              String s="abc";
              Date date=new Date();

              oout.writeObject(s);
              oout.writeObject(date);
              oout.close();*/

        //反序列化
        FileInputStream in=new FileInputStream("G:\\data.txt");
        ObjectInputStream oin=new ObjectInputStream(in);
                  String s=(String) oin.readObject();
                  Date date=(Date) oin.readObject();

                  oin.close();
    }
}

package day4;

import java.io.Serializable;

/*
 需要被序列化类的对象,此类必须显示Serializable接口
 实现此接口后,此类默认生出一个序列化id号,当此类内容发生修改后,这个id会会发生改变
 也可以使用工具生成一个序列化id号,这样类如果发生修改,此类id依然不变
 */
public class Studnet implements Serializable {
    private static final long serialVersionUID = 930203241074318639L;
    int num;
    /*
    被transient关键字修饰的属性  可以不被序列化
     */
    transient String name;
    //String address;

    public Studnet(int num, String name) {
        this.num = num;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Studnet{" +
                "学号=" + num +
                ", 姓名='" + name + '\'' +
                /*"地址=" + address +*/'}';
    }
}

package day4;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class ObjectStreamDemo2 {
    public static void main(String[] args) throws IOException {
        FileOutputStream out=new FileOutputStream("G:\\data.txt");
        ObjectOutputStream oout=new ObjectOutputStream(out);

                  Studnet studnet=new Studnet(100,"zxc");
                  oout.writeObject(studnet);

                  oout.close();
    }
}

package day4;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class ObjectStreamDemo3 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream in=new FileInputStream("G:\\data.txt");
        ObjectInputStream oin=new ObjectInputStream(in);

                Studnet studnet=(Studnet)oin.readObject();
        System.out.println(studnet);
        oin.close();
    }
}

创作不易,大佬们留步… 动起可爱的双手,来个赞再走呗 (๑◕ܫ←๑)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值