java 字节流 字符流 的详细介绍

1.IO流

 1.1 IO流的概念

      我们把数据的传输,可以看成一种数据的流动,按照流动的方向,以内存为基准,分为输入input输出output,即流向内存的是输入流,流出内存的叫输出流

      java中I/O操作主要是指使用java.io包下内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做写出数据

1.2 IO的分类

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

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

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

   根据格局数据的类型分为:字节流和字符流。

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

               字符流:以字符为单位,读写数据的流、

1.3 IO的流向说明

                 硬盘——>内存      输入

                 硬盘<——内存     输出

   1.4 顶级父类

             

 输入流输出流
字节流

字节输入流

InputStream

字节输出流

OutputStream

字符流

字符输入流

Reader

字符输出流

Write

2.字节流

       一切数据在存储时,都是以二进制数字的形式保存的,都是一个一个的字节,那么数据在传输时也是一样的。因此字节流可以传输任意文本数据。在操作流的时候,我们要明确,无论使用什么样的流对象,底层传输的始终是二进制数据。

 

2.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 abstract void write(int b) :将指定的字节输出流。

2.2 FileOutputStream类

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

 构造方法:

                public FileOutputStream(File file) :创建文件输出流以写入由指定的 File对象表示的文件。

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

           构造文件输出流对象。 

public class Demo {
    public static void main(String[] args) throws FileNotFoundException {
        //创建file对象
        File file=new File("aaa.txt");
        //以file对象为参数,构造文件输出流对象
        FileOutputStream fos=new FileOutputStream(file);
        
        //以文件名字构造文件流对象
        FileOutputStream fos1=new FileOutputStream("b.txt");
    }
}

 写出字节数据

                1.写出字节:

                             Write(int b)方法,每次可以写出一个字节数据。

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

 

  这段代码就会在D:\javawrite\src\Demo\day06中先创建一个文件a.txt ,然后创建一个输出流对象,依次写入a b c 三个字节。

         2.写出字节数组

                 write(byte[] b),每次可以写出数组中的数据。

public class Demo {
    public static void main(String[] args) throws IOException {
        //以文件名字创建文件流对象
        FileOutputStream fos=new FileOutputStream("D:\\javawrite\\src\\Demo\\day06\\c.txt");
        //字符串转换成字节数组
        byte[] b="路飞".getBytes();
        //写出字节数组数据
        fos.write(b);
        //关闭资源
        fos.close();
    }
}

        这段代码就会在D:\javawrite\src\Demo\day06中先创建一个文件c.txt ,然后创建一个输出流对象,写出字节数组数据“路飞"。   

        3.写出指定长度字节数组;

                   write(byte[] int off,int len):每次写出从off索引开始,len个字节。

public class Demo {
    public static void main(String[] args) throws IOException {
        //以文件名字创建文件流对象
        FileOutputStream fos=new FileOutputStream("D:\\javawrite\\src\\Demo\\day06\\d.txt");
        //字符串转换成字节数组
        byte[] b="abcde".getBytes();
        //写出字节数组数据
        fos.write(b,2,2);
        //关闭资源
        fos.close();
    }

       这段代码就会在D:\javawrite\src\Demo\day06中先创建一个文件d.txt ,然后创建一个输出流对象,写出指定长度的字节数组,从”abcde“的第二个索引开始,长度为2,就是”cd“.

  

数据追加续写:

         上述的代码演示,每次程序运行,创建输出流对象,都会清空文件中的数据,重写写入,可是我们怎么样才能保留目标文件中的数据,然后在新添加数据呢?

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

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

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

public class Demo {
    public static void main(String[] args) throws IOException {
        //以文件名字创建文件流对象
        FileOutputStream fos=new FileOutputStream("D:\\javawrite\\src\\Demo\\day06\\a.txt",true);
        //字符串转换成字节数组
        byte[] b="abcde".getBytes();
        //写出字节数组数据
        fos.write(b,2,3);
        //关闭资源
        fos.close();
    }
}

     原来的a.txt中有字符创“cd”,经过上述代码后,变为“cdcde”,表示可以续写。

 

写出换行:

     在Windows系统中,换行符号是\r\n。

public class Demo {
    public static void main(String[] args) throws IOException {
        //以文件名字创建文件流对象
        FileOutputStream fos=new FileOutputStream("D:\\javawrite\\src\\Demo\\day06\\a.txt",true);
        //字符串转换成字节数组
        byte[] words = {97,98,99,100,101};
        //遍历数组
        for (int i = 0; i < words.length; i++) {
            fos.write(words[i]);
            fos.write("\r\n".getBytes());
        }
        fos.close();
    }
}

