IO流

IO流

目录
  • IO流
    • 文件
      • 什么是文件?
      • 文件流
      • 创建文件
        • 方式一:完整路径
        • 方式二:根据父目录文件和子路径创建**
        • 方式三:根据父目录路径+子路径构建
        • 小知识点:路径问题
      • 对文件的常用操作
        • 获取文件信息
        • 对文件和目录的操作
    • Java IO流原理及流的分类
      • 概念:
      • 流的分类:
        • 字节流:
        • 字符流:
        • 文件和流的对比:
      • 字节流:
        • InputStream:字节输入流
        • FileInputStream
          • read()
          • read(byte b[]):
        • OutputStream:字节输出流
        • FileOutputStream:
          • write():放一个字节数
          • write(byte[]):
          • write(byte[],0,len):
          • 细节注意点:
        • 文件拷贝:
      • 字符流
        • FileReader:字符输入流
        • FileWriter:字符输出流
        • 构造器注意:
      • 节点流和处理流
        • 概念:
        • 处理流的功能主要体现在以下两个方面:
        • BufferedReader:字符输入处理流
          • readline:
        • BufferedWriter:字符输出处理流
        • 字符处理流实现文件copy
        • BufferedInputStream:字节输入处理流
        • BufferedOutputStream:字节输出处理流
        • 字节处理流实现音乐和视频等二进制文件copy
      • 对象处理流
        • ObjectOutputStream:对象输出流实现序列化
        • ObjectInputStream:对象输入流实现反序列化
        • 注意细节:
      • 标准输入输出流
      • 转换流
        • InputStreamReader:字节转换字符输入流
        • OutputStreamWriter:字节转换字符输出流
      • 打印流
        • PrintStream:字节打印流
        • PrintWriter:字符打印流
    • Properties类

文件

什么是文件?

文件,对我们并不陌生,文件是保存数据的地方,比如大家经常使用的word文档,txt文件,excel文件...都是文件。它既可以保存一张图片,也可以保持视频,声音.

文件流

文件在程序中都是以流的形式来操作的

流:数据在数据源(文件)和程序(内存)之间经历的路径

输入流:数据从数据源(文件)到程序(内存)的路径

输出流:数据从程序(内存)到数据源(文件)的路径

创建文件

createNewFile()

三种方式

方式一:完整路径

注:在创建的时候,我们new File(),只是在内存中,只有调用到createNewFile()才会写入到硬盘

