“Java IO”总结

1 篇文章 0 订阅
首先讲到的是File类,首先查看博客文章“Java IO File类总结”

流类:
流的概念:
---java程序通过流来完成输入/输出。流是生产或消费信息的抽象。流通过Java的输入/输出系统与物理设备链接。尽管与他们链接的物理设备不尽相同,所有流的行为具有同样的方式。这样,相同的输入/输出类和方法适用于所有类型的外部设备。这意味着一个输入流能够抽象多种不同类型的输入:从磁盘文件,从键盘或从网络套接字。同样,一个输出流可以输出到控制台,磁盘文件或相连的网络。流是处理输入/输出的一个洁净的方法,例如它不需要代码理解键盘和网络的不同。Java中流的实现是在java.io包定义的类层次结构内部的。


输入/输出流的概念:
---输入/输出时,数据在通信通道中流动。所谓“数据流(stream)”指的是所有数据通信通道之中,数据的起点和终点。信息的通道就是一个数据流。只要是数据从一个地方“流”到另一个地方,这种数据流动的通道都可以称为数据流。
---输入/输出是相对于程序来说的。程序在使用数据时所扮演的角色有两个:一个是源,一个是目的。若程序是数据流的源,即数据的提供者,这个数据流对程序来说就是一个“输出数据流”(数据从程序流出)。若程序是数据流的终点,这个数据流对程序而言就是一个“输入数据流”(数据从程序外流向程序)


输入/输出类:
---在java.io包中提供了60多个类(流)。
---从功能上分为两大类:输入流和输出流。
---从流结构上可分为字节流(以字节为处理单位或称面向字节)和字符流(以字符为处理单位或称面向字符)。
---[color=red]字节流的输入流和输出流基础是InputStream和OutputStream这两个抽象类,字节流的输入输出操作由这两个类的子类实现。字符流是Java 1.1版后新增加的以字符为单位进行输入输出处理的流,字符流输入输出的基础是抽象类Reader和Writer[/color]。


[color=red]字符流底层也是采用字节流实现的。在底层,所有的输入/输出都是字节形式的。基于字符的流只处理字符提供方便有效的方法[/color]。


Java 2定义了两种类型的流:字节流和字符流。字节流(byte stream)为处理字节的输入和输出提供了方便的方法。例如[color=red]使用字节流可以读取或写入二进制数据[/color]。字符流(character stream)为字符的输入和输出提供了方便。它们采用了统一的编码标准,因而可以国际化。当然,在某些场合,字符流比字节流更有效。


---字节流类(Byte Streams) 字节流类用于向字节流读写8位二进制的字节。一般的,字节流类主要用于读写诸如图像或声音等的二进制数据。
---字符流类(Character Streams) 字符流类用于向字符流读写16位二进制字符。


[img]http://dl2.iteye.com/upload/attachment/0091/1286/39e780f9-1373-36bc-b228-03b9d37c9701.jpg[/img]


两种基本的流是:输入流(Input Stream)和输出流(Output Stream)。可从中读出一系列字节的对象称为输入流。而能向其中写入一系列字节的对象称为输出流。


输入流:
读数据的逻辑为:
open a stream【打开一个流,就像一个水库,开砸了才能取水】
while more information【一次不可能把全部信息读取完,读一部分之后while判断是否还有更多信息】
read information【还有更多信息的话就继续读取信息】
close the stream【读取完信息之后关闭流,流是一种资源,必须关闭了其他地方才能再使用,比如我打开一个文件,但是没有关,那么我就删不掉这个文件,一样的道理】

写数据的逻辑为:
open a stream
while more information
write information
close the stream


流的下一个分类(节点流和过滤流):
[img]http://dl2.iteye.com/upload/attachment/0091/1282/a0403afd-0a0a-361e-af1f-36d7f49032e4.jpg[/img]

节点流直接是和目标交互的,比如说我要从硬盘上读取一个文件,那么这个节点流就是针对于文件的流,直接和文件进行连接的,在读取的过程当中,我可以对节点刘进行一个过滤(比如读取到信息之后我可以对它进行一个包装,增加一些新的功能等),这就是过滤流。过滤流总是与节点流打交道或是与其他的过滤流打交道,而节点刘总是与特定的目标信息打交道的。


