Java基础知识——输入与输出

Java的流其实总的可以划分为两种:字符流和字节流,如下图

简介:本文基于Java核心技术卷二,进行整理和总结对Java的部分流库

  1. 输入 / 输出流(I/O流) ——主要针对一些特别大的文件或二进制文件
  2. 操作文件                       ——主要针对一些长度中小的文件

1. 输入 / 输出流——面向字节流

输入流:可以从其中读入一个字节序列的对象称为输入流

输出流:可以向其中写入一个字节序列的对象称为输出流

而注意这些字节序列的来源地和目的地可以是文件(一般都是文件),网络连接,内存块等;

抽象类 InputStream 和 OutputStream 构成了输入/输出(I/O)类层次结构的基础

  • 为什么首先强调InputStream 和 OutputStream?

就在于InputStream 和 OutputStream 是之后介绍的比如FileInputStream、FilterInputStream 等其他API的 父类一张图来解释,OutputStream与下面几乎一致

 

 

 

1.1— InputStream具体介绍(OutputStream拥有前四个和一个void flush()(用于冲刷输出流,即将所有缓冲的数据发送到目的地))

java.io.InputStream

函数

介绍

abstract void read()

从数据中读入一个字节,并返回该字节,但碰到文件结尾的时候返回-1,

注意此方法是一个抽象方法,即他的子类继承InputStream时都会重写这个方法

int read (byte[]  b)

将数据写入b这个byte数组,并返回实际读入的字节数,遇到文件结尾返回-1

这个方法最多读入b.length个字节

int read (byte[]  b,int off , int len)

同上,参数off : 将读入的第一个数据放入b[off] 中,即off是一个偏移量

           参数len : 读入字节的最大数量

void close  ()

关闭输入流

long skip (long n )                  

在输入流中跳过n个字节,并返回实际跳过的字节数,遇到文件结尾,

返回结果可能小于n

void mark (int readlimit)

在输入流当前位置打一个标记

void reset ( )

返回到最后一个标记,在调用read会重新读入标记之后的字节

boolean markSupported()

如果这个流支持打标记,则返回true

  • 可以看出,InputStream 和 OutputStream类只能支持对字节或者字节数组的读写,但我们在编程中一般用字符串和数字,它的子类DataInputStream 和 DateOutputStream就可以实现以二进制格式读写几乎所有基本Java类型!

注意:这里InputStream 和 OutputStream包括其子类主要面向字节流,不支持Unicode形式存储的信息,所以从抽象类reader 和 writer继承出一些子类来处理。何为Unicode可以自行百度

1.2—组合输入/输出流过滤器

FileInputStream 和 FileOutputStream类(见上图中的部分流家族)可以提供一个附着在磁盘文件上的输入流和输出流,如下代码

FileInputStream  fin = new FileInputStream("data.txt");

与他们的父类—抽象类InputStream 和 OutputStream类一样,这些类只支持在字节级别上的读写,也就是说,我们只能从上述代码中  fin对象中读入字节或字节数组,前面强调了,输入输出流是面向字节的嘛

  • 问题来了,既然这些类是面向字节流的,而且之前说过DataInputStream可以实现以二进制格式读写几乎所有基本Java类型,但他们都没有任何直接的方法可以实现直接读写啊,怎么办?正如本节题目:组合输入/输出过滤器——Java就提供了这样一种灵巧的机制分离这两种职责                         ——读写字节 和 读写数据,如下代码

FileInputStream fin = new FileInputStream("data.txt");
DataInputStream din = new DataInputStream(fin);
din.read_double();
//read你想要的基本数据类型!
  • 具体什么意思呢?就是我得先将文件中的数据以字节流的形式存放到一个输入流对象fin中,然后我再利用他的子类DataInputStream中的一些方法 将该输入流转换组装成我们常用的数据类型!nice!

注意:

  1. 这里我们可以自由嵌套过滤器来实现多重功能,比如输入流在默认情况下是不支持缓冲区缓存的,也就是每次read调用都会向操作系统进行请求调用,看起来比较繁琐,因此我们找来了部分流家族中的BufferedInputStream这个类,可以实现请求一个数据块放在缓冲区,等读满了,我在一次性的进行写入或读出,效率比较高,代码如下
    DataInputStream din = new DataInputStream(
    				new BufferedInputStream(
    						new FileInputStream("data.txt")));
    din.readDouble();
    //read你想要的基本数据类型!
  2. 还有就是当有多个输入流嵌套组合的时候,有时候你想预览下一个字节是否是你想要的值,Java就提供了这样一个子类PushbackInputStream,可以预读下一个字节,并且如果不想要可以直接推回流中,以下代码便实现了既可以回推输入流,又可以读入数字的组合过滤器
     

2.读写文件

Files类可以使得普通文件操作变得十分快捷。例下面的方式可以很容易的读取一个文件的所有内容

byte[] bytes = Files.readAllBytes(path);

如果想将文件以字符串的形式读入,可以在执行完上述语句之后调用下列语句

String s = new String(bytes, charset);

如果想将文件以行序列读入,可以调用

List<String> l = Files.readAllLines(path,charset);

如果想将字符串写入文件中,可以调用

Files.write(path, l.getBytes(charset));
//charset一般为utf-8
Files.write(path, l.getBytes(charset),StandardOpenOption.APPEND);
//最后一个参数是以追加的形式

但是注意,这些方法在操作比较短小的文件的时候效率比较高,一旦操作大的文件或者二进制文件,就需要使用之前介绍的输入输出流或者读入写出器来进行:

InputStream is = Files.newInputStream(path);
OutputStream os = Files.newOutputStream(path);
Reader in = Files.newBufferedReader(path, charset);
Writer in = Files.newBufferedWriter(path, charset);

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值