输入输出

1. Java中的“流”

在大多数程序中,都需要对输入输出进行处理。例如我们在前面各个章节中需要获取用户从键盘上的输入,需要在控制台输出结果等等。除此之外还有从文件中读取数据,向文件中写入数据等等。在Java中,我们把这些不同类型的输入输出源抽象地称为流,也就是Stream;在里面输入输出的数据则称为数据流(Data Stream),它们通常具有统一的接口。

于是我们得到了数据流的定义:

一个Java I/O对象叫做数据流。读取数据到内存的对象叫做输入流,内存写出数据的对象叫做输出流。

可以大致将流分为下面几种类型:

  1. 按照数据流的方向不同分为输入流和输出流。这种分类不是绝对的,例如在向一个文件写入数据时,它就是输出流;而在读取数据时,它就是输入流。
  2. 按照处理数据的单位不同分为字节流和字符流。
  3. 按照功能的不同分为节点流和处理流。

需要特别说明,节点流是从特定的数据节点(文件、数据库、内存等)读写数据;处理流是连接在已有的流上,通过对数据的处理为程序提供更多功能。

在Java环境中,java.io包提供了大多数的类和接口来实现输入输出管理。一些标准的输入输出则来自java.lang包中的类,但它们都是继承自java.io中的类。我们可以将输入流理解为数据的提供者,而把输出流理解为数据的接收者。在最初的时候,这些派生自抽象类InputStream和OutputStream的输入输出类是面向8位的字节流的。但为了支持国际化,又引入了派生自抽象类Reader和Writer的类层次,用于读写一些双字节的Unicode字符。

因此,在学习java的输入输出上,我们希望你以字节流和字符流作为区分来学习。

字节流和字符流:

字节流:表示以字节为单位从stream中读取或往stream中写入信息。通常用来读取二进制数据。 
字符流:以Unicode字符为单位从stream中读取或往stream中写入信息。

java中流的层次结构如下: 
这里写图片描述
字节流与字符流的区别 
这里写图片描述

实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件。

2. 读写一个文件

2.1 使用FileInputStream读取文件

首先在桌面上新建一个txt文件,命名为Test。在Test文件中输入内容a,然后保存并关闭。

字节流中读取文件的方式主要有两种方法:**

int read(),从此输入流中读取一个数据字节。返回:下一个数据字节。如果已到达文件末尾,则返回 -1。 
int read(byte[] b),从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。返回:读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。

创建包含main()方法的类ReadFileTest,代码如下:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ReadFileTest {
    public static void main(String[] args){
        try{
            FileInputStream file = new FileInputStream("C:/Users/Administrator/Desktop/Test.txt");

            int data = 0;
            while((data = file.read())!=-1){
                System.out.println(data);
            }
            file.close();
        }catch(FileNotFoundException e){
            e.printStackTrace();
        }catch(IOException e){
            e.printStackTrace();
        }
    }

}
97

上述代码运行结果为97,因为a的ASCLL码值刚好为97.

2.2 读取文件的其他方式

如果你想使用BufferedInputStream来读取文件,在创建对象时使用下面的格式即可:

BufferedInputStream file = new BufferedInputStream(new FileInputStream("文件的路径"));

同时import java.io.BufferedInputStream;。

上述方法都是对于字节流的,那么对于字符流呢?

查阅API文档可以知道,字节流使用的数组是字节数组byte[] bt,而字符流使用的数组是字符数组char[] chs。

将上个程序的try语句块中的程序改为下面这些,使用字符流的方式来读取文件。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.FileReader;

public class ReadFileTest {
    public static void main(String[] args){
        try{

            FileReader file = new FileReader("C:/Users/Administrator/Desktop/Test.txt");
            //声明一个文件输入流file,并指明该文件在系统中的路径以方便定位

            int data = 0;
            //声明一个整型变量用于存放读取的数据

            while((data=file.read())!=-1){
                //在while循环中使用read()方法持续读取file,数据赋到data中
                //如果读取失败或者结束,则将返回-1,这个特殊的返回值可以作为读取结束的标识

                System.out.print((char)data);
                //输出读取到数据
            }

            file.close();
            //一定要记得读取结束后要关闭文件

        }catch(FileNotFoundException e){
            e.printStackTrace();
        }catch(IOException e){
            e.printStackTrace();
        }
    }

}

上述运行结果为a,这是因为我们在输出前进行了强制类型转换。

2.3 使用FileOutputStream写入文件

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class WriteFileTest {

    public static void main(String[] args) {
        try {

            String path = "C:/Users/Administrator/Desktop/newfile.txt";
            //这一次我们提前声明一个字符串用于存放待写入文件的路径

            String content = "i love you";
            //声明一个字符串存放待写入的内容

            FileOutputStream file = new FileOutputStream(path);
            //声明一个文件输出流对象,并指定路径

            file.write(content.getBytes());    
            //通过write()方法将数据写入到文件中
            //getBytes()方法是将字符串转化为二进制序列

            file.close();
            //记得关闭文件

            System.out.println("File created successfully.");
            //提示用户创建成功

        } catch (FileNotFoundException e) {

            e.printStackTrace();
        } catch (IOException e) {

            e.printStackTrace();
        }
    }
}

将会在桌面上看到一个新建的文本文档。


原文地址:https://www.cnblogs.com/gaoss/p/6636426.html