字节流类以InputStream和OutputStream为顶层类,他们都是抽象类(abstract)


抽象类InputStream和OutputStream定义了实现其他流类的关键方法。最重要的两种方法是read()和write(),他们分别对数据的字节进行读写。两种方法都在InputStream和OutputStream中被定义为抽象方法。[color=red]它们被派生的流类重写[/color]。

每个抽象类都有多个具体的子类,这些子类对不同的外设进行处理,例如磁盘文件,网络连接,甚至是内存缓冲区。


InputStream三个基本的读方法:
---abstract int read():读取一个字节数据,并返回读到的数据,如果返回-1,表示读到了输入流的末尾。
---int read(byte[] b):将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。
---int read(byte[] b, int off, int len):将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。Off指定在数组b中存放数据的其实偏移位置;len指定读取的最大字节数。

问题:为什么只有第一个read方法是抽象的,而其余两个read方法都是具体的?
答案:因为第二个read方法依靠第三个read方法来实现,而第三个read方法又依靠第一个read方法来实现,所以说只有第一个read方法是与具体的I/O设备相关的,它需要InputStream的子类来实现。


Jdk提供的InputStream的每一个子类里面都要重写read()这个方法,而用于完成不同功能的输入流子类,他们重写read()方法的实现方式肯定是不同的。这个read()方法你即便在InputStream你给我定义好了,我的子类里面也一定需要把它重写,你定义的肯定是不符合要求的,这不就符合抽象类的它的含义么(包含抽象方法,包含具体方法,它的子类必须实现抽象方法),具体read()的实现方式你根据自己的实际需求来定,假如你是处理网络的,你就按照网络的那种方式来实现,假如你是处理字节数组的,你就按照字节数组的那种方式来实现,你处理文件的,就按照文件的方式来实现…..。所以InputStream不同的子类对read()方法的实现完全是不一样的。


下面实际开发中流的使用最最常见的一种用法(固定模式):
package com.shengshiyuan.io2;

import java.io.File;
import java.io.FileInputStream;

/**
* 输入流使用的常见的通用使用方式
* 类: InputStreamTest1 <br>
* 描述: TODO <br>
* 作者:
* 时间: Nov 13, 2013 3:23:44 PM
*/
public class InputStreamTest1 {
public static void main(String[] args) throws Exception {
FileInputStream inputStream = new FileInputStream(new File(
"C:/a/hello.txt"));

byte[] b = new byte[200];

StringBuffer str = new StringBuffer();

int length = 0;

// 从0开始读,最多读200个,并返回实际读取到的字节个数赋给length
while ((length = inputStream.read(b, 0, 200)) != -1) {
// 把字节数组转换成字符串,从第0个位置开始转,并指定将length个字节转换成字符。绝对不能写200哈,因为最后一次读取到的字节数很可能不够200个
String s = new String(b, 0, length);
str.append(s);
}

System.out.println(str.toString());

inputStream.close();
}
}


InputStream的子类以及节点流、过滤流的一些讲解:
[img]http://dl2.iteye.com/upload/attachment/0091/2673/9ea02cf5-56e0-35d3-9042-6a92d9defd62.jpg[/img]

FilterInputStream是一个过滤流,FilterInputStream 包含其他一些输入流(节点流),它将这些流用作其基本数据源,我们通常使用它的子类(4个子类)。它的一些子类都是过滤流,这些过滤流可以包装其他的节点流。你用一个过滤流包装了一个节点流,那么这个节点流就相应的增加了新的功能。例如用BufferedInputStream包装FileInputStream,那么这个FileInputStream就具有了缓冲的功能。注:上面图里面的InputStream的直接子类里面除了FilterInputStream是过滤流外,其余所有类都是节点流。

InputStream中包含一套字节输入流需要的方法,可以完成最基本的从输入流读入数据的功能。当Java程序需要外设的数据时,可根据数据的不同形式,创建一个适当的InputStream子类类型的对象来完成与该外设的连接,然后再调用执行这个流类对象的特定输入方法来实现对外设的输入操作。
InputStream类子类对象自然也继承了InputStream类的方法。常用的方法有:读数据的方法read(),获取输入流字节数的方法available(),定位输入位置指针的方法skip()、reset()、mark()等。


