Java -- 流与文件01

Java中用于输入和输出的各种应用编程接口(Application Programming Interface, API)。在Java API中,可以在其中读入一个字节序列的对象称做输入流,而可以向其中写入一个字节序列的对象称做输出流。这些字节序列的来源地和目的地可以是文件,而且通常是文件,但是也可以是网络连接,甚至是内存块。

抽象类InputStream和OutputStream构成了输入/输出(I/O)类层次结构的基础。因为面向字节的流不便于处理以Unicode形式存储的信息,Unicode中每个字符都使用了多个字节来表示,所以从抽象类Reader和Writer中继承出来了一个专门用于处理Unicode字符的单独的类层次结构。这些类都是基于两字节的Unicode码元,而不是基于单字节的字符。

读写字节

InputStream类有一个抽象方法:abstract int read(),这个方法将读入一个字节,并返回读入的字节,或者在遇到输入源结尾是返回-1.在设计具体的输入流类时,必须覆盖这个方法以提供使用的功能。InputStream类还有若干个非抽象的方法,它们可以读入一个字节数组,或者跳过大量的字节。这些方法都要调用抽象的read方法,因此每个子类都只需覆盖这一个方法。

OutputStream类定义了下面的抽象方法,abstract void write(int b),它可以向某个输出位置写出一个字节。

read和write方法在执行时都将阻塞,直至字节确实被读入或写出。 available方法检查当前可读入的字节数量。但完成了对流的读写,应该调用close方法来关闭它,这个调用会释放掉有限的操作系统资源,如果一个应用程序打开了过多的流而没有关闭,那么系统资源将被耗尽。关闭一个输入流同时会冲刷用于该输出流的缓冲区。Java提供了众多从基本的InputStream和OutputStream类导出的类,这些类使我们可以处理那些以常用格式表示的数据,而不是字节。

完整的流家族

Java拥有一个流家族,包含各种流类型,其数量超过60个。按照它们的使用方法来进行划分,这样就形成了处理字节和字符的两个单独的层次结构。DataInputStream和DataOutputStream可以以二进制格式读写所有的基本Java类型。

组合流过滤器

FileInputStream和FileOutputStream可以提供附着在一个磁盘文件上的输入流和输出流,而你只需向其构造器提供文件名或文件的完整路径名。所有的java.io中的类都将相对路径解释为以用户工作目录开始。可以通过调用System.getProperty("user.dir")来获得这个信息。windows系统下,可以使用单斜杠字符,由于反斜杠字符在Java中是转义字符,所以要用双反斜杠。而对于可移植的程序来说,应该使用程序所运行平台的文件分隔符,我们可以通过常量字符串java.io.File.separator来获得它。

Java提供了一种灵巧的机制。某些流(例如FileInputStream和由URL类的openStream方法返回的输入流)可以从文件和其他更外部的位置上获得字节。而其他的流(例如DataInputStream和PrintWriter)可以将字节组装到更有用的数据类型。如:
/*从文件中读入数字*/
FileInputStream fin = new FileInputStream("employee.dat");
DataInputStream din = new DataInputStream(fin);
double s = din.readDouble();

可以通过嵌套过滤器来添加多重功能,例如,流在默认情况下是不被缓冲池缓存的,即每个对read的调用都会请求操作系统再分发一个字节。使用缓冲机制显得更高效,如用于文件的数据输入方法:
DataInputStream din = new DataInputStream(
	new BufferedInputStream(
		new FileInputStream("employee.dat")));

有时当多个流链接在一起时,需要跟踪各个中介流。
如:当读入输入时,需要浏览下一个字节,以了解它是否是想要的值。Java提供了PushbackInputStream:
PushbackInputStream pbin = new PushbackInputStream(
	new BufferedInputStream(
		new FileInputStream("employee.dat")));

/*预读下一个字节*/
int b = pbin.read();

/*在它并非你所期望的值时将其推回流中*/
if(b != '<')	pbin.unread(b);

/*读入和回推是可回推输入流的仅有方法,如想预先浏览并且可以读入数字,那么就需要一个
既是可回推输入流,又是一个数据输入流的引用*/
DataInputStream din = new DataInputStream(
	pbin = new PushbackInputStream(
		new BufferedInputStream(
			new FileInputStream("employee.dat"))));

文本输入与输出

在保存数据时,可以选择二进制格式或文本格式。OutputStreamWriter类将使用选定的字符编码方式,把Unicode字符流转换为字节流。而InputStreamReader类将包含字节(用某种字符编码方式表示的字符)的输入流转换为可以产生Unicode码元的读入器。
如让一个输入读入器可以从控制台读入键盘敲击信息:
InputStreamReader in = new InputStreamReader(System.in);

如何写出文本输出

对于文本输出,可以使用PrintWriter。这个类拥有以文本格式打印字符串和数字的方法,甚至有一个将PrintWriter链接到FileWriter的便捷方法。
PrintWriter out = new PrintWriter("employee.txt"); 等价于 PrintWriter out = new PrintWriter(new FileWriter("employee.txt"));

为了输入到打印写出器,需要使用与使用System.out相同的print, println和printf方法。

String name = "Harry Hacker";
double salary = 75000;
out.print(name);
out.print(' ');
out.println(salary);
/*将Harry Hacker 75000.0 输入到 写入器 out中。之后这些字符被转换为字节并最终写入employee.txt中*/
如果写出器设置为自动冲刷模式,那么只要println被调用,缓冲区中的所有字符都会被发送到它们的目的地。默认情况下,自动冲刷机制是禁用的。可以通过调用PrintWriter(Writer out, Boolean autoFlush)来启用或禁用自动冲刷机制。

如何读入文本输入

在Java5.0之前,处理文本输入的唯一方式是通过BufferedReader类,它拥有一个readLine方法,使得可以读入一行字符。
BufferedReader in = new BufferedReader(
	new InputStreamReader(new FileInputStream("employee.txt"), "UTF-8"));
然而,BufferedReader没有任何用于读入数字的方法,所以我们使用Scanner来读入文本输入。




猜你喜欢

转载自blog.csdn.net/WilliamChancwl/article/details/78406760