[Java IO]02_字节流

简介:

概要

字节流有两个核心抽象类:InputStream 和 OutputStream。所有的字节流类都继承自这两个抽象类。

InputStream 负责输入,OutputStream 负责输出。

字节流主要操作byte类型数据。

以下为 JDK8 版本中字节流的族谱图:

具体详情可查看Java API文档。 

由上图可以看出,InputStream 和 OutputStream对于数据源的操作往往是成对出现的。 

 

InputStream

InputStream的作用是用来表示哪些从不同数据源产生输入的类。 

InputStream类型表

功能 构造器
ByteArrayInputStream 允许将内存的缓冲区当做InputStream使用 缓冲区,字节将从中取出
StringBufferInputStream 将String转换成InputStream 字符串。底层实现实际使用StringBuffer
FileInputStream 从文件中读取信息 字符串,表示文件名、文件或FileDescriptor对象
PipedInputStream 产生用于写入相关PipedOutputStream的数据。实现“管道化”概念 PipedOutputStream
SequenceInputStream 将多个InputStream对象合并为一个InputStream 两个InputStream对象或一个容纳InputStream对象的容器Enumeration
FilterInputStream 抽象类,作为“装饰器”的接口。其中“装饰器”为其他InputStream类提供有用功能


OutputStream

OutputStream决定了数据的输出形式。

OutputStream类型表

功能 构造器
ByteArrayOutputStream 允许将内存的缓冲区当做InputStream使用 缓冲区初始化尺寸(可选的)
FileOutputStream 从文件中读取信息 字符串,表示文件名、文件或FileDescriptor对象
PipedOutputStream 产生用于写入相关PipedOutputStream的数据。实现“管道化”概念 PipedInputStream
FilterOutputStream 抽象类,作为“装饰器”的接口。其中“装饰器”为其他OutputStream类提供有用功能


文件字节流

文件字节流有两个类:FileOutputStream 和 FileInputStream。

它们提供了方法将字节写入到文件和将数据以字节形式从文件中读取出来。

一般情形下,文件字节流操作遵循以下几个步骤:

(1)使用File类绑定一个文件。

(2)把File对象绑定到流对象上。

(3)进行读、写操作。 

(4)关闭输入、输出。

 

FileOutputStream


向文件写入数据

复制代码
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public  class FileOutputStreamDemo {
     public  static  void write1(OutputStream out,  byte[] b)  throws IOException {
        out.write(b);  //  将内容输出,保存文件
    }

     public  static  void write2(OutputStream out,  byte[] b)  throws IOException {
         for ( int i = 0; i < b.length; i++) {  //  采用循环方式写入
            out.write(b[i]);  //  每次只写入一个内容
        }
    }

     public  static  void main(String args[])  throws Exception {
         //  第1步、使用File类找到一个文件
        File f =  new File("d:" + File.separator + "test.txt");  //  声明File对象

        
//  第2步、通过子类实例化父类对象
        OutputStream out =  new FileOutputStream(f);  //  通过对象多态性,进行实例化
        
//  实例化时,默认为覆盖原文件内容方式;如果添加true参数,则变为对原文件追加内容的方式。
        
//  OutputStream out = new FileOutputStream(f, true);

        
//  第3步、进行写操作
        String str = "Hello World\r\n";  //  准备一个字符串
         byte b[] = str.getBytes();  //  只能输出byte数组,所以将字符串变为byte数组
        write1(out, b);
         //  write2(out, b);

        
//  第4步、关闭输出流
        out.close();
    }
};
复制代码

 

FileInputStream


从文件中读取数据 

复制代码
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public  class FileInputStreamDemo {
     public  static  void read1(InputStream input,  byte[] b)  throws IOException {
         int len = input.read(b);  //  读取内容
        System.out.println("读入数据的长度:" + len);
    }

     public  static  void read2(InputStream input,  byte[] b)  throws IOException {
         for ( int i = 0; i < b.length; i++) {
            b[i] = ( byte) input.read();  //  读取内容
        }
    }

     public  static  void read3(InputStream input,  byte[] b)  throws IOException {
         int len = 0;
         int temp = 0;  //  接收每一个读取进来的数据
         while ((temp = input.read()) != -1) {
             //  表示还有内容,文件没有读完
            b[len] = ( byte) temp;
            len++;
        }
    }

     public  static  void main(String args[])  throws Exception {  //  异常抛出,不处理
        
//  第1步、使用File类找到一个文件
        File f =  new File("d:" + File.separator + "test.txt");  //  声明File对象

        
//  第2步、通过子类实例化父类对象
        InputStream input =  new FileInputStream(f);  //  准备好一个输入的对象

        
//  第3步、进行读操作
        
//  有三种读取方式,体会其差异
         byte[] b =  new  byte[( int) f.length()];
        read1(input, b);
         //  read2(input, b);
        
//  read3(input, b);

        
//  第4步、关闭输入流
        input.close();
        System.out.println("内容为:\n" +  new String(b));  //  把byte数组变为字符串输出
    }
};
复制代码

 

