节点流
File
文件
|
字符流
|
字节流
|
---|---|---|
File
文件
|
FileReader
、
FileWriter
|
FileInputStream
、
FileOutputStream
|
内存数组
|
CharArrayReader
、
CharArrayWriter
|
ByteArrayInputStream
、
ByteArrayOutp
|
内存字串
|
StringReader,
StringWriter
| |
管道
|
PipedReader
、
PipedWriter
|
PipedInputStream,
PipedOutputStream
|
文件节点流
FileInputStream
和
FileOutputStream
是文件字节流,是一种节点流
文件字节输入流的构造方法:
- FileInputStream("文件名称"),如果文件不存在则FileNotFoundException
- FileInputStream(File)
文件字节输出流的构造方法
:
- FileOutputStream(“文件名称”) 如果文件不存在则新建文件,如果文件存在则覆盖文件内容
- FileOutputStream(String name文件名称, boolean append是否采用追加方式)
FileReader
和
FileWriter
类似
FileInputStream
和
FileOutputStream
两个类属于结点流,第一个类的源端和第二个类的目的端都是磁盘文件,它们的构造方法允许通过文件的路径名来构造相应的流。
如:
FileInputStream infile = new FileInputStream("myfile.dat");
FileOutputStream outfile = new FileOutputStream("results.dat");
要注意的是,构造
FileInputStream,
对应的文件必须存在并且是可读的,而构造
FileOutputStream
时,如输出文件已存在,则必须是可覆盖的
。
将
d
盘上的
TestFile.java
拷贝到
e
盘,并命名为
dd.txt
try(
InputStream is = new FileInputStream("d:/TestFile.java");
OutputStream os = new FileOutputStream("e:\\dd.txt");)
{
byte[] buffer = new byte[8192];
int len = is.read(buffer);
while (len > 0) {
os.write(buffer, 0, len);
len = is.read(buffer);
}
}catch(
IOException e)
{
e.printStackTrace();
}
// 构造输出文件流时可以使用两种不同的方式
OutputStream os = new FileOutputStream("e:\\dd.txt");
// 如果文件不存在则自动创建;如 果文件存在则进行覆盖
OutputStream os=new FileOutputStream("e:\\dd.txt",true),
// 这里的boolean类型参数 表示是否采用追加的方式写入文件
内存数组节点
如果文本则使用
char[]
,如果二进制则使用
byte[]
构造器方法
- CharArrayReader(char[] buf)其中char[]就是数据的来源,也就是说Reader就是从char[]中读取数据
- CharArrayRead(char[] buf, int offset, int length)
CharArrayWriter
用于实现向一个字符数组中写入数据,这个数组可以自动调整大小
ByteArrayInputStream
、
ByteArrayOutputStream
和
CharArrayReader
以及
CharArrayWriter
类似,支持操作的内容不同而已,操作
byte[]
与
char[]
内存字串流
StringReader
用于从一个字串
String
中读取数据
String str = "亚洲说:‘我爱小黑’";
StringReader sr = new StringReader(str);
int cc;while((cc=sr.read())!=-1)
System.out.print((char)cc);
sr.close();
StringWriter
用于给一个
StringBuffer
中写入数据,实现一个可边长的字串
Scanner sc=new Scanner(System.in);try(
StringWriter sw = new StringWriter();
Writer fw = new FileWriter("c:/console.txt"))
{
String temp = sc.nextLine();
while (!temp.equals("quit")) {
if (temp != null && temp.trim().length() > 0)
sw.write(temp + "\n");
temp = sc.nextLine();
}
fw.write(sw.toString());
}
总结
- 读写文件使用节点流FileInputStream/FileOutputStream和FileReader/FileWriter,如果操作文本 文件,建议使用FileReader/FileWriter,如果操作二进制文件建议使用 FileInputStream/FileOutputStream
- 需要建立缓冲区(建立临时文件的方式效率低),可以考虑使用内存节点,例如 CharArrayReader/CharArrayWriter、StringReader/StringWriter和 ByteArrayInputStream/ByteArrayOutputStream
- 如果需要一个二进制缓冲区可以使用ByteArrayInputStream/ByteArrayOutputStream,如果需要 一个字符缓存可以使用CharArrayReader/CharArrayWriter、StringReader/StringWriter
- 如果数据量不是特别大使用CharArrayReader/CharArrayWriter更为方便,如果数据量大而且可能 需要直接操作缓冲区则使用StringReader/StringWriter
- StringWriter中提供了方法getBuffer():StringBuffer
过滤流类型
过滤流就是在节点流的基础上附加功能
处理类型
|
字符流
|
字节流
|
缓存
|
BufferedReader
、
BufferedWriter
|
BufferedInputStream
、
BufferedOutputStream
|
过滤处理
|
FilterReader
、
FilterWriter
|
FilterInputStream
、
FilterOutputStream
|
桥接处理
|
InputStreamReader
、
OutputStreamWriter
| |
对象序列化
处理
|
ObjectInputStream
、
ObjectOutputStream
| |
数据转换
|
DataInputStream
、
DataOutputStream
| |
行数统计
|
LineNumberReader
|
LineNumberInputStream
|
回滚处理
|
PushbackReader
|
PushbackInputStream
|
打印功能
|
PrintWriter
|
PrintStream
|
过滤流
就是
decorate
模式中的抽象装饰角色
FilterInputStream/FilterOutputStream
和
FilterReader/FilterWriter
所谓的过滤流实际上就是类似上面的加密处理,在输入之后(后置处理,被装饰对象先执行)或者输出之前(前置处理,先处理然后被装饰对象执行)进行一下额外的处理,最终实际操作是调用被装饰对象
的方法完成工作,依靠这种装饰模式实现在节点流的基础上附加额外功能
.
当然也允许多个过滤流嵌套从
而达到功能累加的目的
FilterInputStream
实际上就是一个装饰抽象角色
自定义流实现循环
13
加密
:
读取数据不变
:FileReader---BufferedReader
写出数据自定义过滤流
SecurityWriter(FilterWriter)
public class SecurityWriter extends FilterWriter {
protected SecurityWriter(Writer out) {
super(out);
}
public void write(int c) throws IOException {
if (c >= 'a' && c <= 'z') {
c = (c - 'a' + 13) % 26 + 'a';
} else if (c >= 'A' && c <= 'Z') {
c = (c - 'A' + 13) % 26 + 'A';
}
super.write(c);
}
}
public class SecurityReader extends FilterReader {
protected SecurityReader(Reader in) {
super(in);
}
public int read() throws IOException {
int c = super.read();
if (c >= 'a' && c <= 'z') {
c = (c - 'a' + 13) % 26 + 'a';
} else if (c >= 'A' && c <= 'Z') {
c = (c - 'A' + 13) % 26 + 'A';
}
return c;
}
}
桥接转换流
InputStreamReader
和
OutputStreamWriter
是
java.io
包中用于处理字符流的最基本的类,用来在字节流和字符流之间作为中介:从字节输入流读入字节,并按编码规范转换为字符;往字节输出流写字符时
先将字符按编码规范转换为字节。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,
以便把以字节方式表示的流转换为特定平台上的字符表示。
转换流可以在构造时指定其编码字符集
InputStreamReader
用于将一个
InputStream
类型的输入流自动转换为
Reader
字符流
OutputStreamWriter
用于将一个
Writer
字符输出流转换为
OutputStream
字节输出流
InputStreamReader构造器
- InputStreamReader(InputStream)
- InputStreamReader(InputStream, String)
- InputStreamReader(InputStream, Charset)
- InputStreamReader(InputStream, CharsetDecorder)
缓冲流
缓冲流是套接在响应的节点流之上,对续写的数据提供缓冲的功能,提高读写的效率,同时增加了一些新方法
以介质是硬盘为例,字节流和字符流的弊端:在每一次读写的时候,都会访问硬盘。 如果读写的频率比
较高的时候,其性能表现不佳。为了解决以上弊端,采用缓存流。
缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中读取。
InputStream is = new FileInputStream("d:\\FileTest.java");
long start = System.currentTimeMillis();
int con = is.read();while(con!=-1)
{
System.out.write(con);
con = is.read();
}
long end = System.currentTimeMillis();
is.close();
System.out.println("统计时间为:"+(end-start)+"ms");
构造方法
- BufferedReader(Reader)不定义缓存大小,默认8192
- BufferedReader(Reader in, int size)size为自定义缓冲区的大小
- BufferedWriter(Writer)
- BufferedWriter(Writer out, int size)size为自定义缓冲区的大小
- BufferedInputStream(InputStream)
- BufferedInputStream(InputStream in, int size)size为自定义缓冲区的大小
- BufferedOutputStream(OutputStream)
- BufferedOutputStream(OuputStream out, int size)size为自定义缓冲区的大小
缓冲输入流的方法
BuffedReader
提供了一个方法
readLine():String
,但是
BufferedInputStream
中并没有这个
- BufferedReader提供了readLine方法用于读取一行字符串,以\r或\n分割(换行符)
- 如果读取内容为null,则表示读取到了流的末尾
- readLine方法会自动剔除本行内容末尾的换行符
- BufferedWriter提供了newLine方法用于写入一个行分隔符
对于输出的缓冲流,写入的数据会先在内存中缓存,使用
flush
方法会使内存中的数据立即写出
数据流
DataInputStream
和
DataOutputStream
两个类创建的对象分别被称为数据输入流和数据输出流。这是很有用的两个流,它们允许程序按与机器无关的风格读写
Java
数据。所以比较适合于网络上的数据传
输。这两个流也是过滤器流,常以其它流如
InputStream
或
OutputStream
作为它们的输入或输出
DataInputStram
和
DataOutputStream
分别继承自
InputStream
和
OuputStream
,属于过滤流,需要分别套接在
InputStream
和
OutputStream
类型的节点流上
- 只有字节流,没有对应的字符流
DataInputStream
和
DataOutputStream
提供了可以存取与机器无关的
Java
原始类型数据的方法
DataInputSteram
和
DataOutputStream
构造方法为
- DataInputStream(InputStream)
- DataOutputStream(OutputStream)
打印流
PrintStream
和
PrintWriter
都属于输出流,分别针对字节和字符
PrintWriter
和
PrintStream
都提供了重载的
print
和
println
方法用于输出多种类型数据
print(Object):void
- 输出引用类型,实际上是调用对象的toString方法转换为String进行输出
public void println(Object x) {
String s = String.valueOf(x);//调用String类中的静态方法将object类型的 数据转换为字符串
synchronized (this) {
print(s);
newLine();//print('\n')
}
}
//String中的valueOf方法的定义
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();//如果输出对象非空,则调用对象的吗toString方法
}
println
表示输出后自动换行
- PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
- PrintWriter和PrintStream有自动的flush功能 textOut.flushBuffer();
PrintWriter(Writer)
PrintWriter(Writer out, boolean autoFlush)
自动刷新
----println
PrintWriter(OutputStream out) //参数是一个字节流,但是不需要通过桥接处理 PrintWriter(OutputStream out, boolean autoFlush)
PrintStream(OutputStream)
PrintStream(OutputStream out, boolean autoFlush)