Java学习笔记 19 - 字节流(FileOutputStream/FileInputStream),字符流(FileWriter/FileReader)

本文内容介绍
1、字节流OutputStream--->FileOutputStream
2、字节流InputStream--->FileInputStream
3、文件的续写和换行符号
4、字节流复制文件读取单个字节/字节数组
5、编码表
6、字符流FileWriter类
7、字符流FileReader类
8、字符流复制文本

01字节输出流OutputStream

  • a.概念
    IO流用来处理设备之间的数据传输
    Java对数据的操作是通过流的方式,操作流的类都在IO包中
    流按流向分为两种:输入流,输出流
    流按操作类型分为两种:
    字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
    字符流 : 字符流只能操作纯字符数据,比较方便

  • b.IO流常用父类
    字节流的抽象父类:
    InputStream
    OutputStream
    字符流的抽象父类:
    Reader
    Writer

  • c.IO程序注意事项
    使用前,导入IO包中的类
    使用时,进行IO异常处理
    使用后,释放资源

  • d: 方法介绍
    void close(): 关闭此输出流并释放与此流有关的所有系统资源。
    void write(byte[] b): 将 b.length 个字节从指定的 byte 数组写入此输出流
    void write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
    abstract void write(int b) : 将指定的字节写入此输出流。

02字节输出流FileOutputStream

FileOutputStream用于写入数据文件的原始字节的流
a: FileOutputStream构造方法

* FileOutputStream(File file) 
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

* FileOutputStream(File file, boolean append) 
创建一个向指定 File 对象表示的文件中写入数据的文件输出流,以追加的方式写入。

* FileOutputStream(String name) 
创建一个向具有指定名称的文件中写入数据的输出文件流。

* FileOutputStream(String name, boolean append) 
创建一个向具有指定 name 的文件中写入数据的输出文件流,以追加的方式写入。

b: 流对象使用步骤
1. 创建流子类的对象,绑定数据目的
2. 调用流对象的方法write写
3. close释放资源

        public class FileOutputStreamDemo {
            public static void main(String[] args)throws IOException {
                FileOutputStream fos = new FileOutputStream("c:\\a.txt");
                //流对象的方法write写数据
                //写1个字节
                fos.write(97);
                //关闭资源
                fos.close();
            }
        }

c:字节输出流FileOutputStream写字节数组
void write(byte[] b): 将 b.length 个字节从指定的 byte 数组写入此输出流
void write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。

        public class FileOutputStreamDemo {
            public static void main(String[] args)throws IOException {
                FileOutputStream fos = new FileOutputStream("c:\\a.txt");
                //流对象的方法write写数据
                //写字节数组
                byte[] bytes = {65,66,67,68};
                fos.write(bytes);
                
                //写字节数组的一部分,开始索引,写几个
                fos.write(bytes, 1, 2);
                //写入字节数组的简便方式
                //写字符串
                fos.write("hello".getBytes());
                //关闭资源
                fos.close();
            }
        }

03、文件的续写和换行符号

a: 文件的续写
FileOutputStream构造方法, 的第二个参数中,加入true
b: 换行符号
在文件中,写入换行,符号换行 \r\n
\r\n 可以写在上一行的末尾, 也可以写在下一行的开头

            public class FileOutputStreamDemo1 {
                public static void main(String[] args)throws IOException {
                    File file = new File("c:\\b.txt");
                    FileOutputStream fos = new FileOutputStream(file,true);
                    fos.write("hello\r\n".getBytes());
                    fos.write("world".getBytes());
                    fos.close();
                }
            }

d: IO中的异常处理
try catch finally
1. 保证流对象变量,作用域足够
2. catch里面,怎么处理异常?
输出异常的信息,目的看到哪里出现了问题
停下程序,重新尝试
3. 如果流对象建立失败了,需要关闭资源吗?
new 对象的时候,失败了,没有占用系统资源
释放资源的时候,对流对象判断null
变量不是null,对象建立成功,需要关闭资源

        public class FileOutputStreamDemo3 {
            public static void main(String[] args) {
                //try 外面声明变量,try 里面建立对象
                FileOutputStream fos = null;
                try{
                    fos = new FileOutputStream("s:\\a.txt");
                    fos.write(100);
                }catch(IOException ex){
                    System.out.println(ex);
                    throw new RuntimeException("文件写入失败,重试");
                }finally{
                    try{
                        if(fos!=null)
                          fos.close();
                    }catch(IOException ex){
                        throw new RuntimeException("关闭资源失败");
                    }
                }
            }
        }

04 字节输入流InputStream

抽象类,字节输入流的所有类的超类

* abstract  int read() :
  从输入流中读取数据的下一个字节。