下面讲解OutputStream:
---三个基本的写方法:
abstract void write(int b):往输出流中写入一个字节。
void write(byte[] b):往输出流中写入数组b中的所有字节。
void write(byte[] b, int off, int len):往输出流中写入数组b中从偏移量off开始的len个字节的数据。

---其他方法:
void flush():刷新输出流,强制缓冲区中的输出字节被写出。
void close():关闭输出流,释放和这个流相关的系统资源。


OutputStream是定义了流式字节输出模式的抽象类。该类的所有方法返回一个void值并且在出错情况下引发一个IOException异常。
通过打开一个到目标的输出流,程序可以向外部目标顺序写数据。
[img]http://dl2.iteye.com/upload/attachment/0091/2675/190b791e-4610-3c8e-b35d-23b2d2b18f72.jpg[/img]


OutputStream的子类以及节点流、过滤流的一些讲解:
[img]http://dl2.iteye.com/upload/attachment/0091/2677/874de0b1-a433-34b6-8b96-8b44b0d6bea5.jpg[/img]
和输入流一样,输出流OutputStream的子类里面也同样有一个过滤流(其他的都是节点流),这个流的三个子类都是过滤流,可以包装其他的节点流。注:上面图里面的OutputStream的直接子类里面除了FilterOutputStream是过滤流外,其余所有类都是节点流。


[color=red]下面重点讲解过滤流[/color]:
在InputStream类和OutputStream类子类中,过滤流FilterInputStream和FilterOutputStream过滤流抽象类又派生出DataInputStream和DataOutputStream数据输入输出流类等子类,这些类都作为过滤流类来使用。
过滤流的主要特点是在输入输出数据的同时能对所传输的数据做指定类型或格式的转换,即可实现对二进制字节数据的理解和编码转换。
数据输出流DataInputStream中定义了多个针对不同类型数据的读方法,如readByte()、readBoolean()、readShort()、readChar()、reading()、readLong()、readFloat()、readDouble()、readLine()等。
数据输出流DataOutputStream中定义了多个针对不同类型数据的写方法,如writeByte()、writeBoolean()、writeShort()、writeChar()、writeInt()、writeLong()、writeFloat()、writeDouble()、writeChars()等。
过滤流在读/写数据的同时可以对数据进行处理,它提供了同步机制,使得某一时刻只有一个线程可以访问一个I/O流,以防止多个线程同时对一个I/O流进行操作所带来的意想不到的结果。
类FilterInputStream和FilterOutputStream分别作为所有过滤输入流和输出流的父类。

===========================过滤流讲解完毕====================================


OutputStream中包含一套字节输出流需要的方法,可以完成最基本的输出数据到输出流的功能。当Java程序需要将数据输出到外设时,可根据数据的不同形式,创建一个适当的OutputStream子类类型的对象来完成与外设的连接,然后再调用执行这个流类对象的特定输出方法来实现对相应外设的输出操作。
OutputStream类子类对象也继承了OutputStream类的方法。常用的方法有:写数据的方法write(),关闭流方法close()等。

下面是OutputStream一个测试类:
package com.shengshiyuan.io2;

import java.io.FileOutputStream;
import java.io.OutputStream;

/**
* 文件输出流示例
* 类: OutputStreamTest1 <br>
* 描述: TODO <br>
* 作者:
* 时间: Nov 14, 2013 11:12:17 AM
*/
public class OutputStreamTest1 {
public static void main(String[] args) throws Exception {
// 第二个参数如果为true,则将字节追加到文件末尾处;如果为false,则用现在的字节覆盖文件里面原来的内容
OutputStream os = new FileOutputStream("C:/a/hello.txt", true);

String str = "123";
// 获得字符串的字节数组
byte[] buffer = str.getBytes();
// 写内容
os.write(buffer);
os.close();

}
}



