学号20145306 《Java程序设计》第6周学习总结
教材学习内容总结
第十章 一 InputStream与OutputStream
串流设计的概念 Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象。数据就好比水,串流就像水管,通过水管的衔接,水由一端流向另一端。从应用程序角度来看,若要将数据从来源取出,可以使用输入串流,要将数据写入目的地,可以使用输出串流。在Java中,输入串流代表对象为java.io.InputStream实例,输出串流代表对象为java.io.OutputStream实例。无论数据源和目的为何,只要取的InputStream或者OutputStream的实例,操作输入输出的方法是一致的。 设计一个通用的dump()方法: import java.io.*;
public class IO {
public static void dump(InputStram src,OutputStream dest) throws IOException{
try (InputStram input = src;OutputStream output = dest) {
byte[] data = new byte[1024];
int length;
while ((length = input.read(data)!= -1) {
output.write(data,0,length);
}
}
}
}
dump()方法接受InputStream与OutputStream的实例,分别代表读取数据的来源,以及输出数据的目的地。在进行InputStream与OutputStream的相关操作时若发生错误,会抛出java.io.IOException异常,在这里不特别处理,而是在dump()方法上声明throws,由调用dump()方法的客户端处理。在不使用InputStream与OutputStream时,必须使用close()方法关闭串流,由于InputStream与OutputStream操作了java.io.Closeable接口,其父接口为java.lang.AutoCloseable接口,因此可使用JDK7尝试自动关闭资源语法。每次从InputStream读入的数据,都会置入byte数组中,InputStream的read()方法每次会尝试读入byte数组长度的数据,并返回实际读入的字节,只要不是-1,就表示读取到数据,可以使用OutputStream的write()方法,指定要写出的byte数组、初始索引与数据长度。
书上虽然没有正式介绍到网络程序设计,不过java.net.URL的使用很简单,只要指定网址,URL实例会自动进行HTTP协议,可以使用openStream方法取得InputStream实例,代表与网站连接的数据串流。
串流继承架构
System.in与System.out它们分别是InputStream与PrintStream的实例,分别代表标准输入与标准输出,以个人计算机而言,通常对应至文本模式中的输入与输出。
可以使用System的setIn()方法指定InputStream实例,重新指定标准输入来源。
System的setOut()方法指定PrintStream实例,将结果输出至指定的目的地。
import java.io.*;
public class StandarOut{
public static void main (String[] args) throws IOException {
try (PrintStream printStream = new PrintStream(new FileOutputStream(args[0]))) {
System.out.printf("helloWorld");
}
}
}
PrintStream接受InputStream实例,在这个范例中用PrintStream打包FileOutputStream,你操作PrintStream相关方法,PrintStream会代你操作FileOutputStream。除了System.in与System.out之外,还有个System.err为PrintStream实例,称为标准错误输入串流,它是用来立即显示错误信息的。
FileInputStream与FileOutputStream
FileInputStream是InputStream的子类,可以指定文件名创建实例,一旦创建文档就开启,接着就可以用来读取数据,FileOutputStream是OutputStream的子类,可以指定文件名创建实例,一旦创建文档就开启,接着就可以用来写出数据,无论FileInputStream还是FileOutputStream,不使用时都要用close()关闭文档。
ByteArrayInputStream与ByteArrayOutputStream
ByteArrayInputStream是InputStream的子类,可指定byte数组创建实例。一旦创建就可以将byte数组当作数据源进行读取。ByteArrayOutputStream是OutputStream的子类,可指定byte数组创建实例。一旦创建就可以将byte数组当作目的地写出数据。
串流处理装饰器
InputStream、OutputStream提供串流基本操作,如果想要为输入/输出的数据做加工处理,则可以使用打包器类。前面示范过的Scanner类就是作为打包器,其接受InputStream实例,你操作Scanner打包器相关方法,Scanner会实际操作打包的InputStream取得数据,并转换为你想要的数据类型。InputStream、OutputStream的一些子类也具有打包器的作用。前面介绍的PrintStream就是实际例子,你操作PrintStream的print()、println()等方法,PrintStream会自动转换为byte数组数据,利用打包的OutputStream进行输出。下面介绍几种常用的串流装饰器类。第一种BufferedInputStream与BufferedOutputStream,两者都具备缓冲作用。如果InputStream第一次read()时可以尽量读取足够的数据至内存的缓冲区,后续调用read()时先看看缓冲区是不是还有数据,如果有就从缓冲区读取,没有再从来源读取数据至缓冲区,这样减少从来源直接读取数据的次数,对读取效率将会有帮助。毕竟内存的访问速度较快。如果OutputStream每次write()时可将数据写入内存中的缓冲区,缓冲区满了再将缓冲区的数据写入目的地,这样可减少对目的地的写入次数,对写入效率也会有帮助。第二种是DataInputStream与DataOutputStream,DataInputStream与DataOutputStream提供读取、写入Java基本数据类型的方法,像是读写int、double、boolean等的方法。这些方法会自动在指定的类型与字节间转换。第三种是ObjectInputStream与ObjectOutputStream,ObjectInputStream与ObjectOutputStream可以将内存中的对象整个储存下来,之后再读入还原为对象。ObjectInputStream提供readObject()方法将数据读入为对象,而ObjectOutputStream提供writeObject()方法将对象写至目的地,可以被这两个方法处理的对象,必须操作java.io.Serializable接口,这个接口并没有定义任何方法,只是作为标示之用,表示这个对象是可以串行化的。如果在做对象串行化时,对象中某些数据成员不希望被写出,则可以标上transient关键字。
字符处理类 Reader与Writer继承架构 针对字符数据的读取,Java SE提供了java.io.Reader类,其抽象化了字符数据读入的来源,针对字符数据的写入,则提供了java.io.Writer类,其抽象化了数据写出的目的地。在不使用Reader与Writer时,必须使用close()方法关闭串流。Reader与Writer操作了Closeable接口,其父接口为AutoCloseable接口,因此可使用JDK7尝试自动关闭资源语法。StringReader可以将字符串打包,当作读取来源,StringWriter则可以作为写入目的地,最后用toString()取得所有写入的字符组成的字符串。在启动JVM时,可以用-Dfile.encoding来指定FileReader、FileWriter所使用的编码。
2.字符处理装饰器
如果串流处理的字节数据,实际上代表某些字符的编码数据,而你想要将这些字节数据转换为对应的编码字符,可以使用InputStreamReader、OutputStreamWriter对串流数据打包,在建立InputStreamReader与OutputStreamWriter时,可以指定编码,如果没有指定编码,则以JVM启动时所获取的默认编码来做字符转换。PrintStream与PrintWriter使用上极为相似,不过除了可以对OutputStream打包之外,PrintWriter还可以对Writer进行打包,提供print()、println()、format()等方法。