IO(2)----字节输出流OutputStream

本文详细探讨了Java中的字节输出流OutputStream,包括其基本概念、使用场景和常见子类,如FileOutputStream、BufferedOutputStream等。通过实例代码解析了如何进行文件输出、网络数据传输等操作,帮助读者掌握OutputStream在数据写入过程中的核心功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、输入输出的概念                                                                                                                         点击此处返回总目录

二、字节输出流OutputStream

三、FileOutputStream

四、IO中的异常处理

 

一、输入输出的概念

前面讲了如何操作文件和目录。从现在开始讲如何往文件中写数据读数据。

首先要搞明白什么叫做Input,什么叫做Output。

Input、Output是对于程序来说的。读取文件中的数据叫做输入,把数据写到文件中叫做输出。

Input   :输入  从文件(硬盘)------->程序(内存)

Output:输出  从程序(内存)------->文件(硬盘)

 

进行文件内容的操作需要通过Java中提供的两组数据流的操作类完成:

字节操作流:OutputStream、InputStream

字符操作流:Writer、Reader

 

流对象学习技巧:

       流对象都是相辅相成的:有输入必有输出,有输出必有输入;输出能输出什么,输入就能输入什么。所以学会了一个方向,另一个方向完全能够明白。

 

流对象的使用步骤:

1. 创建流的子类对象,绑定数据目的或数据源

2. 调用流对象的方法

3. close()

 

二、字节输出流OutputStream

java.io.OutputStream是抽象类,是所有字节输出流的父类。作用是从java程序写出到文件。

OutputStream每次只操作文件中的1个字节。

字节输出流可以写任意文件。

 

常用方法:

这个类的方法都是写文件的一下方法,一共也没几个。所有的子类都得具有这些方法。

1. write(int b)                                   //写入1个字节。int型可以砍掉3个字节变为byte。要写入的字节是参数b的八个低位。

                                  b的 24 个高位将被忽略。【例1】【例2】【例3】

2. write(byte[] b)                              //写入字节数组。【例4】【例5】。写入字符数组的简便方式:【例6】

3. write(byte[] b , int off , int len)      //将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。【例7】

4. close()                                         //关闭流对象,并且释放与此流相关的资源。java当中的流对象,在操作文件的时候,自己并不                                                                做,而是使用的操作系统的功能,当流用完了,系统资源必须要释放掉。如果不close(),文件

                                                        想删都删不了。

 

因为是抽象类,所以要通过子类对象来学习父类的方法。OutputStream类的常用子类有ByteArrayOutputStream(字节数组输出流,这个流可以写字节数组)、FileOutputStream(这个流用于写文件)、FilterOutputStream(跟过滤器有关系)、ObjectOutputStream(这个用来写对象)、OutputStream(其他包中的一个流,跟我们没什么关系)、PipeOutputStream(管道流)等。

 

三、FileOutputStream

 

1)构造方法

作用:绑定输出的输出目的。

1. FileOutputStream(File file)                      //参数为File类型的对象。当原先有文件时,会覆盖掉(先删除原来的,再创建新的)

2. FileOutputStream(String name)                         //参数为String类型的对象。覆盖方式。

3. FileOutputStream(File file,boolean append)            //当append为true时,会追加写,不再覆盖。【例8】

4. FileOutputStream(String name,boolean append)    //String,追加方式。

 

注:

1.当文件不存在时,构造方法会先创建文件。

2.当原先有文件时,会覆盖掉(先删除原来的,再创建新的)。

 

2)继承过来的方法:

例1:write(int b)

package cn.itcast.demo01;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) throws IOException {
        OutputStream ops = new FileOutputStream("e:\\a.txt");    //写数据的目的文件。就是指写到哪里。
        ops.write(100);  
        ops.close();
    }
}

运行结果:

       打开e:\a.txt,发现里面只有一个字母'd'。

 

分析:

      100的二进制为:00000000 00000000 00000000 01100100 ,低字节为01100100。所以在硬盘中存的是byte 100,当打开记事本,记事本是文本工具,文本工具开启的一瞬间都会去走编码表,byte 100 对应的是字符'd',所以看到的是字符'd'。

 