基本流类讲解:
FileInputStream和FileOutputStream:节点流,用于从文件中读取或往文件中写入字节流。如果在构造FileOutputStream时,文件已经存在,则覆盖这个文件(可以用第二个参数指定不覆盖,追加内容)。
BufferedInputStream和BufferedOutputStream:过滤流,需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率。
DataInputStream和DataOutputStream:过滤流,需要使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。
PipedInputStream和PipedOutputStream:管道流(节点流),用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流。


I/O流的链接:
[img]http://dl2.iteye.com/upload/attachment/0091/2679/5682b003-e660-3ad8-8015-c1af5c8774ea.jpg[/img]


BufferedOutputStream(缓冲输出流):
缓冲输出流BufferedOutputStream类提供和FileOutputStream类同样的写操作方法,但所有输出全部写入缓冲区中。当写满缓冲区或关闭输出流时,它再一次性输出到流,或者用flush()方法主动将缓冲区输出到流。
BufferedOutputStream与任何一个OutputStream相同,除了用一个另外的flush()方法来保证数据缓冲区被写入到实际的输出设备。
BufferedOutputStream通过减小系统写数据的时间而提高性能。
[color=red]如果不使用缓冲输出流,直接使用FileOutputStream,那么就是往流里面写一个字符,然后就直接往文件里面写一次,操作一次文件,对文件的操作相当频繁[/color]。
缓冲去里面的内容写到文件里面有两种方式:
1、调用BufferedOutputStream的flush()方法。
2、调用close()方法之前会把缓冲区里的东西都写入流里面。

下面是BufferedOutputStream一个测试类:
package com.shengshiyuan.io2;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class BufferedOutputStreamTest1 {
public static void main(String[] args) throws Exception {
OutputStream os = new FileOutputStream("1.txt");

BufferedOutputStream bos = new BufferedOutputStream(os);

bos.write("http://www.google.com".getBytes());

bos.close();
os.close();
}
}


不像缓冲输入,缓冲输出不提供额外的功能,Java中输出缓冲区是为了提高性能的。下面是两个可用的构造方法:
---BufferedOutputStream(OutputStream outputStream)
---BufferedOutputStream(OutputStream outputStream, int bufSize)
---第一种形式创建了一个使用512字节缓冲区的缓冲流。
---第二种形式,缓冲区的大小用bufSize参数传入。

要想在程序结束之前将缓冲区里的数据写入磁盘,除了填满缓冲区或关闭输出流外,还可以显示调用flush()方法。Flush()方法的声明为:
---public void flush() throws IOException


BufferedInputStream(缓冲输入流):
---public void mark(int readlimit):在此输入流中标记当前的位置。对reset方法的后续调用会在最后标记的位置重新定位此流,以便后续读取重新读取相同的字节。
---public void reset():将此流重新定位到对此输入流最后调用mark方法时的位置。

缓冲一个输入流同样提供了在可用缓冲区的流内支持向后移动的必备基础。除了在任何InputStream类中执行的read()和skip()方法外,BufferedInputStream同样支持mark()和reset()方法。
BufferedInputStream.markSupported()返回true是这一支持的体现。
当创建缓冲输入流BufferedInputStream时,一个输入缓冲区数组被创建,来自流的数据填入缓冲去,一次课填入许多字节。
缓冲输入/输出是一个非常普通的性能优化。Java的BufferedInputStream类允许把任何InputStream类“包装”成缓冲流并使它的性能提高。


BufferedInputStream有两个构造方法:
---BufferedInputStream(InputStream inputStream)
---BufferedInputStream(InputStream inputStream, int bufSize)
---第一种形式创建BufferedInputStream流对象并为以后的使用保存InputStream参数in,并创建一个内部缓冲区数组来保存输入数据。
---第二种形式用指定的缓冲区大小size创建BufferedInputStrean流对象,并为以后的使用保存InputStream参数in。

缓冲字节流:
若处理的数据量较多,为避免每个字节的读写都对流进行,可以使用过滤流类的子类缓冲流。缓冲流建立一个内部缓冲区,输入输出数据先读写到缓冲区中进行操作,这样可以提高文件流的操作效率。


下面是ByteArrayInputStream和ByteArrayOutputStream两个使用示例:
package com.shengshiyuan.io2;

import java.io.ByteArrayInputStream;

