Java(9-1)输入与输出(一)

我们将会介绍如何在JAVA中进行输入和输出操作。

part 1 大体介绍输入输出流
在JavaAPI中,可以从其中读入一个字节序列的对象称作输入流,而可以向其中写入一个字节序列的对象称为输出流。这些字节序列的来源和目的地可以是文件,也可以是网络连接,甚至内存块。**抽象类!**InputStream 和 OutputStream 构成了输入和输出各类层次的基础。

part 2.1 读写字节虚类的介绍
在InputStream中有许多很有用的抽象方法,其中有一些可能会在子类中重写,例如:
read()方法。这个方法将读入一个字节,并返回读入的字节,或者在遇到输入源结尾时返回-1。在我们具体的输入流类中,他往往被重写以提供适用的功能。

与之类似OutputStream类中也定义了类似的方法——abstract void write(int b)

read和write方法在执行时都将阻塞,直至字节确实被读入或写出。

available方法可以让我们去检查当前可读入的字节数量,那我们就可以通过这个方法来避免,read和write没有可读信息的阻塞:

int by = in.available();
if(by > 0)
{
    byte[] data = new byte[byteAvailable];
    in.read(data);
}

当我们完成了对输入/输出流的读写时,应该通过他们的close方法来关闭它,这可以及时释放我们有限的系统资源。
我们可以使用众多继承InputStream和OutputStream的类,而不是直接使用字节

Tip:我们的读写都是按照一个字节进行的,但是Unicode编码有两个字节,所以我们对Unicode文本建立了Reader和Writer的抽象类,基本方法与InputStream和OutputStream类似。

part 2.2 输入/输出流过滤器的组合

FileInputStream和FileOutputStream可以提供磁盘上文件的输入流和输出流,而你只需要提供文件民或者文件的完整路径即可。但是注意,他们是抽象类InputStream和OutputStream类一样,是基于一个字节操作的。

FileInputStream fin = new FileInputStream("emplotee.dat");

上面那行代码可以查看用户目录下的名为employee.dat的文件。(我们当然可以绝对路径)

我们以后会看到,DataInputStram,只能读入数值类型。

而FileInpuStream没有任何读入数值类型的方法,DataInputStream也没有任何从文件中获取数据的方法。

在Java中,我们使用一种机制来融合分离这两种职责,简单说,这过程感觉像是过滤一样,我们可以这样:

FileInputStram fin = new FileInputStream("emplotee.dat");
DataInputStream din = new DataInputStream(fin);
double x = din.readDouble();

我们可以通过嵌套过滤器来添加多重功能过滤来获得数据。例如,输入流在默认情况下是不被缓冲区缓存的,相比之下,请求一个数据块并将其置于缓冲区会显得更加高效。如果我们想使用缓冲机制,以及用于文件的数据输入方法,那么就需要使用下面这种构造序列:

DataInputStream din = new DataInputStream(
    new BufferedInputStream(
        new FileInputStream("employee.dat")));

part 2.3 如何写出文本输出
对于文本输出,我们用PrintWriter。这个类拥有以文本格式打印字符串和数字的方法,它还有一个将PrinterWriter链接到FileWriter的便捷方法:

PrintWriter out = new PrintWriter("employee.txt","UTF-8");

等同于:

PrintWriter out = new PrintWriter(new FileOutputStream("employee.txt"),"UTF-8");

为了打印写出器,需要使用System.out的print, println, printf方法,例如:

//上面有outout.print();

part 2.4 如何读入文本输入

最简单的处理任意文本的方式就是我们常见的Scanner类。
我们可以将短小的文本文件,像这样读入到这样的一个字符串:

String content = new String(Files.readALLbYTES(path),charset);

如果我们想将这个文件一行行地读入,那我们可以这样:

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

如果文件太大,那么可以将行惰性处理为一个Stream< String >对象:

try(Stream< String >lines = Files.lines(path, charset))
{
    ...
}

part 2.3 以文本格式存储对象

package TextFileTest;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Scanner;

public class TextTest {
    public static void main(String[] args) throws IOException {
        Employee[] staff = new Employee[3];
        // 创建数组内容
        staff[0] = new Employee("黄一东",10000);
        staff[1] = new Employee("黄玮东",20000);
        staff[2] = new Employee("黄玮琛",30000);

        // 写出通过写出类来 写出staff的内容 。 这里的PrintWriter自己内部会实现FileOutputStream
        try(PrintWriter out = new PrintWriter("Employee.dat","UTF-8"))
        {
            // 调用WriteData 先向文本写入数组的大小,再根据数组大小分别调用WriteEmpolyee
            // 按照格式写入各个数据
            writeData(staff, out);
        } 

        // 通过读入类 Scanner来读入employee.dat(UTF-8)的内容  这里显式的调用了
        // FileInputStream类 组合了流类 
        try(Scanner in = new Scanner(new FileInputStream("employee.dat"),"UTF-8"))
        {
            // 这里调用readData(文件读入流对象) 先获取文件第一行保存的对象行数(n),然后再跳到下一行
            // 调用readEmployee每次读取一行内容 循环n次 每次保存内容到数组newStaff中
            Employee[] newStaff = readData(in);

            for(Employee e:newStaff)
                System.out.println(e);
        }
    }

    private static void writeData(Employee[] employees, PrintWriter out)throws IOException{
        out.println(employees.length);

        for(Employee e:employees)
            writeEmployee(out, e);
    }

    public static void writeEmployee(PrintWriter out, Employee e){
        out.println(e.getName() + "|" + e.getSalary());
    }

    private static Employee[] readData(Scanner in){
        // 得到数组大小
        int n = in.nextInt();
        in.nextLine();

        Employee[] employees = new Employee[n];
        for(int i = 0; i < n; i++)
        {
            employees[i] = readEmployee(in);
        }
        return employees;
    }

    public static Employee readEmployee(Scanner in){
        String line = in.nextLine();
        String[] tokens = line.split("\\|");
        String name = tokens[0];
        int salary = Integer.parseInt(tokens[1]);
        return new Employee(name, salary);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值