欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-22 22:00:10
...

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

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

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

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

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

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

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

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

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

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

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

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

 

 

 

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);

 

 

 

 

 

 

 

相关标签: 算法 java