黑马程序员技术交流社区
标题:
IO part6
[打印本页]
作者:
fmi110
时间:
2015-8-10 18:08
标题:
IO part6
IO
4、序列流 SequenceInputStream
特点:可以将多个流合并成一个流,这样操作起来很方便
原理:其实就是将每一个读取流对象存储到一个集合,最后一个流对象结尾作为这个流的结尾
两个构造函数:
1 SequenceInputStream(InputStream in1,InputStream in2)
2 SequenceInputStream(Enumeration<? extends InputStream> e)
可以将枚举中的多个流合并成一个流
注意:因为 Enumeration 式 Vector 中特有的取出方式,而 Vector 被
ArrayList取代,所以要使用ArrayList集合效率更高一些。可通过如下方式获取
重写 Enumeration
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
//添加要合并的流
al.add(new FileInputStream("..."));
.....
Iterator<FileInputStream> it = al.iterator();
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
{
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};
//创建数据目的
FileOutputStream fos = new FileOutputStream("1.txt");
SequenceInputStream sin = new SequenceInputStream(en);
byte[] by = new byte[1024*1024];
int len;
while((len=sin.read())!=-1)
{
fos.write(by,0,len);
}
fos.close();
sis.close();
文件切割:将文件读入输入流,再传递给输出流,输出流将流内容分段输出到不同的文档即可。
5、 ObjectInputStream
ObjectOutputStream 通常这两个对象成对使用
可以通过这两个流对象直接操作已有的对象并对对象进行本地持久化存储。
存储后的对象可进行网络传输。
两个对象特有的方法:
ObjectInputStream
Object readObject(); 该方法抛出异常: ClassNotFoundException
ObjectOutputStream
void writeObject(Object);被写入的对象必须实现一个接口 Serializable
否则抛出异常: NotSerializableException
Serializable: 该接口其实就是一个没有方法的标记接口。
用于给类指定一个uid,该uid 是通过类中的可序列化成员的数字签名运算出来
的一个long型值。
只要这些成员发生变化,该值就会重新计算。
该值用于判断被序列化的对象和类文件是否兼容。(文件篡改检查)
如果被序列化的对象需要被不同的类版本所兼容,可以在类中自定义UID
定义方式: static final long serialVersionUID = 32L;
注意:对于静态的成员变量,不会被序列化。
对应的非静态成员也不想被序列化时,可以使用 关键字 transient 修饰
6、操作基本数据类型的流对象
DataInputStream(InputStream);
操作基本数据类型的方法:
int readInt(); 一次读取四个字节,并将其转换成int值
boolean readBoolean(); 一次读取一个字节
short readShort();
long readLong();
。。。。。。。
String readUTF();按照utf-8修改班读取字符。注意,它只能读writeUTF()写入的字符数据
DataOutputStream(OutputStream);
操作基本数据类型的方法;
writeInt(int); 一次写入四个字节
write(int); 一次只写入一个字节
writeBoolean(boolean);
。。。。。。。。
writeUTF(String); 按照utf-8修改版将字符数据进行存储。只能通过readUTF读取。
通常只要操作基本数据类型的数据。就需要通过 DataStram 进行包装。
操作数组的流对象。
1,操作字节数组
ByteArrayInputStream
ByteArrayOutputStream
toByteArray();
toString();
writeTo(OutputStream);
2,操作字符数组。
CharArrayReader
CharArrayWriter
对于这些流,源是内存。目的也是内存。
而且这些流并未调用系统资源。使用的就是内存中的数组。
所以这些在使用的时候不需要 close。
操作数组的读取流在构造时,必须要明确一个数据源。所以要传入相对应的数组。
对于操作数组的写入流,在构造函数可以使用空参数。因为它内置了一个可变长度数组
作为缓冲区。
编码转换:
在 io 中涉及到编码转换的流是转换流和打印流。
但是打印流只有输出。
在转换流中是可以指定编码表的。
默认情况下,都是本机默认的码表。GBK. 这个编码表怎么来的?
System.getProperty("file.encoding");
常见码表:
ASCII:美国标准信息交换码。使用的是 1 个字节的 7 位来表示该表中的字符。
ISO8859-1:拉丁码表。使用 1 个字节来表示。
GB2312:简体中文码表。
GBK:简体中文码表,比 GB2312 融入更多的中文文件和符号。
unicode:国际标准码表。都用两个字节表示一个字符。
UTF-8:对 unicode 进行优化,每一个字节都加入了标识头。
编码转换:
字符串 -->字节数组 :编码。通过 getBytes(charset);
字节数组-->字符串 : 解码。通过 String 类的构造函数完成。String(byte[],charset);
如果编错了,没救!
如果编对了,解错了,有可能还有救!
String s = "你好";
//编码。
byte[] b = s.getBytes("GBK");
//解码。
String s1 = new String(b,"iso8859-1");
System.out.println(s1);//????
/*
对 s1 先进行一次解码码表的编码。获取原字节数据。
然后在对原字节数据进行指定编码表的解码。
*/
byte[] b1 = s1.getBytes("iso8859-1");
String s2 = new String(b1,"gbk");
System.out.println(s2);//你好。
这种情况在 tomcat 服务器会出现。
因为 tomcat 服务器默认是 iso8859-1 的编码表。
所以客户端通过浏览器向服务端通过 get 提交方式提交中文数据时,
服务端获取到会使用 ISO8859-1 进行中文数据的解码。会出现乱码。
这时就必须要对获取的数据进行 iso8859-1 编码。然后在按照页面指定的编码表进行解
码即可
而对于 post 提交,这种方法也通用。但是 post 有更好的解决方式。
request.setCharacterEncoding("utf-8");即可。
所以建立客户端提交使用 post 提交方式
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2