public class ByteArrayInputStreamTest1 {
public static void main(String[] args) {
String temp = "abc";
byte[] b = temp.getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(b);
for (int i = 0; i < temp.length(); i++) {
int c;
// 每次会读一个字节
while (-1 != (c = in.read())) {
if (0 == i) {
// java里面的字符在内存里面都是用数字表示的,用整型来表示的,获取到c之后,c是一个整型,把它转换成字符才能真正显示出来字符的内容。
System.out.println((char) c);
} else {
// 将字符"(char)c"转换成大写。
System.out.println(Character.toUpperCase((char) c));
}
}
System.out.println();

// 将缓冲区读的位置重置为标记位置。除非已标记了另一个位置,或者在构造方法中指定了一个偏移量,否则该标记位置是
// 0。【查看API文档,这个在实际开发中用的不多】。可以调用mark()方法来设定读取时回到流的哪个字节的位置上开始读取,不设定的话就回到流的起始位置
in.reset();
}
}
}

package com.shengshiyuan.io2;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;

/**
* ByteArrayOutputStream使用示例
* 类: ByteArrayOutputStreamTest1 <br>
* 描述: TODO <br>
* 作者: fangguanhong fangguanhong@163.com <br>
* 时间: Nov 15, 2013 4:34:12 PM
*/
public class ByteArrayOutputStreamTest1 {
public static void main(String[] args) throws Exception {
ByteArrayOutputStream f = new ByteArrayOutputStream();
String str = "hello world welcome";

byte[] buffer = str.getBytes();
// 把str对应的字节数组写到f这个流里面
f.write(buffer);

// 从f这个流里面得到刚才放进去那个字节数组
byte[] result = f.toByteArray();

// 遍历字节数组,打印每个字符
for (int i = 0; i < result.length; i++) {
System.out.println((char) result[i]);
}

OutputStream os = new FileOutputStream("test.txt");
// 将f里面的字节数组写入到os这个流里面去
f.writeTo(os);

f.close();
os.close();
}
}


关于io的笔记太多,决定最后还是把笔记里面的两个pdf文档上传到博客文章的附件作为日后查看笔记的地址(IO_1.pdf和IO_2.pdf,老师讲课时候的课件)。上面记录的只作为一个样例查看(比如笔记顺序,模块汇总等等,上面记录的笔记都是比较重要的,并且所有笔记在附件的pdf文档里面都有)。

下面是DataInputStream和DataOutputStream的使用示例:
package com.shengshiyuan.io2;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
* DataOutputStream使用示例
* 使用了装饰模式
* 类: DataStream1 <br>
* 描述: TODO <br>
* 作者:
* 时间: Nov 15, 2013 5:30:27 PM
*/
public class DataStream1 {
public static void main(String[] args) throws Exception {
// FileOutputStream是节点流,BufferedOutputStream是过滤流,DataOutputStream是过滤流,过滤流可以包装节点流,过滤流也可以包装节点流。
// 单独使用FileOutputStream只能向文件里面写数据,使用BufferedOutputStream表示可以带缓冲的方式写数据,使用DataOutputStream表示可以使用java基本数据类型的方式写数据。
// 综合起来表示我可以向文件当中以缓冲的方式写入java的基本数据类型。也就是所最后生成的dos对象的功能增强了,它现在已经具备三个功能了。
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(
new FileOutputStream("data.txt")));

byte b = 3;
int i = 12;
char c = 'a';
float f = 3.3f;
dos.writeByte(b);
dos.writeInt(i);
dos.writeChar(c);
dos.writeFloat(f);

dos.close();

// 上面吧数据写入到文件里面了,下面再读出来。
DataInputStream dis = new DataInputStream(new BufferedInputStream(
new FileInputStream("data.txt")));
// 读和写的顺序一定要保持一致
System.out.println(dis.readByte());
System.out.println(dis.readInt());
System.out.println(dis.readChar());
System.out.println(dis.readFloat());

dis.close();
}
}



[size=large][color=red]实际项目里面一定会用到的流类有:FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream、ByteArrayInputStream、ByteArrayOutputStream。其他的虽然用,但是用的不多,有的甚至用的很少[/color][/size]。


[size=small][color=red]下面开始讲解java io的另一个重要模块:字符流,(上面讲解的都是字节流)[/color][/size]。