      在文件a中的输出结果为 a b c d e  每个都是换行的。   

           回车符 \r 和换行符 \n

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

        各个操作系统中的换行:

              Windows系统中,每行皆为都是回车+换行,即\r\n

              Lunix系统中,每行的结尾值换行,即\n

              Max系统里,每行的结尾是回车,即\r

 

 

2.3 字节输入流

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

          public void close():关闭此输入流并释放与此相关联的任何系统资源。

          public  abstract int read():从输入流读取数据的下一个字节。

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

2.4 FileInputStream类

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

构造方法;

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

        FileInputStream(String name) : 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名                                                                 name命名。

  当创建一个流对象,必须传入一个文件路径,该路径下如果没有文件,就会抛出异常FileNotFoundException。

public class Demo {
    public static void main(String[] args) throws IOException {
    //使用File对象创建输入流对象
    File file=new File("D:\\javawrite\\a.txt");
    file.createNewFile();
    FileInputStream fis=new FileInputStream(file);
     //使用文件名创建输入流对象
     FileInputStream fis1=new FileInputStream("b.txt");
    }
}

读取字节数据:

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

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

       文件夹b.txt中原有数据abcd ,读取结果如程序所示。

循环改进读取的方式:

public class Demo {
    public static void main(String[] args) throws IOException {
        //使用文件名创建输入流对象
         FileInputStream fis=new FileInputStream("b.txt");
         int read;
         while((read=fis.read())!=-1){
            System.out.println((char) read);
         }
        //关闭资源
        fis.close();
    }
}
a
b
c
d

    注:read读取的字节,自动会提升为int类型,操作完毕后,一定要释放资源

          2.使用字节数组读取:

                   read(byte[] b),每次读取到b长度的字节到数组中,返回读取到的有效字节个数,读取到末尾是,返回-1.

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

     我们可以看出最后有一个错误数据ed,是因为最后一次读取,只能读取到一个字节e,在数组中,上次读取的数据就没有被完全替代,因此要通过len,获取有效字节。

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

 

2.5 字节流练习:图片复制;

             复制原理图解:

               

public class Demo {
    public static void main(String[] args) throws IOException {
        //1创建输出流对象
        //先指定数据源
        FileInputStream fis=new FileInputStream("D:\\1.jpg");
        //指定复制的mdd
        FileOutputStream fos=new FileOutputStream("copy_1.jpg");
        //读写数据
        //2.1 定义数组
        byte[]  b=new byte[1024];
        //2.2 定义长度
        int len;
        //2.3循环读取
        while ((len=fis.read(b))!=-1){
            fos.write(b,0,len);
        }
        //3.关闭资源
        fis.close();
        fos.close();
    }
}

        复制的文件都会存在java程序所在的目录下。

 

3.字符流

        当使用字节流去读文件文本时,可能会遇到一个问题,就是遇到中文字符时,可能不会完全显示,因为中文字符可能会占用多个字节,因此java中提供了一些字符流,以字符为单位读写数据,用来专门处理文本文件。

3.1 字符输入流【Reader】

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

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

        public int read():从输入流读取到一个字符。

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

3.2 FileReader类

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

          字符编码:字节与字符的对应规则。windows系统汇总的中文编码默认是GBK编码表。

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

构造方法:

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

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

    当要创建一个流对象是,必须要闯入一个文件路径。类似FileInputStream。

public class Demo {
    public static void main(String[] args) throws IOException {
        //使用File对象创建FileRead流对象
        File file=new File("aa.txt");
        file.createNewFile();
        FileReader fr=new FileReader(file);
        //使用文件名字创建FileRead流对象
        FileReader fr1=new FileReader("b.txt");
    }
}

  读取字符数据:

           1.读取字符:

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

public class Demo {
    public static void main(String[] args) throws IOException {
        //使用文件名字创建FileRead流对象
        FileReader fr=new FileReader("b.txt");//b 中的字符串为路飞橡胶
        //定义变量,保存数据
        int len;
        //循环读取
        while ((len=fr.read())!=-1){
            System.out.println((char) len);
        }
        //关闭资源
        fr.close();
    }
}
路
飞
橡
胶