new File(String path)

  @Test
    public void crate1(){
        String path="D:\\java高级部分\\JavaIo\\源\\One.txt";
        File file = new File(path);
        try {
            file.createNewFile();
            System.out.println("创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

方式二:根据父目录文件和子路径创建**

**new File(File parent,String child)

public void crate2(){
    String path="Two.txt";
    File file1 = new File("D:\\java高级部分\\JavaIo\\源");
    File file2 = new File(file1,path);
    try {
        file2.createNewFile();
        System.out.println("创建成功");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

方式三:根据父目录路径+子路径构建

new File(String parent, String child)

  //    方式三:new File(String parent, String child)//根据父目录路径+子路径构建
    @Test
    public void crate3(){
        String path="Three.txt";
       String ParenPath="D:\\java高级部分\\JavaIo\\源";
        File file2 = new File(ParenPath,path);
        try {
            file2.createNewFile();
            System.out.println("创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

小知识点:路径问题

在文件创建时有一个注意点就是,就是文件的路径是D:/ 之类的,但是我们在程序写的时候必须是D://有一个转义符,或者写成D:

对文件的常用操作

获取文件信息

对文件和目录的操作

listFiles():将文件下的所有内容放到一个File数组里

 public static void Test(String path){
        File file = new File(path);
        if (file.isDirectory()){
            将文件下的所有内容放到一个File数组里
            File[] files = file.listFiles();
            for (int i = 0; i 

创建:一级目录mkdir(),多级目录mkdirs()

删除:delete()

//    判断文件是否存在,存在就删除,不存在创建
    @Test
    public void c1(){
        File file = new File("D:\\java高级部分\\JavaIo\\源\\Four.txt");
        if (file.exists()){
            if (file.delete()){
                System.out.println("删除成功");
            }
        }else{
            if ( file.mkdir()){
                System.out.println("创建成功");
            }
        }
    }

//    判断目录是否存在,存在就删除,不存在创建
//    在java中编程中,目录也被当成文件
    @Test
    public void c2(){
        File file = new File("D:\\java高级部分\\JavaIo\\源\\sb");
        if (file.exists()){
            if (file.delete()){
                System.out.println("删除成功");
            }
        }else{
            if ( file.mkdir()){
                System.out.println("创建成功");
            }
        }
    }

Java IO流原理及流的分类

概念:

  1. I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等。
  2. Java程序中,对于数据的输入/输出操作以”流(stream)”的方式进行。
  3. java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据

输入流:数据从数据源(磁盘,网络,光盘)到程序(内存)的路径

输出流:数据从程序(内存)到数据源(磁盘,光盘,网络)的路径

流的分类:

按操作数据单位:字节流(8 bit),字符流(字符)

按流的方向:输入流,输出流

按流的角色的不同:字节流,处理流/包装流

字节流:

InputStream();

OutputStream()

字符流:

Writer()

Reader()

文件和流的对比:

字节流:

InputStream:字节输入流

FileInputStream

read()
 @Test
    public void readFile1(){
//		将文件放入内存中
        File file = new File("D:\\java高级部分\\JavaIo\\源\\FileInputStream");
 //     创建一个文件输入流  
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(file);
//            定义一个变量用于接收流的数据
            int readDate=0;
//            read方法读取一个字节,如果读到最后一个字节就返回-1
            while ((readDate=fileInputStream.read())!=-1){
                System.out.print((char)readDate);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
read(byte b[]):
//使用read(byte[])优化
    @Test
    public void readFile2(){
        File file = new File("D:\\java高级部分\\JavaIo\\源\\FileInputStream");
        FileInputStream fileInputStream = null;
        byte buf[]=new byte[3];
        int readbuf=0;
        try {
            fileInputStream = new FileInputStream(file);
//            read方法读取一个字节,如果读到最后一个字节就返回-1
            while ((readbuf=fileInputStream.read(buf))!=-1){
//                从该输入流读取最多 buf.length个字节的数据为字节数组。
                System.out.print(new String(buf,0, readbuf));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

OutputStream:字节输出流

FileOutputStream:

write():放一个字节数
write(byte[]):
 public void writeStream1(){
        File file = new File("D:\\java高级部分\\JavaIo\\源\\FileOutputStream");
        if (file.exists()){
            file.delete();
        }else{
            file.mkdir();
        }
        String buf="刘超真帅";
        FileOutputStream outps=null;
        try {
            outps = new FileOutputStream(file);
//将字符串转换为字节数组            
            outps.write(buf.getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                outps.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
write(byte[],0,len):

从位于偏移量 off的指定字节数组写入 len字节到该文件输出流。

细节注意点:

当我们正常写入时,会覆盖原来文件的内容

FileOutputStream outps = new FileOutputStream(file,true);

这个时候在构造器加一个true,就不会覆盖会追加到内容后

文件拷贝:

 public void copy1(){
        File file = new File("D:\\java高级部分\\JavaIo\\源\\ALisa - 溯Reverse(治愈版).mp3");
        FileInputStream FIus=null;
        FileOutputStream FOps=null;
        int readlen=0;
        try {
            FIus = new FileInputStream(file);
            byte buf[]=new byte[1024];
            FOps = new FileOutputStream("D:\\java高级部分\\JavaIo\\源\\ALisa - 溯Reverse(治愈版)2.mp3");
            while ((readlen=FIus.read(buf))!=-1){
                //边读边写
                FOps.write(buf,0, readlen);
                //这里不要用write(byte[]),因为固定死了读取整个数组长度的值,如果后面剩余的数量小于数组值,会填入很快空值
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                FIus.close();
                FOps.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

字符流

FileReader:字符输入流

read()

read(byte[]):

 //    一次读取多个字符
    @Test
    public void Reader2(){
        File file = new File("D:\\java高级部分\\JavaIo\\源\\One.txt");
        int Readdate=0;
        FileReader reader = null;
        char []buf=new char[8];
        try {
            reader = new FileReader(file);
            while ((Readdate=reader.read(buf))!=-1){
                System.out.print(new String(buf,0,Readdate));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

FileWriter:字符输出流

构造器注意:

new FileWriter(path/file):覆盖模式

new fileWriter(path/file,true):追加模式

    @Test
    public void writer1(){
        FileWriter fileWriter =null;
        char []b=new char[]{'a','c','d'};
        try {
              fileWriter = new FileWriter("D:\\java高级部分\\JavaIo\\源\\Two.txt");
//            Writer(char):写入单个字符
            fileWriter.write('A');
//            write(char[]):写入指定数组
            fileWriter.write(b);
//             write(char[],off,len):写入指定数组的指定部分
            fileWriter.write(b,0,2);
//            Writer(String):写入整个字符串
            fileWriter.write("你好zz,");
//            write(String,off,len):写入字符串的指定部分
            fileWriter.write("你好傻逼",2,2);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

节点流和处理流

概念:

1.节点流就是从一个特定的数据源读写数据,如FileReader,FileWriter

有哪些字节流:

2.处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供
更为强大的读写功能,如BufferedReader、BufferedWriter [源码]

BufferReader类里有Reader,封装了一个字节流

处理流的功能主要体现在以下两个方面:

  1. 性能的提高:主要以增加缓冲的方式来提高输入输出的效率。

  2. 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使
    用更加灵活方便

BufferedReader:字符输入处理流

注意点:关闭处理流只需要关闭外层流就可以了,如果你关闭处理流,底层的节点流就会自己关闭

readline:

读取一行,末行返回null

  @Test
    public void Reader1(){
        File file = new File("D:\\java高级部分\\JavaIo\\源\\One.txt");
        String line;
        BufferedReader bufferedReader =null;
        try {
           bufferedReader = new BufferedReader(new FileReader(file));
//           readline()读取一行,末行返回null
           while ((line=bufferedReader.readLine())!=null){
               System.out.println(line);
           }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
//                这里只需要关闭处理流,底层节点流自己会关闭
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

BufferedWriter:字符输出处理流

如果你是覆盖方式就是普通构造器:

如果你是追加方式,因为BufferWriter构造器没有,且底层是节点流在处理数据,所以追加就在节点流构造器加true就行

public void Writer1(){
        BufferedWriter bufferedWriter =null;
        try {
            //覆盖模式:
            bufferedWriter = new BufferedWriter(new FileWriter("D:\\java高级部分\\JavaIo\\源\\Three.txt"));
            //追加模式:
            bufferedWriter = new BufferedWriter(new FileWriter("D:\\java高级部分\\JavaIo\\源\\Three.txt"),true);
            bufferedWriter.write('o');
            bufferedWriter.write("耶");
            bufferedWriter.newLine();//插入一个换行
            bufferedWriter.write("你好帅b",0,3);
            bufferedWriter.write(new char[]{'H','a'},0,1);
            bufferedWriter.write(new char[]{'H'});
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                bufferedWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

字符处理流实现文件copy

    public void copy(){
    File file = new File("D:\\java高级部分\\JavaIo\\源\\Three.txt");
    File file2 = new File("D:\\java高级部分\\JavaIo\\源\\Three2.txt");
    BufferedReader bufferedReader =null;
    BufferedWriter bufferedWriter =null;
            String line;
    try {
         bufferedReader = new BufferedReader(new FileReader(file));
//         追加
         bufferedWriter = new BufferedWriter(new FileWriter(file2,true));
        while ((line=bufferedReader.readLine())!=null){
//           读一行写一行
            bufferedWriter.write(line);
//           读一行就换行
            bufferedWriter.newLine();
       }
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            bufferedWriter.close();
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BufferedInputStream:字节输入处理流

BufferedOutputStream:字节输出处理流

字节处理流实现音乐和视频等二进制文件copy

public void OutCopy(){
    File file = new File("D:\\java高级部分\\JavaIo\\源\\img.png");
    File file2 = new File("D:\\java高级部分\\JavaIo\\源\\img2.png");
    byte []buf=new byte[1024];
    BufferedInputStream bufferedInputStream =null;
    BufferedOutputStream bufferedOutputStream =null;
    try {
        bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
        bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file2));
        while ((bufferedInputStream.read(buf,0,buf.length)!=-1)){
            bufferedOutputStream.write(buf,0,buf.length);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            bufferedOutputStream.close();
            bufferedInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

对象处理流

对象处理流不仅仅要保存对象的值,还要保存类型,这就涉及到了序列化的问题

  • 序列化和反序列化
  1. 序列化就是在保存数据时,保存数据的值和数据类型

  2. 反序列化就是在恢复数据时,恢复数据的值和数据类型

  3. 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该
    类必须实现如下两个接口之一:
    Serializable //这是一个标记接口

Externalizable //该接口有方法要实现,所以一般不使用这个接口

ObjectOutputStream:对象输出流实现序列化

同样有一个构造器里有一个OutputStream的参数**,可以调用其他子类

   public void Object1(){
        File file = new File("D:\\java高级部分\\JavaIo\\源\\FileOutputStream");
        ObjectOutputStream outputStream =null;
        try {
            outputStream = new ObjectOutputStream(new FileOutputStream(file));
            outputStream.writeBoolean(true);  //包装类Boolean实现了序列化接口
            outputStream.writeByte(1);
            outputStream.writeChar('l');  //Character实现类序列化接口
            outputStream.writeDouble(3.22);
            outputStream.writeUTF("你好");//写入字符串
            //实现类的序列化时一定要注意这个类要自己实现序列化接口
            outputStream.writeObject(new Person(20,"刘超"));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

ObjectInputStream:对象输入流实现反序列化

同样有一个构造器里有一个InputStream的参数,可以调用其他子类

  public void Object1(){
        File file = new File("D:\\java高级部分\\JavaIo\\源\\FileOutputStream");
        ObjectInputStream Ois =null;
        try {
            Ois = new ObjectInputStream(new FileInputStream(file));
//            读取的顺序必须跟序列化顺序一样,因为序列化有数据类型,所以你反序列化类型必须相同
            System.out.println(Ois.readBoolean());
            System.out.println(Ois.readByte());
            System.out.println(Ois.readChar());
            System.out.println(Ois.readDouble());
            System.out.println(Ois.readUTF());   //读取字符串
            System.out.println(Ois.readObject());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                Ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

注意细节:

  1. 序列化和反序列化顺序一致,不然会报错
  2. 要求序列化或者反序列的对象必须实现Serializable
  3. 序列化的类中建议添加SerializableUID,提高版本兼容性
  4. 序列化对象中,默认将所有属性都序列化,但除了static或transient修饰的成员
  5. 序列化对象时,要求里面的属性也实现序列化接口

当你在一个实现序列化接口的类里,里面有一个引用数据类型,并且这个类没有实现接口就会报错,其他基本数据类型的属性,由于包装类其实都实现了序列化了,所以没问题

6.序列化具有可继承性,如果某类实现了序列化,那么它的子类也默认实现了序列化

标准输入输出流

System.in==>InputStream 设备:键盘

System.out==>PrintStream 设备:显示器

    public static void main(String[] args) {
//        输入流
//        编译时:public final static InputStream in = null;
//        运行时:BufferedInputStream
        InputStream in = System.in;
        System.out.println(in.getClass());


//        输出流
//        编译时: public final static PrintStream out = null;
//        运行时:PrintStream
        System.out.println(System.out.getClass());
    }

转换流

InputStreamReader:字节转换字符输入流

Reader的子类

此时的文件编码格式为ANSI
public void Code1(){
        File file = new File("D:\\java高级部分\\JavaIo\\源\\Three.txt");
        char buf[]=new char[1024];
        String b;
        InputStreamReader ISR =null;
        FileInputStream FIS =null;
        BufferedReader BR=null;
        try {
             FIS = new FileInputStream(file);
            此时的GBK对应着文件的编码格式
//             将字节处理流FileInputStream转换成字符流InputStreamReader,并指定编码格式GBk
             ISR = new InputStreamReader(FIS,"GBk");
//             再把流丢到处理流里处理
             BR=new BufferedReader(ISR);
            while ((b=BR.readLine())!=null){
                System.out.print(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
//                同样只关闭外层流
                BR.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

OutputStreamWriter:字节转换字符输出流

Writer的子类

    public void OW1() throws IOException {
        File file = new File("D:\\java高级部分\\JavaIo\\源\\Five.txt");
        OutputStreamWriter OSW = new OutputStreamWriter(new FileOutputStream(file), "GBK");
        OSW.write("你好");
//        这里发现不关流的化没有写入成功
        写入内存缓冲区了,在不关闭、刷新情况下,或者内存缓冲没满时,是不会写入文档中,你必须加入flush()方法,或者关闭流,来刷新内存缓冲,这样就可以写到文档中
        OSW.close();
    }

注意点:输出的时候指定的编码格式就是设置那个文件的编码格式

打印流

打印流只有输出流(只能从程序打印出去)

PrintStream:字节打印流

 public static void main(String[] args) throws FileNotFoundException {
        PrintStream PS =System.out;
//          public void print(String s) {
//        if (s == null) {
//            s = "null";
//        }
//        write(s);          print底层是write输出
//    }
        PS.print("你好");
//        设置输出流输出的位置
        System.setOut(new PrintStream("D:\\java高级部分\\JavaIo\\源\\Six.txt"));
        System.out.println("刘超真帅");
    }

PrintWriter:字符打印流

   public static void main(String[] args) throws IOException {
//        打印流丢进去一个标准输出流就会在显示器控制台打印
//        PrintWriter PW = new PrintWriter(System.out);
//        PW.print("你好");
//        别忘了关流,不然缓存会导致无法写入
//        PW.close();
//        打印流也是一个处理流
        PrintWriter PW = new PrintWriter(new FileWriter("D:\\java高级部分\\JavaIo\\源\\Five.txt"),true);
        PW.print("你好");
        PW.close();
    }

Properties类

专门用于读写配置文件的集合类(Hashtable的子类)

(1)配置文件的格式

键=值

(2)键值对不需要有空格,值不需要用引号,默认类型为String

(3)常用方法:

load:加载配置文件

list:将整个文件(以打印处理流)输出到某个位置

getProperty(key):获取某个键的值

setProperty(key,value):设置键值对到Properties对象里,如果没有这个键就是创建,有就是修改

store(输出位置,注释):将Properties储存的键值对储存到配置文件中,如果含有中文,会储存为Unicode码

     public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
//        加载指定配置文件
        properties.load(new BufferedReader(new FileReader("D:\\java高级部分\\JavaIo\\源\\My.properties")));
//        将整个Properties文件输出到某个地址
        properties.list(System.out);
        PrintWriter PW = new PrintWriter(new FileWriter("D:\\java高级部分\\JavaIo\\源\\One.txt"));
        properties.list(PW);
        PW.close();
//         获取某一个键的值
        String user = properties.getProperty("User");
        String password = properties.getProperty("password");
        System.out.println(user+" "+password);
//        设置键值对到Properties对象里(此时并未储存,只是在内存中)
         如果没有这个键就是创建,有就是修改
        properties.setProperty("name","刘超");
        properties.setProperty("age","20");
//          将Properties储存的键值对储存到配置文件中
          第一个参数是:输出流的位置    第二个参数是:注释
        properties.store(new FileWriter("D:\\java高级部分\\JavaIo\\源\\My2.properties"),null);
    }

你可能感兴趣的:(IO流)