例2:write(int b)

package cn.itcast.demo01;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) throws IOException {
        OutputStream ops = new FileOutputStream("e:\\a.txt");    //写数据的目的文件。就是指写到哪里。
        ops.write(1124); 
        ops.close();
    }
}

运行结果:

       打开e:\a.txt,发现里面只有一个字母'd'。

 

结果分析:

      1124的二进制为:00000000 00000000 00000100 01100100 ,低字节为01100100。所以在硬盘中存的是二进制01100100,即byte 100,当打开记事本,记事本是文本工具,文本工具开启的一瞬间都会去走编码表,100对应的是字符'd',所以看到的是字符'd'。

 

 

在一个文本当中,一个汉字占两个字节,数字占1个字节。所以如果a.txt中存储了"吃",则a.txt为2个字节。如果a.txt中存储了"100",则a.txt为3个字节。

要想打开a.txt,能够看到"100",使用write()怎么存?一个write写一个字节,要想看到100,即3个字节,需要存三次。【例3】

 

例3:write(int b)

package cn.itcast.demo01;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) throws IOException {
        OutputStream ops = new FileOutputStream("e:\\a.txt");    //写数据的目的文件。就是指写到哪里。
        ops.write(49);    //低字节二进制对应十进制为49,ASCII码为'1'
        ops.write(48);    //十进制48对应ASCII码为'0'
        ops.write(48);
        ops.close();
    }
}

运行结果:

打开a.txt,能够看到"100"

 

例4:

package cn.itcast.demo02;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) throws IOException {
        OutputStream ops = new FileOutputStream("e:\\aaa.txt");
        byte[] b = {68,65,66,67};
        ops.write(b);                                   //存进去的分别是68,65,66,67,当打开TXT时,查看ASCII码表,显示DABC
        
        ops.close();
    }
}

 

例5:

package cn.itcast.demo02;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) throws IOException {
        OutputStream ops = new FileOutputStream("e:\\aaa.txt");
        byte[] b = {-68,-65,-66,-67};
        ops.write(b);    
        
        ops.close();
    }
}

运行结果:

打开aaa.txt,能够看到"伎窘"

 

分析:负数代表汉字,两个字节表示一个汉字。所以显示两个汉字。

 

例6:写入字符数组的简便方式。

package cn.itcast.demo02;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) throws IOException {
        OutputStream ops = new FileOutputStream("e:\\aaa.txt");
        ops.write("helloworld".getBytes());    
        
        ops.close();
    }
}

运行结果:

打开aaa.txt,能够看到"helloworld"。

 

 

例7:

package cn.itcast.demo02;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) throws IOException {
        OutputStream ops = new FileOutputStream("e:\\aaa.txt");
        byte[] b = {65,66,67,68};
        ops.write(b,1,2);                                                                 //从1开始,写两个。
        
        ops.close();
    }
}

运行结果:

打开aaa.txt,能够看到"BC"

 

例8:追加方式

package cn.itcast.demo02;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) throws IOException {
        OutputStream ops = new FileOutputStream("e:\\aaa.txt",true);     //追加方式
        ops.write("helloworld".getBytes());    
        
        ops.close();
    }
}

运行结果:

假设执行之前aaa.txt中有内容"aa",则执行之后内容为"aahelloworld"。

 

例9:怎么写入换行。通过"\r\n"来换行,可以写在上一行的后面,也可以写在下一行的前面。

package cn.itcast.demo02;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) throws IOException {
        OutputStream ops = new FileOutputStream("e:\\aaa.txt",true);
        ops.write("nihao\r\n".getBytes());                   //写完之后换行
        ops.write("lijing".getBytes());
        ops.write("\r\nbuhao".getBytes());                 //换行之后再写
        
        ops.close();
    }
}

运行结果:

nihao
lijing
buhao

 

 

四、IO中的异常处理

IO流中遇到异常,需要使用try catch finally语句处理掉。

 

1.标准写法

