前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

IO流

作者头像
晚上没宵夜
发布2020-03-11 14:21:23
3480
发布2020-03-11 14:21:23
举报

1. 流

不同设备之间的数据传输就是流,可以抽象理解供水厂到家庭之间的水管,水(数据)在管道传输,就成了流

根据流向分为输出流和输入流

  • 数据从文件流向程序称为输入流
  • 数据从程序流向文件称为输出流

根据数据类型分为字节流和字符流

  • 字节流处理字节数据
  • 字符流处理字符数据

按处理数据分为节点流和处理流

  • 节点流
    • 文件流
    • 数组流
    • 管道流
  • 处理流
    • 缓冲流
    • 转换流
    • 基本数据流
    • 对象序列化流
    • 打印控制流

IO流属于阻塞操作,一般项目中应放到子线程中,避免阻塞主线程

其中几个常见流之间的继承关系如下

2. 各种流介绍

2.1 File

在了解各种流之前,先来看看File类

其静态字段有:

Modifier and Type

Field

Description

static String

pathSeparator

系统的路径分隔符

static char

pathSeparatorChar

系统的路径分隔符

static String

separator

系统的名称分隔符

static char

separatorChar

系统的名称分隔符

以windows系统为例上面的字段值为:

代码语言:javascript
复制
public static void main(String[] args) {

    System.out.println(File.pathSeparator);
    System.out.println(File.pathSeparatorChar);
    
    System.out.println(File.separator);
    System.out.println(File.separatorChar);
}
代码语言:javascript
复制
;
;
\
\

其构造函数,是对文件系统的映射,并不是硬盘上真实的文件,可以不存在,但真正被当参数应用的时候不存在就报错,所以得处理异常

Modifier and Type

Constructor

Description

File

File(String pathname)

从字符串路径参数创建文件实例

代码语言:javascript
复制
File file = new File("C:\\Users\\Howl\\Desktop\\FileInputStream.txt");

其方法

Modifier and Type

Method

Description

boolean

delete

删除文件或目录

boolean

exists

文件或目录是否存在

File

getAbsolutePath

返回此实例的绝对路径

String

getName

返回此实例的目录或文件名

long

length

此实例的长度

boolean

mkdirs

创建目录,包括父目录,不是文件

boolean

createNewFile

创建文件

File

getParentFile

返回父类目录文件类

boolean

isFile

判断是否文件

举个创建/删除目录的例子,还挺好玩的,注意目录有内容是不能被删除的,要先把里面东西删完,这里不介绍了

代码语言:javascript
复制
public static void main(String[] args) throws IOException {
    
    File file = new File("C:/Users/Howl/Desktop/test/Howl.txt");
    File dir = file.getParentFile();
    
    if(!dir.exists()){
        dir.mkdirs();
        file.createNewFile();
    }else{
        file.delete();
        dir.delete();
    }
}

2.2 字节流

能处理各类数据,比如图片视频,这种流解释为原始的二进制数据,二进制不需要编码解码,比文本效率高,可移植,缺点是人们看不懂二进制内容,当读入数据到内存时,用一个字节或字节数组来存储,写出时同理,并且无论使用什么流,底层传输的都是二进制,所以字节流是一切流的基础

2.2.1 FileInputStream和FileOutputStream

从本地文件读写字节流,先看二者构造函数,还有各自的方法

代码语言:javascript
复制
FileInputStream(File file)                      //参数为一个File类型       
FileOutputStream(File file, boolean append)     //第二个参数表示覆盖还是追加

FileInputStream

代码语言:javascript
复制
int read()                              //返回下一个字节的值,到了末尾返回-1
int read(byte[] b)                      //把字节放入数组b,返回读取的字节个数
int read(byte[] b,int off,int len)      //把字节放入数组b,后两参数代表始末位置,返回读取的字节个数
void close()                            //关闭流

FileOutputStream

