java中的IO流的学习笔记

一、File类的使用

1.File类的理解

1.File类的一个对象,代表一个文件或者一个文件目录(俗称s:文件夹)
2.File类声明在java.io包下
3.File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,
并未涉及到写入或读取文件内容的操作。如果需要读取或写入文件内容,必须使用IO流来完成。
4.后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的“终点”.

2. File类的实例化

2.1 常用构造器

       File(String filePath)
       File(String parentPath,String childPath)
       File(File parentFile, String childPath)

2.2 路径的分类

相对路径:相较于某个路径下,指明的路径。
绝对路径:包含盘符在内的文件或文件目录的路径。
说明:
IDEA中
如果开发使用JUnit中的单元测试方法测试,相对路径即为当前Module下。
如果使用main()测试,相对路径都是当前的Project下。
Eclipse中:
不管使用单元测试方法还是使用main()测试,相对路径都是当前的Project下。

2.3 路径分隔符

windows:\
unix:/

3.file类的常用方法

public String getAbsolutePath(): 获取绝对路径
public String getPath():获取路径
public String getName():获取名称
public String getParent():获取上层文件目录路径。若无,返回null
public long length():获取文件长度(即:字节数)。不能获取目录的长度。
public long lastModified():获取最后一次的修改时间,毫秒值

如下的两个方法适用于目录:
public String[] list():获取指定目录下的所有文件或者目录的名称数组
public File[] listFiles():获取指定目录下的所有文件或文件目录的File数组
public boolean renameTo(File dest): 把文件重命名为指定的文件路径
    比如file1.renameTo(file2)为例:
        要想保证返回true,需要file1在硬盘中是存在的,且file2不能在硬盘中存在。
public boolean isDirectory():判断是否是文件目录
public boolean isFile():判断是否是文件
public boolean exists():判断是否存在
public boolean canRead():判断是否可读
public boolean canWrite():判断是否可写
public boolean isHidden:判断是否隐藏
创建硬盘中对应的文件或文件目录
public boolean createNewFile():创建文件。若文件存在,则不创建,返回false
public boolean mkdir():创建文件目录。如果此文件目录存在,就不创建了。如果次文件目录的上层文件目录不存在,也不创建。
public boolean mkdirs():创建文件目录。如果上层文件目录不存在,一并创建

删除磁盘中的文件或文件目录
public boolean delete():删除文件或文件夹
    删除注意事项:
        Java中的删除不走回收站。

二、IO流的概述

1.流的分类

1.操作数据单位:字节流、字符流
2.数据的流向:输入流、输出流
3.流的角色:字节流、处理流

2.重点说明的几个流结构

 抽象基类           节点流(或文件流)                                   缓冲流(处理流的一种)