* int read(byte[] b)  
  从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
* int read(byte[] b, int off, int len) 
  将输入流中最多 len 个数据字节读入 byte 数组。
* void close() 
  关闭此输入流并释放与该流关联的所有系统资源。

05字节输入流FileInputStream

a:方法介绍

* abstract  int read() :
从输入流中读取数据的下一个字节,返回的是读取到的字节, 读取到结尾返回-1
* int read(byte[] b)  
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。
* int read(byte[] b, int off, int len) 
将输入流中最多 len 个数据字节读入 byte 数组。
* void close() 
关闭此输入流并释放与该流关联的所有系统资源。

b: 流对象使用步骤
1. 创建字节输入流的子类对象
2. 调用读取方法read读取
3. 关闭资源

        public class FileInputStreamDemo {
            public static void main(String[] args) throws IOException{
                FileInputStream fis = new FileInputStream("c:\\a.txt");
                //读取一个字节,调用方法read 返回int
                //使用循环方式,读取文件,  循环结束的条件  read()方法返回-1
                int len = 0;//接受read方法的返回值
            
                while( (len = fis.read()) != -1){
                    System.out.print((char)len);
                }
                //关闭资源
                fis.close();
            }
        }

c:字节输入流FileInputStream读取字节数组
1: 方法介绍

* int read(byte[] b)  
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。
* int read(byte[] b, int off, int len) 
 将输入流中最多 len 个数据字节读入 byte 数组。

2:案例

        /*
         *  FileInputStream读取文件
         *   读取方法  int read(byte[] b) 读取字节数组
         *   数组作用: 缓冲的作用, 提高效率
         *   read返回的int,表示什么含义 读取到多少个有效的字节数
         */
        public class FileInputStreamDemo1 {
            public static void main(String[] args) throws IOException {
                FileInputStream fis = new FileInputStream("c:\\a.txt");
                // 创建字节数组
                byte[] b = new byte[2];

                int len = fis.read(b);
                System.out.println(new String(b));// ab
                System.out.println(len);// 2

                len = fis.read(b);
                System.out.println(new String(b));// cd
                System.out.println(len);// 2

                len = fis.read(b);
                System.out.println(new String(b));// ed
                System.out.println(len);// 1

                len = fis.read(b);
                System.out.println(new String(b));// ed
                System.out.println(len);// -1

                fis.close();
            }
        }

3:实现原理

        public class FileInputStreamDemo1 {
            public static void main(String[] args) throws IOException {
                FileInputStream fis = new FileInputStream("c:\\a.txt");
                //创建字节数组
                byte[] b = new byte[1024];
                
                int len = 0 ;
                while( (len = fis.read(b)) !=-1){
                    System.out.print(new String(b,0,len));
                }
                fis.close();
            }
        }

d:字节流复制文件读取单个字节

        /*
         *  将数据源 c:\\a.txt
         *  复制到 d:\\a.txt  数据目的
         *  字节输入流,绑定数据源
         *  字节输出流,绑定数据目的
         *  
         *  输入,读取1个字节
         *  输出,写1个字节
         */
        public class Copy {
            public static void main(String[] args) {
                //定义两个流的对象变量
                FileInputStream fis = null;
                FileOutputStream fos = null;
                try{
                    //建立两个流的对象,绑定数据源和数据目的
                    fis = new FileInputStream("c:\\t.zip");
                    fos = new FileOutputStream("d:\\t.zip");
                    //字节输入流,读取1个字节,输出流写1个字节
                    int len = 0 ;
                    while((len = fis.read())!=-1){
                        fos.write(len);
                    }
                }catch(IOException ex){
                    System.out.println(ex);
                    throw new RuntimeException("文件复制失败");
                }finally{
                    try{
                        if(fos!=null)
                            fos.close();
                    }catch(IOException ex){
                        throw new RuntimeException("释放资源失败");
                    }finally{
                        try{
                            if(fis!=null)
                                fis.close();
                        }catch(IOException ex){
                            throw new RuntimeException("释放资源失败");
                        }
                    }
                }
            }
        }