package cn.itcast.demo03;

 

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) {
        OutputStream ops = null;
        try{
            ops = new FileOutputStream("e:\\abc.txt");
            ops.write(76);
        }catch(IOException e){
            e.printStackTrace();
            throw new RuntimeException("文件写入失败,请重试");
        }finally{
            try{
                if (ops !=null)
                    ops.close();
            }catch(IOException e){
                e.printStackTrace();
                throw new RuntimeException("文件关闭失败");
            }
        }
    }
}

 

2.为什么这么写 

 

首先:写语句。

package cn.itcast.demo03;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) {
        OutputStream ops = new FileOutputStream("e:\\abc.txt");
        ops.write(76);
        ops.close();
    }
}

结果红色部分报错,因为没有进行异常处理。

 

改进:

package cn.itcast.demo03;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) {
        try{
            OutputStream ops = new FileOutputStream("e:\\abc.txt");            //第一句
            ops.write(76);                                                                               //第二句
            ops.close();                                                                                  //第三句
        }catch(IOException e){
            e.printStackTrace();
        }
    }
}

虽然上面的程序不报错,但是有问题。当执行了第二句出现异常之后,就不会执行第三句,结果资源就不能释放了。可以使用finally语句释放资源。

 

继续改进:

package cn.itcast.demo03;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) {
        try{
            OutputStream ops = new FileOutputStream("e:\\abc.txt");
            ops.write(76);
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            ops.close();                                                                           //这句报错。找不到ops变量。
        }
    }
}

虽然将ops.close()放到了finally进行处理,但是程序报错了。因为变量ops的生命周期在try的大括号内。所以应当在try外声明变量,在try内建立对象。这样就可以扩大变量的作用域了。

 

继续改进:

package cn.itcast.demo03;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) {
        OutputStream ops = null;
        try{
            ops = new FileOutputStream("e:\\abc.txt");
            ops.write(76);
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            ops.close();                                                              //这句报错。
        }
    }
}

放到外面之后又报错了。close()方法抛异常。释放资源有可能也出错,但是程序没有处理。所以应当增加对close()的异常处理。

 

继续改进:

package cn.itcast.demo03;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) {
        OutputStream ops = null;
        try{
            ops = new FileOutputStream("e:\\abc.txt");
            ops.write(76);
        }catch(IOException e){                                                  //第一个catch。
            e.printStackTrace();
        }finally{
            try{
                ops.close();
            }catch(IOException e){                                              //第二个catch
                 e.printStackTrace();
            }
        }
    }
}

 

到这里就大致写完了,但是还有一些细节需要处理。

第一个细节就是catch怎么处理?

首先要打印出异常信息,这个不用多说。

但是这样就够了么?比如,正在往一个U盘上写东西,突然U盘被拔掉了。这种情况下再怎么用catch处理都不行,程序根本处理不了,后面再继续做也没有什么意义了。所以这里应当抛出一个RuntimeException,让程序停下来。

第二个catch,当close()的时候发生问题,比如系统占着资源呢。这时候也没办法,还是要把系统停下来。

 

 

继续改进:

package cn.itcast.demo03;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) {
        OutputStream ops = null;
        try{
            ops = new FileOutputStream("e:\\abc.txt");                                   //第一句
            ops.write(76);
        }catch(IOException e){
            e.printStackTrace();
            throw new RuntimeException("文件写入失败,请重试");
        }finally{
            try{
                ops.close();                                                                               //第二句
            }catch(IOException e){
                e.printStackTrace();
                throw new RuntimeException("文件关闭失败");
            }
        }
    }
}

 

第二个细节就是,如果流对象建立失败了,还需要关闭资源么?第一句都没有成功,new 对象失败了,也就是没有占用系统资源。但是最后还是执行第二句,这样就多此一举。所以应该加一个判断。

 

继续改进:

package cn.itcast.demo03;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test {
    public static void main(String[] args) {
        OutputStream ops = null;
        try{
            ops = new FileOutputStream("e:\\abc.txt");
            ops.write(76);
        }catch(IOException e){
            e.printStackTrace();
            throw new RuntimeException("文件写入失败,请重试");
        }finally{
            try{
                if (ops !=null)
                    ops.close();
            }catch(IOException e){
                e.printStackTrace();
                throw new RuntimeException("文件关闭失败");
            }
        }
    }
}

以上就是最终版了。代码量比较大~~~~

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值