首先查看字符流的相关pdf文档IO_3.pdf,了解详细知识。并且听完之后把pdf文档里面的笔记重写在这个文档里面记录一遍并且贴到将来的博客文章里面。


尽管字节流提供了处理任何类型输入/输出操作的足够的功能,它们不能直接操作[color=red]Unicode[/color]字符。既然Java的一个主要目的是支持“只写一次,到处运行”的哲学,包括直接的字符输入/输出支持是必要的。本节将讨论几个字符输入/输出类。字符流层次结构的顶层是[color=red]Reader [/color]和[color=red]Writer [/color]抽象类。我们将从它们开始。

字符输入/输出类是在java 的1.1版本中新加的。由此,你仍然可以发现遗留下的程序代码在应该使用字符流时却使用了字节流。当遇到这种代码,最好更新它

由于Java采用16位的Unicode字符,因此需要基于字符的输入/输出操作。从Java1.1版开始,加入了专门处理字符流的抽象类Reader和Writer,前者用于处理输入,后者用于处理输出。这两个类类似于InputStream和OuputStream,也只是提供一些用于字符流的规定,本身不能用来生成对象。

Reader和Writer类也有较多的子类,与字节流类似,它们用来创建具体的字符流对象进行I/O操作。字符流的读写等方法与字节流的相应方法都很类似,但读写对象使用的是字符

Reader中包含一套字符输入流需要的方法,可以完成最基本的从输入流读入数据的功能。当Java程序需要外设的数据时,可根据数据的不同形式,创建一个适当的Reader子类类型的对象来完成与该外设的连接,然后再调用执行这个流类对象的特定输入方法,如read(),来实现对相应外设的输入操作。

Writer中包含一套字符输出流需要的方法,可以完成最基本的输出数据到输出流的功能。当Java程序需要将数据输出到外设时,可根据数据的不同形式,也要创建一个适当的Writer子类类型的对象来完成与该外设的连接,然后再调用执行这个流类对象的特定输出方法,如write(),来实现对相应外设的输出操作。

• Reader是定义Java的流式字符输入模式的抽象类。该类的所有方法在出错情况下都将引发IOException 异常 。
• Writer 是定义流式字符输出的抽象类。所有该类的方法都返回一个void 值并在出错条件下引发IOException 异常。


Java.io包中Reader的类层次:
[img]http://dl2.iteye.com/upload/attachment/0091/2683/8bc9544c-0880-3942-b4b8-dd3528e3cd56.jpg[/img]
像里面的FilterReader也是过滤类型的,和字节流里面的过滤流使用方式类似。

Java.io包中Writer的类层次:
[img]http://dl2.iteye.com/upload/attachment/0091/2671/de0a2fc6-13f4-3bf9-8223-c569784f24ca.jpg[/img]
像里面的FilterWriter也是过滤类型的,和字节流里面的过滤流使用方式类似。


Java 程序语言使用Unicode来表示字符串和字符,[color=red]Unicode使用两个字节来表示一个字符[/color],即一个字符占16位(一个字节占8位)。

[color=red]InputStreamReader和OutputStreamWriter[/color]两个类是java.io包中用于处理字符流的基本类,[color=red]用来在字节流和字符流之间搭一座“桥”[/color]。这里字节流的编码规范与具体的平台有关,可以在构造流对象时指定规范,也可以使用当前平台的缺省规范。

• InputStreamReader和OutputStreamWriter类的主要构造方法如下
–public InputSteamReader(InputSteam in)
–public InputSteamReader(InputSteam in,String enc)
–public OutputStreamWriter(OutputStream out)
–public OutputStreamWriter(OutputStream out,String enc)
• [color=red]其中in和out分别为输入和输出字节流对象[/color],enc为指定的编码规范(若无此参数,表示
使用当前平台的缺省规范,可用getEncoding()方法得到当前字符流所用的编码方式)。
• 读写字符的方法read()、write(),关闭流的方法close()等与Reader和Writer类的同名方法用法都是类似的。