        2.使用字符串数组读取:

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

public class Demo {
    public static void main(String[] args) throws IOException {
        //使用文件名字创建FileRead流对象
        FileReader fr=new FileReader("b.txt");//路飞橡胶者
        //定义变量,保存数据
        int len;
        //定义字符数组,作为装字符数据的容器
        char[] cbuf=new char[2];
        //循环读取
        while ((len=fr.read(cbuf))!=-1){
            System.out.println(new String(cbuf));
        }
        //关闭资源
        fr.close();
    }
}
路飞
橡胶
者胶

        和FileInputStream一样,要获取有效的字符,需要改进:

public class Demo {
    public static void main(String[] args) throws IOException {
        //使用文件名字创建FileRead流对象
        FileReader fr=new FileReader("b.txt");//路飞橡胶者
        //定义变量,保存数据
        int len;
        //定义字符数组,作为装字符数据的容器
        char[] cbuf=new char[2];
        //循环读取
        while ((len=fr.read(cbuf))!=-1){
            System.out.println(new String(cbuf,0,len));
        }
        //关闭资源
        fr.close();
    }
}
路飞
橡胶
者

  3.3 字符输出流【Write】

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

          void write(int c) 写入单个字符。

         void write(char[] cbuf) 写入字符数组。

        abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分,off数组的开始索引,len写的字符个数。

        void write(String str) 写入字符串。

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

        void flush() 刷新该流的缓冲。

        void close() 关闭此流,但要先刷新它。

3.4 FileWrite类

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

构造方法:

         FileWriter(File file) : 创建一个新的 FileWriter,给定要读取的File对象。

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

当要创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。

public class Demo {
    public static void main(String[] args) throws IOException {
        //使用File对象创建FileWrite流对象
        File file =new File("ab.txt");
        FileWriter fw=new FileWriter(file);
        //使用文件名称创建FileWrite流对象
        FileWriter fw1=new FileWriter("abc.txt");
    }
}

   写出基本数据:  

            写出字符:write(int b)方法,每次可以写出一个字符数据。

public class Demo {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建FileWrite流对象
        FileWriter fw=new FileWriter("abc.txt");
        //写出数据
        fw.write(97);// 写出第1个字符
        fw.write('b');// 写出第2个字符
        fw.write('c');// 写出第3个字符
        fw.write(30000);// 写出第4个字符,中文编码表中30000对应一个汉字。
        fw.close();
    }
}

         注:   虽然参数为int类型四个字节,但是只会保留一个字符的信息写出。未调用close方法,数据只是保存到了缓冲区,并未写出到文件中。

    关闭和刷新

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

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

      close:先刷新缓冲器,然后通知系统释放资源,流对象不可继续在使用。

public class Demo {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建FileWrite流对象
        FileWriter fw=new FileWriter("abc.txt");
        //写出数据,通过flush
        fw.write('刷');
        fw.flush();
        fw.write('新');
        fw.flush();

        //写出数据,通过close
        fw.write('关');
        fw.close();
        //fw.write('闭');//报错java.io.IOException: Stream closed
       // fw.close();

    }
}

    

写出其它数据:

     1.写出字符数组:

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

public class Demo {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建FileWrite流对象
        FileWriter fw=new FileWriter("abc.txt");
        //字符串转换成字节数组
        char[] chars="路飞橡胶者".toCharArray();
        //写出字符数组
        fw.write(chars);//路飞橡胶者
        //写出从索引2 开始,2个字节
        fw.write(chars,2,2);
        //关闭资源
        fw.close();
    }
}

        

         2.写出字符串:

                  write(String str) 和 write(String str, int off, int len) ,每次可以写出字符串中的数据。

public class Demo {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建FileWrite流对象
        FileWriter fw=new FileWriter("abc.txt");
        //字符串
        String s="路飞索隆山治呀";
        //写出字符数组
        fw.write(s);//路飞索隆山治呀
        //写出从索引2 开始,2个字节
        fw.write(s,2,3);
        //关闭资源
        fw.close();
    }
}

         3. 续写和换行

public class Demo {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建FileWrite流对象
        FileWriter fw=new FileWriter("abc.txt",true);
        //字符串
        String s="路飞索隆山治呀";
        //写出字符数组
        fw.write(s);//路飞索隆山治呀
        fw.write("\r\n");
        //写出从索引2 开始,2个字节
        fw.write(s,2,3);
        //关闭资源
        fw.close();
    }
}

          

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值