内存操作流

ByteArrayInputStream 和 ByteArrayOutputStream是用来完成内存的输入和输出功能。

内存操作流一般在生成一些临时信息时才使用。 
如果临时信息保存在文件中,还需要在有效期过后删除文件,这样比较麻烦。


使用内存操作流完成一个转换为小写字母的程序 

复制代码
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public  class ByteArrayDemo {
     public  static  void main(String args[]) {
        String str = "HELLOWORLD";
        
        ByteArrayInputStream bis =  new ByteArrayInputStream(str.getBytes());  //  内存输入流
        ByteArrayOutputStream bos =  new ByteArrayOutputStream();  //  内存输出流
        
        
//  用ByteArrayInputStream读取字符串内容,
        
//  全转为小写后,写入ByteArrayOutputStream
         int temp = 0;
         while((temp = bis.read()) != -1) {
             char c = ( char) temp;  //  读取的数字变为字符
            bos.write(Character.toLowerCase(c));  //  将字符变为小写
        }
        
         //  所有的数据就全部都在ByteArrayOutputStream中
        String newStr = bos.toString();     //  取出内容
         try {
            bis.close();
            bos.close();
        }  catch(IOException e) {
            e.printStackTrace();
        }
        System.out.println(newStr);
    }
};
复制代码


管道流

管道流的主要作用是可以进行两个线程间的通信。

如果要进行管道通信,则必须把PipedOutputStream连接在PipedInputStream上。

为此,PipedOutputStream中提供了connect()方法。

复制代码
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

class Send  implements Runnable {
     private PipedOutputStream pos =  null//  管道输出流

     public Send() {
         this.pos =  new PipedOutputStream();  //  实例化输出流
    }

     public  void run() {
        String str = "Hello World!!!";  //  要输出的内容
         try {
             this.pos.write(str.getBytes());
        }  catch (IOException e) {
            e.printStackTrace();
        }
         try {
             this.pos.close();
        }  catch (IOException e) {
            e.printStackTrace();
        }
    }

     public PipedOutputStream getPos() {  //  得到此线程的管道输出流
         return  this.pos;
    }
};

class Receive  implements Runnable {
     private PipedInputStream pis =  null//  管道输入流

     public Receive() {
         this.pis =  new PipedInputStream();  //  实例化输入流
    }

     public  void run() {
         byte b[] =  new  byte[1024];  //  接收内容
         int len = 0;
         try {
            len =  this.pis.read(b);  //  读取内容
        }  catch (IOException e) {
            e.printStackTrace();
        }
         try {
             this.pis.close();  //  关闭
        }  catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("接收的内容为:" +  new String(b, 0, len));
    }

     public PipedInputStream getPis() {
         return  this.pis;
    }
};

public  class PipedDemo {
     public  static  void main(String args[]) {
        Send s =  new Send();
        Receive r =  new Receive();
         try {
            s.getPos().connect(r.getPis());  //  连接管道
        }  catch (IOException e) {
            e.printStackTrace();
        }
         new Thread(s).start();  //  启动线程
         new Thread(r).start();  //  启动线程
    }
};
复制代码


数据操作流

 

数据操作流提供了格式化读入和输出数据的方法,分别为DataInputStream 和 DataOutputStream。

 

DataOutputStream

将格式化的订单数据写入到文件

 

复制代码
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public  class DataOutputStreamDemo {
     public  static  void main(String args[])  throws IOException {
         //  第1步、使用File类找到一个文件
        File f =  new File("d:" + File.separator + "order.txt");
        
         //  第2步、通过子类实例化父类对象
        DataOutputStream dos =  new DataOutputStream( new FileOutputStream(f));  //  实例化数据输出流对象

        
//  第3步、进行写操作
        String names[] = { "衬衣", "手套", "围巾" };  //  商品名称
         float prices[] = { 98.3f, 30.3f, 50.5f };  //  商品价格
         int nums[] = { 3, 2, 1 };  //  商品数量
        
//  循环输出
         for ( int i = 0; i < names.length; i++) {
            dos.writeChars(names[i]);
            dos.writeChar('\t');
            dos.writeFloat(prices[i]);
            dos.writeChar('\t');
            dos.writeInt(nums[i]);
            dos.writeChar('\n');
        }

         //  第4步、关闭输出流
        dos.close();
    }
};
复制代码

 

DataInputStream

将订单文件中的格式化数据读取出来

复制代码
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;


