I/O流(一)--------文件专属

 

目录

一、I/O概述

1、什么是IO

2、 IO的分类

   2.1、根据数据的流向分为:输入流和输出流

  2.2、根据数据的类型分为:字节流和字符流。

3、  顶级父类

二、字节流

1 、字节输出流OutputStream

2、 FileOutputStream类(文件专属)

2.1、创建流对象

2.2、写出字节数据:

2.3数据追加续写

2.4写出换行

 

3、 字节输入流InputStream

4、FileInputStream类(文件专属)

4.1构造方法:

4.2读取字节数据

                                                                               ​                             

4.3、 FileInputStream类的其他常用方法

三、字符流

1、 字符输入流Reader

2、 FileReader类(文本文件专属)

2.1、构造方法:

2.2、读取字符数据

3、字符输出流Writer

4、FileWriter类(文本文件专属)

4.1、构造方法: 

4.2、基本写出数据

4.3、写出其他数据

四、文件复制        

1、使用FileInputStream和FileOutputStream来实现文件的拷贝

2、使用FileReader和FileWriter对文本文件进行复制


一、I/O概述

1、什么是IO

   生活中,你肯定经历过这样的场景,当你编辑一个文本文件,忘记了ctrl+s,可能文件就白白编辑了。当你电脑插入一个U盘,可以把一个视频,拷贝到你的电脑硬盘里,那么数据都是在那些设备上呢?键盘、内存、硬盘、外设等等。我们把这种数据的传输,可以看作是一种数据的流动,按照流动的方向,以内存为基准,分为输入input和输出output,即流向内存是输入流,流出内存是输出流。

   Java中io操作主要是指用java.io包下的内容,进行输入、输出操作,输入也叫做读取数据,输出也叫做写出数据。Java中所有的流都在java.io.*包下。

2、 IO的分类

   2.1、根据数据的流向分为:输入流和输出流

          输入流:把数据从其他设备上读取到内存中的流。

          输出流:把数据从内存中写出到其他设备上的流。

  2.2、根据数据的类型分为:字节流和字符流。

          字节流:以字节(byte)为单位,读写数据的流

          字符流:以字符(char)为单位,读写数据的流

注意:在Java中只要"类名"以“Stream”结尾都是字节流,以“Reader/Writer”结尾的都是字符流

3、  顶级父类

 

输入流

输出流

字节流

字节输入流 InputStream

字节输出流 OutputStream

字符流

字符输入流 Reader

字符输出流 Writer

注意:

    1、这四个类均为抽象类

    2、这四个类都实现了Java.io.Closeable接口,所有的流都是可关闭的,都有close()方法,流毕竟是一个管道,这个是内存与硬盘之间的通道,用完之后一定晏关闭,不然会浪费很多资源。

    3、所有的输出流都实现了java.io.Flashable接口。都是可刷新的,都有flash()方法。输出流在最终输出后,一定要记得flash()方法,这个刷新表示将管道/通道当中剩余未输出的数据强行输出完,刷新的作用就是清空管道!如果没有flash()可能会丢失数据。

二、字节流

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都是一个一个的字节,那么传输时一样如此。所以,字节流可以传入任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。

注意:

字节流是一个一个字节读取的,字母占一个字节,中文占两个字节,所以读中文时一次只能读该字符的一半

        

1 、字节输出流OutputStream

 Java.io.OutputStream 抽象类是表示字节输出流的所有的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。

  Public void close();关闭此输出流并释放与此流相关联的任何系统资源。

  Public void flush();刷新此输出流并强制任何缓冲流的输出字节被写出。

  Public void write(byte[] b);将b.length字节从指定的字节数组写入此输出流

  Public void write(byte[] b,int off,int len);从指定的字节数组写入len字节,从偏移量off开始输出到此输出流

  Public void write(int b);将指定的字节输出流

2、 FileOutputStream类(文件专属)

OutputStream有很多子类,java.io. FileOutputStream类是文件输出流,用于将数据写出到文件

2.1、创建流对象