• FileReader类创建了一个可以读取文件内容的Reader类。FileReader继承于InputStreamReader。它最常用的构造方法显示如下
–FileReader(String filePath)
–FileReader(File fileObj)
–每一个都能引发一个FileNotFoundException异常。这里,filePath是一个文件的完整路径,fileObj是描述该文件的File 对象。

• FileWriter 创建一个可以写文件的Writer 类。 FileWriter继承于OutputStreamWriter.它最常用的构造方法如下:
–FileWriter(String filePath)
–FileWriter(String filePath, boolean append)
–FileWriter(File fileObj)
–append :如果为 true,则将字节写入文件末尾处,而不是写入文件开始处
• FileWriter类的创建不依赖于文件存在与否。在创建文件之前,FileWriter将在创建对象时打开它来作为输出。如果你试图打开一个只读文件,将引发一个IOException异常。


• CharArrayReader 是一个把字符数组作为源的输入流的实现。该类有两个构造方法,每一个都需要一个字符数组提供数据源
–CharArrayReader(char array[ ])
–CharArrayReader(char array[ ], int start, int numChars)
–这里,array是输入源。第二个构造方法从你的字符数组的子集创建了一个Reader,该子集以start指定的索引开始,长度为numChars。


• BufferedReader 通过缓冲输入提高性能。它有两个构造方法
–BufferedReader(Reader inputStream)
–BufferedReader(Reader inputStream, int bufSize)
–第一种形式创建一个默认缓冲区长度的缓冲字符流。第二种形式,缓冲区长度由bufSize传入
• 和字节流的情况相同,缓冲一个输入字符流同样提供支持可用缓冲区中流内反向移动的基础。为支持这点,BufferedReader 实现了mark( )和reset( )方法,并且BufferedReader.markSupported( ) 返回true


• BufferedWriter是一个增加了flush( )方法的Writer。flush( )方法可以用来确保数据缓冲区确实被写到实际的输出流。用BufferedWriter 可以通过减小数据被实际的写到输出流的次数而提高程序的性能。

• BufferedWriter有两个构造方法:
–BufferedWriter(Writer outputStream)
–BufferedWriter(Writer outputStream, int bufSize)
–第一种形式创建了使用默认大小缓冲区的缓冲流。第二种形式中,缓冲区大小是由bufSize参数传入的

• ASCII(American Standard Code for Information Interchange,美国信息互换标准代码),是基于常用的英文字符的一套电脑编码系统。我们知道英文中经常使用的字符、数字符号被计算机处理时都是以二进制码的形式出现的。这种二进制码的集合就是所谓的ASCII码。每一个ASCII码与一个8位(bit)二进制数对应。其最高位是0,相应的十进制数是0-127。如,数字“0”的编码用十进制数表示就是48。另有128个扩展的ASCII码,最高位都是1,由一些制表符和其它符号组成。ASCII是现今最通用的单字节编码系统。
• GB2312:GB2312码是中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字符集-基本集》。主要用于给每一个中文字符指定相应的数字,也就是进行编码。一个中文字符用两个字节的数字来表示,为了和ASCII码有所区别,将中文字符每一个字节的最高位置都用1来表示。【用来表示中文的编码格式】
• GBK:为了对更多的字符进行编码,国家又发布了新的编码系统GBK(GBK的K是“扩展”的汉语拼音第一个字母)。在新的编码系统里,除了完全兼容GB2312 外,还对繁体中文、一些不常用的汉字和许多符号进行了编码。 【它是能表示一些生僻的GB2312表示不了的中文】
• ISO-8859-1:是西方国家所使用的字符编码集,是一种单字节的字符集 ,而英文实际上只用了其中数字小于128的部分。【不能表示中文】
• Unicode:这是一种通用的字符集,对所有语言的文字进行了统一编码,对每一个字符都用2个字节来表示,对于英文字符采取前面加“0”字节的策略实现等长兼容。如 “a” 的ASCII码为0x61,UNICODE就为0x00,0x61。(在internet上传输效率较低)
• UTF-8:Eight-bit UCS Transformation Format,(UCS,Universal Character Set,通用字符集,UCS 是所有其他字符集标准的一个超集)。一个7位的ASCII码值,对应的UTF码是一个字节。如果字符是0x0000,或在0x0080与0x007f之间,对应的UTF码是两个字节,如果字符在0x0800与0xffff之间,对应的UTF码是三个字节(汉字为3个字节)。【最通用的一种编码格式,所有的语言都能表示,国际化里面一般都用的这种编码格式】