代码语言:javascript
复制
void write(int b)                       //只读取低8位
void write(byte[] b)                    //和上面同理
void write(byte b,int off,int len)
void close()                            //关闭流

例子

代码语言:javascript
复制
File file = new File("C:/Users/Howl/Desktop/test/FileOutputStream.txt");
byte[] bytes = {127,10,10,20,0,13,13,20,30,10,40,127,126,15,124};   // 数据字节数组

FileOutputStream fs = new FileOutputStream(file,true);
fs.write(bytes);

FileInputStream fi = new FileInputStream(file);
fi.read(bytes);

for(byte a : bytes){
    System.out.println(a);
}

fi.close();
fs.close();

2.2.2 ObjectInputStream和ObjectOutputStream

对象的序列化和反序列化,前提是该对象实现了序列化接口Serializable

其构造方法

代码语言:javascript
复制
ObjectInputStream (InputStream in)
ObjectOutputStream (OutputStream out)   //参数类型为字节流

其方法

返回值

函数

说明

void

writeObject(Object obj)

往流中写入一个对象

Object

readObject()

从流中读取一个对象

例子

代码语言:javascript
复制
public static void main(String[] args) {
    
    //准备
    User user = new User(20,"1210911104@qq.com","Howl");
    File file = new File("C:\\Users\\Howl\\Desktop\\ObjectOutputStream.txt");
    
    //自动关闭资源
    try( FileOutputStream fos = new FileOutputStream(file);
         ObjectOutputStream obs = new ObjectOutputStream(fos);){
        
        if(!file.exists()){
            file.createNewFile();
        }
    
        //先写入对象
        obs.writeObject(user);
        System.out.println("写入成功\n");
        
        //读取对象
        FileInputStream fis = new FileInputStream(file);
        ObjectInputStream ois = new ObjectInputStream(fis);
        User user2 = (User) ois.readObject();
        System.out.println("读入成功\n" + user2.getId() + "--" + user2.getEmail() + "--" + user2.getPassword());
        
        
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

打印,桌面多了一个ObjectOutputStream.txt文件,存放序列化的对象,这些是字节流文件,所以是会乱码的

代码语言:javascript
复制
写入成功

读入成功
20--1210911104@qq.com--Howl

2.2.3 BufferedInputStream和BufferedOutStream

缓冲流主要作用是为其他流提供缓冲功能,先把数据放入缓冲流中,等程序把处理完再往缓存中放入数据

构造函数

代码语言:javascript
复制
BufferedInputStream(InputStream in)
BufferedOutputStream(OutputStream out)

方法

代码语言:javascript
复制
read()
read(byte[] b, int off, int len)
    
write(byte[] b, int off, int len)

例子(传输图片)

代码语言:javascript
复制
public static void main(String[] args) throws IOException {
    
    File file1 = new File("C:/Users/Howl/Desktop/test/1.png");
    File file2 = new File("C:/Users/Howl/Desktop/test/2.png");
    
    if(!file2.exists()){
        file2.createNewFile();
    }
    
    FileInputStream fis = new FileInputStream(file1);
    BufferedInputStream bis = new BufferedInputStream(fis);
    
    FileOutputStream fos = new FileOutputStream(file2);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    
    int num;
    byte[] bytes = new byte[1024];
    while( (num = bis.read(bytes)) != -1){
        bos.write(bytes, 0, num);
    }
    
    // 关闭各种流
}

2.2.4 DataInputStream和DataOutputStream

主要传输基本类型的数据,接收的参数是InputStream

2.2.5 PrintStream

打印流提供了非常方便的打印功能,可以打印任何的数据类型,接收的参数是OutputStream

来分析一下日常见到的System.out.println(),其中out在System类中定义 ,可以看出out属于PrintStream字节打印流

代码语言:javascript
复制
public final class System {
    
    // 省略各种定义的变量
    public final static PrintStream out = null;
}

再进去看看PrintStream类,可以发现print方法重载了一堆,这里只写几个,难怪能打印那么多类型

代码语言:javascript
复制
public void print(boolean b) {}
public void print(int i) {}
public void print(String s) {}

print和println什么区别?

代码语言:javascript
复制
public void println(int x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

public void print(String s) {
    if (s == null) {
        s = "null";
    }
    write(s);
}


private void write(String s) {
    try {
        synchronized (this) {
            ensureOpen();       // 确保流打开着
            textOut.write(s);   // textOut属于BufferedWriter
            textOut.flushBuffer();  //
            charOut.flushBuffer();  // charOut属于OutputStreamWriter
            if (autoFlush && (s.indexOf('\n') >= 0))
                out.flush();
        }
    }
    catch (InterruptedIOException x) {
        Thread.currentThread().interrupt();
    }
    catch (IOException x) {
        trouble = true;
    }
}

可以看出后者调用了前者,不过在同步中增多了一个newLine()方法来换行,而print调用write()方法,write内部又调用各种方法

2.3 字符流

只能处理字符数据

2.3.1 InputStreamReader和OutputStreamWriter

字节流转换成字符流

其构造函数,第一个参数是字节流,第二参数指定是字符集一般写utf-8

代码语言:javascript
复制
InputStreamReader(InputStream in, Charset cs)
OutputStreamWriter(OutputStream out, Charset cs)

转换流的方法和2.1.1方法很类似但区别在于参数是byte还是int或String类型

InputStreamReader

代码语言:javascript
复制
int read()
int read(char[] cbuf, int offset, int length)

OutputStreamWriter

代码语言:javascript
复制
void write(int c)
void write(char[] cbuf, int off, int len)
void write(String str, int off, int len)

例子

代码语言:javascript
复制
public static void main(String[] args) throws IOException {
        
        File file1 = new File("C:/Users/Howl/Desktop/test/1.txt");
        File file2 = new File("C:/Users/Howl/Desktop/test/2.txt");
        
        if(!file2.exists()){
            file2.createNewFile();
        }
        
        FileInputStream fis = new FileInputStream(file1);
        FileOutputStream fos = new FileOutputStream(file2,true);
        
        InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
        OutputStreamWriter osr = new OutputStreamWriter(fos,"UTF-8");
        
        int num;
        char[] arr = new char[10];
        while( (num = isr.read(arr)) != -1 ){
            osr.write(arr, 0, num);
        }
        
        osr.close();  // close里面有flush方法刷新,各种关闭
    }

2.3.2 FileReader和FileWriter

从本地文件读写字符流,和上面的主要区别是上面读取字节流,能指定编码,而这里读取的是字符流,只能使用系统默认编码

构造函数,并且方法和父类一致,这里不介绍了

代码语言:javascript
复制
FileReader(File file)
FileWriter(File file, boolean append)

2.3.3 BufferedReader和BufferedWriter

带缓冲区的流,减少访问磁盘次数,提高性能,其构造函数

代码语言:javascript
复制
BufferedReader(Reader in)       //以字符流为参数,例如FileReader
BufferedWriter(Writer out)      //以字符流为参数,例如FileWriter

BufferedReader有一个特有方法

代码语言:javascript
复制
String readLine()           //读取一行字符,返回字符串

BufferedWriter也有一个特殊方法

代码语言:javascript
复制
void newLine()              //写入行分隔符
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-12-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 流
  • 2. 各种流介绍
    • 2.1 File
      • 2.2 字节流
        • 2.2.1 FileInputStream和FileOutputStream
        • 2.2.2 ObjectInputStream和ObjectOutputStream
        • 2.2.3 BufferedInputStream和BufferedOutStream
        • 2.2.4 DataInputStream和DataOutputStream
        • 2.2.5 PrintStream
      • 2.3 字符流
        • 2.3.1 InputStreamReader和OutputStreamWriter
        • 2.3.2 FileReader和FileWriter
        • 2.3.3 BufferedReader和BufferedWriter
    相关产品与服务
    文件存储
    文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档