当你创建一个流对象时,必须传入一个文件路径,该路径下,如果没有这个文件,会创建该文件。如果有这个文件,会清空这个文件的数据。再写入。代码如下:

public class FileOutputStreamDemo {
    public static void main(String[] args) throws FileNotFoundException {
        //使用File对象创建流对象
        File file = new File("d:\\a.txt");
        FileOutputStream fos1 = new FileOutputStream(file);
        //使用文件名称创建流对象
        FileOutputStream fos2 = new FileOutputStream("d:\\b.txt");
    }
}

2.2、写出字节数据:

2.2.1、写出字节:write(int b)方法  每次可以写出一个字节数据,代码使用演示:

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileOutputStream fos = new FileOutputStream("d:\\a.txt");
        //写出数据
        fos.write(97);
        fos.write(98);
        fos.write(99);
        //关闭资源
        fos.close();
    }
}

2.2.2、写出字节数组:write(byte[] b) 每次可以写出数组中的数据,使用代码演示:

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileOutputStream fos = new FileOutputStream("d:\\a.txt");
        byte[] b = "Good Good Study".getBytes();
        //写出字节数组数据
        fos.write(b);
        //关闭资源
        fos.close();
    }
}

2.2.3、写出指定长度字节数组: write(byte[] b,int off,int len)每次写出从off索引开始,len个字节,代码使用演示

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileOutputStream fos = new FileOutputStream("d:\\a.txt");
        byte[] b = "day day up".getBytes();
        //写出字节数组数据
        fos.write(b,2,2);
        //关闭资源
        fos.close();
    }
}

备注:写出的是y+空格

2.3数据追加续写

经过上面的演示,每次程序运行,创建出流对象,就会清空目标文件中的数据,如何保留目标文件中的数据,还能继续添加新数据吗?

Public FileOutputStream(File file,Boolean append);创建文件输出流以写入由指定的File对象表示的文件。

Public FileOutputStream(String name,booean append):创建文件输出流以指定的名称写入文件。

这两个构造方法,参数中都需要传入一个Boolean类型的值,true表示追加数据,false表示清空原有数据据,这样创建的输出流对象,就可以指定是否追加续写了,

【代码演示】

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        //创建流对象
        FileOutputStream fos = new FileOutputStream("D:\\a.txt", true);
        //字符串转换为字节数组
        byte[] b = "hello".getBytes();
        //写数据
        fos.write(b);
        //关闭资源
        fos.close();
    }
}

2.4写出换行

  Windows系统里,换行符号是\r\n。把\r\n以指定是否追加续写,代码使用演示:

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        //创建流对象
        FileOutputStream fos = new FileOutputStream("D:\\a.txt");
        //字符串转换为字节数组
        byte[] b = {97,98,99,100,101};
        //遍历数组
        for(int i=0;i<b.length;i++){
            //写出一个字节
            fos.write(b[i]);
            //写出一个换行,换行符号转成数组写出
            fos.write("\r\n".getBytes());
        }
        //关闭资源
        fos.close();
    }
}

注意:

回车符 \r 和换行符\n

  回车符:回到一行的开头(return)

  换行符:下一行(newline

系统中的换行:

   Windows系统里,每行结尾都是回车+换行,即\r\n

   Linux系统里,每行结尾之后换行,即\n

   Mac系统,每行结尾都是回车,即\r。从Mac OS X开始与Linux统一。

 

3、 字节输入流InputStream

  Java.io.InputStream 抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。  

  Public void close();关闭此输入流并释放与此流相关的任何系统资源

  Public abstract int read();从输入流读取数据的下一个字节

  Public int read(byte[] b):从输入流中读取一些字节数,并将他们存储到字节数组b中

4、FileInputStream类(文件专属)

Java.io.FileInputStream 类是文件输入流,从文件中读取字节。

4.1构造方法:

   FileInputStream(File file):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的File对象file命名。

  FileInputStream(String name);通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name 命名。当你创建一个流对象时,必须传入一个文件路径,该路径下,如果没有该文件,会抛出FileNotFoundException。代码如下:

public class FlieInputStreamDemo {
    public static void main(String[] args) throws FileNotFoundException {
        //使用File对象创建流对象(字节输入流)
        File file = new File("d:\\a.txt");
        FileInputStream fos1 = new FileInputStream(file);
        //使用文件名来创建流对象
        FileInputStream fos2 = new FileInputStream("d:\\a.txt");
    }
}

 

4.2读取字节数据

4.2.1、读取字节:read方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1,

【代码演示】

public class FISRead {
    public static void main(String[] args) throws IOException {
        //使用文件名来创建流对象
        FileInputStream fis = new FileInputStream("d:\\a.txt");
        //读取数据,返回一个字节
        int b;
        while ((b=fis.read())!=-1){
            System.out.println((char)b);
        }
        //关闭资源
        fis.close();
    }
}

4.2.2、使用字节数组读取:read(byte[] b),每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1

【代码演示】

public class FISRead {
    public static void main(String[] args) throws IOException {
        //使用文件名来创建流对象
        FileInputStream fis = new FileInputStream("d:\\a.txt");
        //定义变量,作为有效个数
        int len;
        //定义字节数组,作为装字节数组的容器
        byte[] b = new byte[2];
        //循环读取
        while ((len=fis.read(b))!=-1){
            //每次读取后,把数组变成字符串打印
            System.out.println(new String(b));
        }
        //关闭资源
        fis.close();
    }
}

错误修正:

a.txt中的数据为“11 22 33 a”,此时多出来一个3是由于最后一次读取时,只读取一个字节a,数组中,上次读取的数据没有被完全替换,所以要通过len,获取有效的字节

代码使用演示:

public class FISRead {
    public static void main(String[] args) throws IOException {
        //使用文件名来创建流对象
        FileInputStream fis = new FileInputStream("d:\\a.txt");
        //定义变量,作为有效个数
        int len;
        //定义字节数组,作为装字节数组的容器
        byte[] b = new byte[2];
        //循环读取
        while ((len=fis.read(b))!=-1){
            //每次读取后,把数组变成字符串打印
            System.out.println(new String(b,0,len));
        }
        //关闭资源
        fis.close();
    }
}

                                                                                                            

4.3、 FileInputStream类的其他常用方法

4.3.1、int available():返回流中剩余的没有读到的字节数量

import java.io.FileInputStream;
import java.io.IOException;
public class myclass {
    public static void main(String[] args) throws IOException {
            FileInputStream file=new FileInputStream("F:\\abc.txt"); //ab cdef
            System.out.println(file);
            //读取一个字节
            int by =file.read();
            System.out.println(by);   //97
            //还剩几个字节?
           int a=file.available();  //6
           System.out.println("还剩下的字节数长度为:"+a);
        }
    }

 int available()的用途:将byte数组的数组长度指定为总字节数量,可以一次读取文件中的所有字符。代码演示如下所示:

import java.io.FileInputStream;
import java.io.IOException;
public class myclass {
    public static void main(String[] args) throws IOException {
            FileInputStream file=new FileInputStream("F:\\abc.txt"); //ab cdef
            System.out.println(file);
            //总共有多少个字节
           int a=file.available();  //7
            //将byte数组的数组长度指定为总字节数量
           byte[] byt1=new byte[a];
           //读的次数
           int count=file.read(byt1);
           System.out.println(count);  //7
           System.out.println(new String(byt1));  //ab cdef
           long b=file.skip(2);
        }
    }

注意:这种方式不太适合大文件,因为byte数组不能太大

4.3.2、long skip(long n):跳过几个字节不读

import java.io.FileInputStream;
import java.io.IOException;
public class myclass {
    public static void main(String[] args) throws IOException {
            FileInputStream file=new FileInputStream("F:\\abc.txt"); //ab cdef
            System.out.println(file.read());//读取第一个字符 97
            file.skip(2);  //跳过两个字符
           System.out.println(file.read());//再一次读取 99
        }
    }

三、字符流

字节流虽然什么类型的数据都可以读取,但是在处理文本文件时,可能会遇到一些小问题,比如遇到中文字符,中文字符占两个字节,而字节流只能一个字节一个字节的读取,所以一次不能完整的读取整个中文字符。而字符流正好解决了这一问题,一次读取一个字符,字符流专门用于处理文本文件,不能读取图片、声音、视频等文件。

1、 字符输入流Reader

Java.io.Reader 抽象类是表示用于读写字符流的所有类的超类,可以读取字符信息到内存中,它定义了字符输入流的基本共性功能方法。

Public void close();关闭此流并释放与此流相关的任何系统资源

Public int read();从输入流读取一个字符

Public int read(char[] cbuf);从输入流中读取一些字符,并将他们存储到字符数组cbuf中。

 

2、 FileReader类(文本文件专属)

   Java.io.FileReader 类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

   注意:

  1. 字符编码:字节与字符对应的规则。Windows系统的中文编码默认的GBK编码表

Idea中UTF-8

     2.字节缓冲区:一个字节数组,用来临时存储字节数据。

2.1、构造方法:

FileReader(File file);创建一个新的FileReader,给定要读取的File对象

FileReader(String fileName);创建一个新的FileReader,给定要读取的文件的名称

2.2、读取字符数据

2.2.1、读取字符:read方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1,循环读取

public class FRRread {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建流对象
        FileReader fr = new FileReader("d:\\a.txt");//112233a
        //定义变量 保存数据
        int b;
        //循环读取
        while ((b=fr.read())!=-1){
            System.out.println((char) b);
        }
        //关闭资源
        fr.close();
    }
}