public  class DataInputStreamDemo {
     public  static  void main(String args[])  throws IOException {  //  所有异常抛出
        
//  第1步、使用File类找到一个文件
        File f =  new File("d:" + File.separator + "order.txt");

         //  第2步、通过子类实例化父类对象
        DataInputStream dis =  new DataInputStream( new FileInputStream(f));  //  实例化数据输入流对象
        
        
//  第3步、进行读操作
        String name =  null//  接收名称
         float price = 0.0f;  //  接收价格
         int num = 0;  //  接收数量
         char temp[] =  null//  接收商品名称
         int len = 0;  //  保存读取数据的个数
         char c = 0;  //  '\u0000'
         try {
             while ( true) {
                temp =  new  char[200];  //  开辟空间
                len = 0;
                 while ((c = dis.readChar()) != '\t') {  //  接收内容
                    temp[len] = c;
                    len++;  //  读取长度加1
                }
                name =  new String(temp, 0, len);  //  将字符数组变为String
                price = dis.readFloat();  //  读取价格
                dis.readChar();  //  读取\t
                num = dis.readInt();  //  读取int
                dis.readChar();  //  读取\n
                System.out.printf("名称:%s;价格:%5.2f;数量:%d\n", name, price, num);
            }
        }  catch (Exception e) {
        }
        
         //  第4步、关闭输入流
        dis.close();
    }
};
复制代码

 

合并流

合并流的主要功能是将多个InputStream合并为一个InputStream流。

合并流的功能由SequenceInputStream完成。

需要稍微留意的是,由前面的字节流族谱图,可以得知并没有对应的OutputStream。

将两个文件内容合并为一个文件

复制代码
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.SequenceInputStream;

public  class SequenceDemo {
     public  static  void main(String args[])  throws IOException {
         //  第1步,绑定要操作的文件
        InputStream is1 =  new FileInputStream("d:" + File.separator + "a.txt");  //  输入流1
        InputStream is2 =  new FileInputStream("d:" + File.separator + "b.txt");  //  输入流2    
        OutputStream os =  new FileOutputStream("d:" + File.separator + "ab.txt");  //  输出流
        
        
//  第2步,绑定要合并的InputStream对象到SequenceInputStream
        SequenceInputStream sis =  new SequenceInputStream(is1, is2);  //  实例化合并流

        
//  读取两个InputStream流的数据,然后合并输出到OutputStream
         int temp = 0;  //  接收内容
         while ((temp = sis.read()) != -1) {  //  循环输出
            os.write(temp);  //  保存内容
        }
        
         //  第4步,关闭相关流
        sis.close();
        os.close();    
        is1.close();
        is2.close();
    }
};
复制代码

 本文转自静默虚空博客园博客,原文链接:http://www.cnblogs.com/jingmoxukong/p/4513964.html,如需转载请自行联系原作者

目录
打赏
0
0
0
0
51
分享
相关文章
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
77 23
JAVA网络IO之NIO/BIO
本文介绍了Java网络编程的基础与历史演进,重点阐述了IO和Socket的概念。Java的IO分为设备和接口两部分,通过流、字节、字符等方式实现与外部的交互。
|
5月前
|
java 中 IO 流
Java中的IO流是用于处理输入输出操作的机制,主要包括字节流和字符流两大类。字节流以8位字节为单位处理数据,如FileInputStream和FileOutputStream;字符流以16位Unicode字符为单位,如FileReader和FileWriter。这些流提供了读写文件、网络传输等基本功能。
87 10
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
161 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
揭秘Java IO流:字节流与字符流的神秘面纱!
揭秘Java IO流:字节流与字符流的神秘面纱!
80 1
Java IO流全解析:字节流和字符流的区别与联系!
Java IO流全解析:字节流和字符流的区别与联系!
195 1
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
386 12
|
6月前
|
Java 中 IO 流的分类详解
【10月更文挑战第10天】不同类型的 IO 流具有不同的特点和适用场景,我们可以根据具体的需求选择合适的流来进行数据的输入和输出操作。在实际应用中,还可以通过组合使用多种流来实现更复杂的功能。
120 0
IO流:字节流
在Java编程中,IO流是一个核心概念,用于与文件、网络、内存等数据源交互。Java的IO库提供丰富的类和方法支持数据读写。IO流分为字节流和字符流,前者可操作所有类型文件,后者仅限纯文本文件。`FileOutputStream`用于向文件写入字节,支持多种写入方式,并可通过构造函数的布尔参数控制是否追加写入。`FileInputStream`则用于从文件读取字节,支持逐字节或批量读取。文件拷贝可通过结合读写操作实现,高效的方法是一次性读取并写入大容量数组。处理IO流时需注意异常管理,合理使用try-catch-finally结构确保资源正确释放。JDK7及以后版本提供了自动关闭资源的简化语法
73 10

热门文章

最新文章