下面来个小的总结:
• [size=x-large][color=red]InputStream和OutputStream:字节流的输入输出[/color][/size]。
• [size=x-large][color=red]Reader和Writer:字符流的输入输出[/color][/size]。
• 流的链接(Java I/O库的设计原则)

下面是字符流的一些使用示例(重点查看):
package com.shengshiyuan.io2;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class StreamTest {
// 使用字符流操作字符串的时候就比使用字节流方便多了,不用一次次将字节转换成字符了(虽然使用字符流的地方使用字节流也能实现,但是没它方便)。
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("file.txt");

OutputStreamWriter osw = new OutputStreamWriter(fos);

BufferedWriter bw = new BufferedWriter(osw);

bw.write("http://www.google.com");
bw.write("\n");
bw.write("http://www.baidu.com");

bw.close();

FileInputStream fis = new FileInputStream("file.txt");

InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);

// 固定的代码格式(经常用到)
String str = br.readLine();
while (null != str) {
System.out.println(str);
str = br.readLine();
}

br.close();
}
}

package com.shengshiyuan.io2;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class StreamTest2 {
public static void main(String[] args) throws Exception {
// 将标准输入设备(比如键盘就是标准输入设备,命令行就是标准输出设备)包装成一个字符流
InputStreamReader isr = new InputStreamReader(System.in);

BufferedReader br = new BufferedReader(isr);

String str;
while (null != (str = br.readLine())) {
System.out.println(str);
}

br.close();
}
}

package com.shengshiyuan.io2;

import java.io.BufferedReader;
import java.io.FileReader;

/**
* FileReader使用示例
* 类: FileReader1 <br>
* 描述: TODO <br>
* 作者: fangguanhong fangguanhong@163.com <br>
* 时间: Nov 18, 2013 3:30:53 PM
*/
public class FileReader1 {
// 读取自己的源文件,然后写到命令行里面
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader(
"c:/FileReader1.java");
// 增加缓冲
BufferedReader br = new BufferedReader(fr);

String str;
while (null != (str = br.readLine())) {
System.out.println(str);
}
br.close();
}
}

package com.shengshiyuan.io2;

import java.io.FileWriter;

/**
* FileWriter使用示例
* 类: FileWriter1 <br>
* 描述: TODO <br>
* 作者: fangguanhong fangguanhong@163.com <br>
* 时间: Nov 18, 2013 3:46:09 PM
*/
public class FileWriter1 {
public static void main(String[] args) throws Exception {
String str = "hello world welcome nihao hehe";

char[] buffer = new char[str.length()];

// 从字符串里面将字符拷贝到目标数组里面
str.getChars(0, str.length(), buffer, 0);

FileWriter f = new FileWriter("file2.txt");

for (int i = 0; i < buffer.length; i++) {
f.write(buffer[i]);
}

f.close();
}
}

package com.shengshiyuan.io2;

import java.io.CharArrayReader;

/**
* CharArrayReader使用示例
* 类: CharArrayReader1 <br>
* 描述: TODO <br>
* 作者: fangguanhong fangguanhong@163.com <br>
* 时间: Nov 18, 2013 4:01:52 PM
*/
public class CharArrayReader1 {
public static void main(String[] args) throws Exception {
String temp = "abcdefg";

char[] ch = new char[temp.length()];

// 从字符串里面将字符拷贝到目标数组里面
temp.getChars(0, temp.length(), ch, 0);

CharArrayReader input = new CharArrayReader(ch);

int i;
while (-1 != (i = input.read())) {
System.out.println((char) i);
}

input.close();
}
}



RandomAccessFile类比较特殊,即能读,又能写。而且没有继承InputStream和OutputStream。这个类了解下就可以。

把IO_1.pdf和IO_2.pdf上传附件即可,IO_3.pdf和Decorator.pdf已经在笔记里面总结完了。

附件里面的IO_2.zip里面装IO_2.pdf,IO_1.zip里面装IO_1.pdf
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值