e:字节流复制文件读取字节数组

        /*
         *  字节流复制文件
         *   采用数组缓冲提高效率
         *   字节数组
         *   FileInputStream 读取字节数组
         *   FileOutputStream 写字节数组
         */
        public class Copy_1 {
            public static void main(String[] args) {
                long s = System.currentTimeMillis();
                FileInputStream fis = null;
                FileOutputStream fos = null;
                try{
                    fis = new FileInputStream("c:\\t.zip");
                    fos = new FileOutputStream("d:\\t.zip");
                    //定义字节数组,缓冲
                    byte[] bytes = new byte[1024*10];
                    //读取数组,写入数组
                    int len = 0 ; 
                    while((len = fis.read(bytes))!=-1){
                        fos.write(bytes, 0, len);
                    }
                }catch(IOException ex){
                    System.out.println(ex);
                    throw new RuntimeException("文件复制失败");
                }finally{
                    try{
                        if(fos!=null)
                            fos.close();
                    }catch(IOException ex){
                        throw new RuntimeException("释放资源失败");
                    }finally{
                        try{
                            if(fis!=null)
                                fis.close();
                        }catch(IOException ex){
                            throw new RuntimeException("释放资源失败");
                        }
                    }
                }
                long e = System.currentTimeMillis();
                System.out.println(e-s);
            }
        }

06编码表

a: 定义:生活中字符和计算机二进制的对应关系表,即编码表
b: 分类
1、ascii: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx
2、iso-8859-1:拉丁码表 latin,用了一个字节用的8位。1-xxxxxxx 负数。
3、GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节第一个字节是负数,第二个字节可能是正数
GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中的一部分文字,第一个字节开头是1,第二字节开头是0
GB18030:最新的中文码表,目前还没有正式使用。
4、unicode:国际标准码表:无论是什么文字,都用两个字节存储。
Java中的char类型用的就是这个码表。char c = 'a';占两个字节。
Java中的字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。
5、UTF-8:基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息
6、能识别中文的码表:GBK、UTF-8;正因为识别中文码表不唯一,涉及编码解码
常见的编码 GBK UTF-8 ISO-8859-1
文字--->(数字) :编码。 “abc”.getBytes() byte[]
(数字)--->文字 : 解码。 byte[] b={97,98,99} new String(b)

07 字符输出流写文本FileWriter类

java.lang.Object
— java.io.Writer
— java.io.OutputStreamWriter
— java.io.FileWriter

字符输出流写数据时,必须进行刷新flush()

a: 方法介绍

*  void write(int c)写入单个字符
     
* void write(String str)  写入字符串

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

b:案例

        public class WriterDemo {
            public static void main(String[] args) throws IOException{
                FileWriter fw = new FileWriter("c:\\1.txt");
                
                //写1个字符
                fw.write(100);
                fw.flush();
                
                //写1个字符数组
                char[] c = {'a','b','c','d','e'};
                fw.write(c);
                fw.flush();
                
                //写字符数组一部分
                fw.write(c, 2, 2);
                fw.flush();
                
                //写如字符串
                fw.write("hello");
                fw.flush();
                
                fw.close();
            }
        }

08 字符输入流读取文本FileReader类

java.lang.Object
— java.io.Reader
— java.io.InputStreamReader
— java.io.FileReader
a: 方法介绍

*  int read() 读取单个字符

* int read(char[] cbuf) 将字符读入数组

* abstract  int read(char[] cbuf, int off, int len)  将字符读入数组的某一部分。

b:案例

        public class ReaderDemo {
            public static void main(String[] args) throws IOException{
                FileReader fr = new FileReader("c:\\1.txt");
                /*int len = 0 ;
                while((len = fr.read())!=-1){
                    System.out.print((char)len);
                }*/
                char[] ch = new char[1024];
                int len = 0 ;
                while((len = fr.read(ch))!=-1){
                    System.out.print(new String(ch,0,len));
                }
                
                fr.close();
            }
        }

c:flush方法和close方法区别
flush()方法
用来刷新缓冲区的,刷新后可以再次写出,只有字符流才需要刷新
close()方法
用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出

09字符流复制文本

  • 字符流复制文本文件,必须文本文件

  • 字符流查询本机默认的编码表,简体中文GBK

  • FileReader读取数据源

  • FileWriter写入到数据目的

        public class Copy_2 {
            public static void main(String[] args) {
                FileReader fr = null;
                FileWriter fw = null;
                try{
                    fr = new FileReader("c:\\1.txt");
                    fw = new FileWriter("d:\\1.txt");
                    char[] cbuf = new char[1024];
                    int len = 0 ;
                    while(( len = fr.read(cbuf))!=-1){
                        fw.write(cbuf, 0, len);
                        fw.flush();
                    }
                    
                }catch(IOException ex){
                    System.out.println(ex);
                    throw new RuntimeException("复制失败");
                }finally{
                    try{
                        if(fw!=null)
                            fw.close();
                    }catch(IOException ex){
                        throw new RuntimeException("释放资源失败");
                    }finally{
                        try{
                            if(fr!=null)
                                fr.close();
                        }catch(IOException ex){
                            throw new RuntimeException("释放资源失败");
                        }
                    }
                }
            }
        }
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容