InputStream        FileInputStream (read(byte[] cbuf))                BufferedInputSteam (read(byte[] cbuf))
OutputStream       FileOutputStream (write(byte[] buffer, 0, len)     BufferedOutputSteam (write(byte[] buffer, 0, len)
Reader             FileReader (read(char[] cbuf))                     BufferedReader (read(char[] cbuf) / readline())
Writer             FileWriter (write(char[] cbuf, 0, len)             BufferedWriter (write(char[] cbuf, 0, len)

3.输入、输出的标准化过程

3.1 输入过程

① 创建File类的对象,指明读取的数据的来源。(要求此文件一定要存在)
② 创建相应的输入流,将File类的对象作为参数,传入流的构造器中
③ 具体的读入过程
创建相应的byte[] 或 char[]
④ 关闭流资源
说明:程序中出现的异常需要使用try-catch-finally处理。

3.2 输出过程

① 创建File类的对象,指明写出的数据的位置。(不要求此文件一定要存在)
② 创建相应的输出流,将File类的对象作为参数,传入流的构造器中
③ 具体的读出过程
write( char[] /byte[] buffer, 0, len)
④ 关闭流资源
说明:程序中出现的异常需要使用try-catch-finally处理。

三、节点流(或文件流)

1.FileReader /FileWriter的使用:

1.1FileReader的使用

    @Test
    public void testFileReader1() {
        //1.File类的实例化
        File file = new File("hello.txt");
        FileReader fr = null;
        try {
            //2.FileReader流的实例化
            fr = new FileReader(file);

            //3.读入的操作
            //read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。如果达到文件末尾,返回-1.
            char[] cbuf = new char[5];
            int len;
            while ((len = fr.read(cbuf))!=-1){
                //方式一:
                //错误的写法
//                for (int i = 0 ;i<cbuf.length;i++){
//                    System.out.print(cbuf[i]);
//                }
                //正确的写法
//                for (int i = 0 ;i<len;i++){
//                    System.out.print(cbuf[i]);
//                }

                //方式二:
                //错误的写法,对应方式一的错误的写法
//                String str = new String(cbuf);
//                System.out.print(str);
                //正确的写法
                String str = new String(cbuf,0,len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fr!=null){
                //4.资源的关闭
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }    

说明点:
1.read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1
2.异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally来处理
3.读入的文件一定要存在,否则就会报FileNotFoundException。

1.2 FileWriter的使用

从内存中写出数据到硬盘的文件里

说明:
	1. 输出操作,对应的File可以不存在的。并不会报异常。
	2.
 	 File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。
	 File对应的硬盘中的文件如果存在:
    	如果流使用的构造器是:FileWriter(file, false) / FileWriter(file):对原有文件的覆盖
    	如果流使用的构造器是:FileWriter(file, true):不会在原有文件进行覆盖,而且在原有文件基础上追加数据
    @Test
    public void testFileWriter(){
        FileWriter fw = null;

        try {
            //1.提供file类对象,指明写出到的文件
            File file = new File("hello1.txt");

            //2.提供FileWriter的对象,用于数据的写出
            fw = new FileWriter(file);

            //3.写出的操作
            fw.write("I have a dream!\n");
            fw.write("You need to have a dream!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fw!=null){
                try {
                    //流资源的关闭
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

1.3 文本文件的复制:

@Test
    public void testFileReaderFileWriter() {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            //1.创建File类的对象,指明读入和写出的文件
            File srcfile = new File("hello.txt");
            File destfile = new File("hello2.txt");

            //不能使用字符流来处理图片等字节数据

            //2.创建输入流和输出流的对象
            fr = new FileReader(srcfile);
            fw = new FileWriter(destfile);


            //3.数据的读入和写出操作
            char[] cbuf = new char[5];
            int len;//记录每次读入到cbuf数组中的字符的个数
            while ((len = fr.read(cbuf))!=-1){
                //每次写出len个字符
                fw.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();

        } finally {
            //4.流资源的关闭
            //方式一:
//            try {
//                fw.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }finally {
//                try {
//                    fr.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }

            //方式二:
            try {
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

2.FileInputStream / FileOutputStream的使用:

1.对于文本文件(.txt, .java, .cpp),使用字符流处理
2.对于非文本文件(.jpg, .mp3, .mp4, .avi, .doc, .ppt,…),使用字节流处理

 /*
   实现对图片的复制操作

    */
   @Test
   public void testFileInputOutputStream() {
       FileInputStream fis = null;
       FileOutputStream fos = null;
       try {
           File srcfile = new File("黄山.jpg");
           File destfile = new File("黄山1.jpg");

           fis = new FileInputStream(srcfile);
           fos = new FileOutputStream(destfile);

           //复制的过程
           byte[] buffer = new byte[5];
           int len;
           while ((len = fis.read(buffer))!=-1){
               fos.write(buffer,0,len);
           }
       } catch (IOException e) {
           e.printStackTrace();
       } finally {
           //
           if(fos!=null){
               try {
                   fos.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
           if(fis!=null){
               try {
                   fis.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
       }
   }

四、缓冲流的使用:

1. 缓冲流涉及到的类:

BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter

2.作用:

提供流的读取、写入的速度
提高读写速度的原因:内部提供了一个缓冲区。默认情况下是8kb

3. 典型代码:

3.1 使用BufferedInputStream和BufferedOutStream:

处理非文本文件

/*
   实现文件复制的方法
    */
   public void copyFileWithBuffered(String srcPath, String destPath){
       BufferedInputStream bis = null;
       BufferedOutputStream bos = null;

       try {
           //1.造文件
           File srcfile = new File(srcPath);
           File destfile = new File(destPath);
           //2.造流
           //2.1 造节点流
           FileInputStream fis = null;
           fis = new FileInputStream(srcfile);
           FileOutputStream fos = new FileOutputStream(destfile);
           //2.2 造缓冲流
           bis = new BufferedInputStream(fis);
           bos = new BufferedOutputStream(fos);
           //3.复制的细节:读取、写入
           byte[] buffer = new byte[5];
           int len ;
           while ((len = bis.read(buffer))!=-1){
               bos.write(buffer,0,len);

//                bos.flush();//刷新缓冲区
           }
       } catch (IOException e) {
           e.printStackTrace();
       } finally {

           //4.资源的关闭
           //要求:先关闭外层的流,再关闭内层的流
           if(bos!=null){
               try {
                   bos.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
           if(bis!=null) {
               try {
                   bis.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
           //关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略。
//        fos.close();
//        fis.close();
       }
   }

3.2 使用BufferedReader和BufferedWriter:

/*
  使用BufferedReader和BufferedWriter实现文本文件的复制。
   */
  @Test
  public void testBufferedReaderBufferedWriter() {
      BufferedReader br = null;
      BufferedWriter bw = null;
      try {
          //创建文件和相应的流
          br = new BufferedReader(new FileReader(new File("hello.txt")));
          bw = new BufferedWriter(new FileWriter(new File("hello3.txt")));

          //读写操作
          //方式一:
//            char[] cbuf = new char[5];
//            int len;
//            while ((len = br.read(cbuf))!=-1){
//                bw.write(cbuf,0,len);
//    //            bw.flush();
//            }
          //方式二:
          String data;
          while ((data = br.readLine())!=null){
              //方法一:
//                bw.write(data+"\n");//data中不包含换行符
              //方法二:
              bw.write(data);//data中不包含换行符
              bw.newLine();//提供换行的操作
          }
      } catch (IOException e) {
          e.printStackTrace();
      } finally {
      //关闭资源
          if(br!=null){
              try {
                  br.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
          if(bw!=null){
              try {
                  bw.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }

  }

五、转换流

1. 转换流涉及到的类:

InputStreamReader:将一个字节的输入流转换为字符的输入流
	解码:字节、字节数组 --->字符数组、字符串
	
OutputStreamWriter:将一个字符的输出流转换为字节的输出流
	编码:字符数组、字符串 --->字节、字节数组

说明:编码决定了解码的方式

2. 作用:

提供字节流与字符流之间的转换

3. 典型实现

    @Test
    public void test1() throws IOException {
        FileInputStream fis = new FileInputStream("dbcp.txt");

//        InputStreamReader isr = new InputStreamReader(fis);//使用系统默认的字符集
        //参数2指明了字符集,具体使用哪个字符集,取决于文件dbcp.txt保存时使用的字符集。
        InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);//使用系统默认的字符集

        char[] cbuf = new char[5];
        int len;
        while ((len = isr.read(cbuf))!=-1){
            String str = new String(cbuf, 0, len);
            System.out.print(str);
        }
        isr.close();

    }

4. 说明

文件编码的方式(比如:GBK),决定了解析时使用的字符集(也只能是GBK)

5.常见的编码表

 ASCII:美国标准信息交换码
    用一个字节的7位可以表示。
 ISO8850-1:拉丁码表。欧洲码表
    用一个字节的8位表示。
 GB2312:中国的中文编码表。最多两个字节编码所有字符
 GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码。
 Unicode:国际标准码,融合了目前人类使用的所有字符,为每一个字符分配唯一的字符码。所有的文字都用两个字节表示。
 UTF-8:变长的解码方式,可用1-4个字节来表示一个字符。

六、其他的几个处理流

1.标准的输入、输出流

System.in:标准的输入流,默认从键盘输入
System.out:标准的输出流,默认从控制台输出

修改默认的输入和输出行为:
System类的setIn(InputStream is) / setOut(PrintStream ps)方式重新指定输入和输出的流

2.打印流

PrintStream 和 PrintWriter

说明:
		提供了一系列重载的print()和println()方法,用于多种数据类型的输出
		System.out返回的是PrintStream的实例

3. 输出流

DataInputStream 和 DataOutputStream
作用:用于读取或写出基本数据类型的变量或字符串

七、对象流的使用

1. 对象流

ObjectInputStream 和ObjectOutputStream

2. 作用

ObjectOutputStream:内存中的文件 ---->存储中的文件、通过网络传输出去 :序列化过程
ObjectInputStream:存储中的文件、通过网络接受进来 ---->内存中的文件:反序列化过程

3. 对象的序列化机制

对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。 当其他程序获取了这种二进制流,就可以恢复成原来的java对象。

4. 序列化过程代码实现

/*
    序列化过程:将内存中的java对象保存操磁盘中或通过网络传输出去
    使用ObjectOutputStream实现w
     */
    @Test
    public void testObjectOutputStream() {

        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));

            oos.writeObject(new String("我爱北京天安门"));

            oos.flush();//刷新操作

            oos.writeObject(new Person("王明",23));
            oos.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(oos!=null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

5.反序列化代码实现

/*
    反序列化:将磁盘文件中的对象还原为内存中的一个java对象
    使用ObjectInputStream来实现
     */
    @Test
    public void testObjectInputStream(){
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("object.dat"));

            Object obj = ois.readObject();
            String str = (String) obj;

            Person p = (Person) ois.readObject();

            System.out.println(str);
            System.out.println(p);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if(ois!=null){

                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

6.实现序列化的对象所属的类需要满足:

  1. 需要实现接口:Serializable
  2. 需要当前类提供一个全局常量:serialVersionUID
  3. 除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性
    也必须是可序列化的。(默认情况下,基本数据类型可序列化)

补充: ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量

八、RandomAccessFile的使用

1. 随机存取文件流

RandomAccessFile

2.使用说明:

1.RandomAccessFile直接继承与java.lang.Object类,实现了DataInput和DataOutput接口
2.RandomAccessFile既可以作为输入流,又可以作为一个输出流

3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建
如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖)

4.可以通过相关的操作,实现RandomAccessFile接口实现插入数据操作

3. 典型代码

@Test
   public void test1() {
       RandomAccessFile raf1 = null;
       RandomAccessFile raf2 = null;
       try {
           raf1 = new RandomAccessFile(new File("黄山.jpg"), "r");
           raf2 = new RandomAccessFile(new File("黄山1.jpg"), "rw");

           byte[] buffer = new byte[1024];
           int len;
           while ((len = raf1.read(buffer))!=-1){
             raf2.write(buffer,0,len);
           }
       } catch (IOException e) {
           e.printStackTrace();
       }finally {
           if (raf1!=null){

               try {
                   raf1.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
           if (raf2!=null){
               try {
                   raf2.close();
               } catch (IOException e) {
                   e.printStackTrace();
               }

           }
       }
   }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值