2.2.2使用字符数组读取:read(char[] cbuf),每次读取b的长度个字符到数组中,返回读取到的有效字符个数,读取到末尾时,返回-1

public class FRRread {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建流对象
        FileReader fr = new FileReader("d:\\a.txt");//112233a
        //定义变量 保存有效字符个数
        int len;
        //定义字符数组,作为装字符数据的容器
        char[] cbuf =new char[3];
        //循环读取
        while ((len=fr.read(cbuf))!=-1){
            System.out.println(new String(cbuf));
        }
        //关闭资源
        fr.close();
    }
}

获取有效的字符改进,代码使用演示:

public class FRRread {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建流对象
        FileReader fr = new FileReader("d:\\a.txt");//112233a
        //定义变量 保存有效字符个数
        int len;
        //定义字符数组,作为装字符数据的容器
        char[] cbuf =new char[3];
        //循环读取
        while ((len=fr.read(cbuf))!=-1){
            System.out.println(new String(cbuf,0,len));
        }
        //关闭资源
        fr.close();
    }
}

 

 

3、字符输出流Writer

   Java.io.Writer抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地,它定义了字符输入流的基本共性功能方法。

Void write(int c);写入单个字符

Void write (char[] cbuf);写入字符数组

   Abstract void write(char[] dbuf,int off,int len);写入字符数组的某一部分,off数组的开始索引,len写出的字符个数

Void write(String str);写入字符串

Void  write(String str,int off,int len);写入字符串的某一部分,off字符串的开始索引,len写出字符的个数。

Void flush();刷新该流的缓冲,

Void close();关闭流,但要先刷新它

4、FileWriter类(文本文件专属)

Java.io.FileWriter 类是写出字符到文件的便利类,构造时使用系统默认的字符编码和默认的字节缓冲区

4.1、构造方法: 

FileWriter(File file);创建一个新的FileWriter,给定要写入的file对象

FileWriter(String fileName);创建一个新的FileWriter,给定要写入的文件的名称

public class FileWriterDemo {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileWriter fw1 = new FileWriter("D:\\a.txt");
        //使用file对象创建流对象
        File file = new File("D:\\a.txt");
        FileWriter fw2 = new FileWriter(file);
    }
}

4.2、基本写出数据

写出字符:write(int b)方法,每次可以写出一个字符数据,代码使用演示:

public class FWrite {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileWriter fw = new FileWriter("d:\\a.txt");
        //写出数据
        fw.write(97);  //写出第一个字符
        fw.write('b');
        fw.write('c');
        fw.write(30000);  //中文编码表中的30000对应一个汉字
        fw.close();
    }
}

注意:关闭资源是,与FileOutputStream不同,如果不关闭,数据只是保存到缓冲区,并为保存到文件。

关闭和刷新:

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中,但是关闭的流对象,是无法继续写出的。如果我们既想写出数据,又想继续使用流,就需要使用flush方法了

  Flush:刷新缓冲区,流对象可以继续使用。

  Close:先刷新缓冲区,然后通知系统释放资源,流对象不可以再被使用了。

代码使用演示:

public class FWrite {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileWriter fw = new FileWriter("d:\\a.txt");
        //写出数据
        fw.write('刷');  //写出第一个字符
        fw.flush();
        fw.write('新');
        fw.flush();
        fw.write('关');
        fw.flush();
        fw.close();
        //fw.write('闭');  //报错 java.io.IOException: Stream closed
        //fw.close();
    }
}

4.3、写出其他数据

4.3.1、写出字符数组,write(char[] cbuf)和write(char[] cbuf,int off,int len),每次可以写出字符数组中的数据,用法类似FileOutputStream 代码使用演示:

public class FWrite {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileWriter fw = new FileWriter("d:\\a.txt");
        //字符串转换为字符数组
        char[] chars = "hello man".toCharArray();
        fw.write(chars);
        //fw.write(chars,2,2);
        fw.close();
    }
}

4.3.2、写出字符串,write(String str) 和wtrie(String str,int off,int len)每次可以写出字符串中的数据,更为方便,代码演示:

public class FWrite {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileWriter fw = new FileWriter("d:\\a.txt");
        //定义字符串
        String msg = "程序员";
        //写出从索引2开始,2个字节
        fw.write(msg,2,1);
        fw.close();
    }
}

 

四、文件复制        

1、使用FileInputStream和FileOutputStream来实现文件的拷贝

拷贝的过程应该是一边读一边写

使用FileInputStream和FileOutputStream字节流拷贝文件的时候,文件类型随意,什么样的文件都能拷贝

【代码演示】 

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class myclass {
    public static void main(String[] args){
        FileInputStream fis=null;
        FileOutputStream fos=null;
        try {
            //创建一个输入流
            fis=new FileInputStream("D:\\SecureCRT keygen.exe");
            //创建一个输出流
            fos=new FileOutputStream("F:\\SecureCRT keygen.exe");
            //一边读一边写
            byte[] bytes=new byte[1024*1024];  //设置一次最多拷贝1MB
            int readcount=0;
            while((readcount=fis.read(bytes))!=-1){
                fos.write(bytes,0,readcount);
            }
            //输出流最后要刷新
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //分开try不要一起try,一起try的话,其中一个出错,另一个就关不了了
            if(fos !=null){
                try{
                    fos.close();
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fis !=null){
                try{
                    fis.close();
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    }

2、使用FileReader和FileWriter对文本文件进行复制

文件字符输入流,只能读取普通的文本文件

读取文本内容时,比较方便快捷

注意:Java文件也是普通文本文件(能用记事本编辑的都是普通文本文件,普通文本文件与后缀名无关,不一定是.txt)

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class myclass {
    public static void main(String[] args){
        FileReader frs=null;
        FileWriter fws=null;
        try {
            //创建一个输入流
            frs=new FileReader("F:\\abc.txt");
            //创建一个输出流
            fws=new FileWriter("D:\\abc.txt");
            //一边读一边写
            char[] chars=new char[1024*512];  //设置一次最多读取1M
            int readcount=0;
            while((readcount=frs.read(chars))!=-1){
                fws.write(chars,0,readcount);
            }
            //输出流最后要刷新
            fws.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //分开try不要一起try,一起try的话,其中一个出错,另一个就关不了了
            if(fws !=null){
                try{
                    fws.close();
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(frs !=null){
                try{
                    frs.close();
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
    }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值