天天看点

黑马程序员_JAVA_IO流2

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

序列化

要序列化的对象需要实现Serializable接口,Serializable接口没有方法,为标记接口。UID为类定义一个标示,只能序列化堆里的数据static修饰的数据不能被序列化,transient修饰的数据不能被序列化,保证数据存在在堆内存而不存在在文本文件中,可以自定义。 public static final long serialVersionUID = 42L; ObjectOutputStream ObjectInputStream 序列化对象 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt")); oss.writeObject(new Person("lili",23)); oss.close(); 读取序列化对象 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt")); Person p = (Person)ois.readObject(); ois.close();

管道流

PipeddInputStream和PipedOutputStream 输入输出可以直接进行连接,结合线程使用,不建议单线程,因为可能死锁 PipeddInputStream in = new PipeddInputStream(); PipedOutputStream out = new PipedOutputStream(); in.connect(out);//连接管道流

RandomAccessFile类

不属于IO体系的子类,直接继承object,但是是IO包中的成员,因为具备读写功能,该实例支持对随机文件的 读取和 写入。内部封装一个byte数组,通过指针对数组元素进行操作。可以通过getFilePointer获取指针的位置,通过seek改变指针的位置,内部封装了字节的输入流和输出流。

局限性:只能操作文件,而且操作文件有模式(r,rw),如果模式为只读r,不会创建文件,会读取已存在的文件,不存在,发生异常。模式为rw,要操作的文件不存在会自动创建,存在的话不覆盖。因为可以指定位置随机访问,所以可以实现多线程写入,多线程下载应用。

RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");//模式读写 raf.write("张三".getBytes()); raf.writeInt(97);写入四个字节 raf.wtite(97);写入一个字节

RandomAccessFile raf1 = new RandomAccessFile("fan.txt","r");//只读,屏蔽写的操作,new对象不覆盖

raf1.seek(8);//调整指针从角标为8的字节开始取 raf1.skipBytes(8);//跳过8个字节,不能往回跳

byte[] buf = new byte[4]; raf1.read(buf); String name = new String(buf); int age = raf1.readInt();//一次读四个字节,转换成int型

raf1.close();

DataInputStream和DataOutputStream

可以操作基本数据类型

DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));

	dos.writeInt();
	dos.writeBoolean();
	dos.writeDouble();

	dos.writeUTF("");//UTF-8修改版方法,只能用对应方法读取
	八个字节两个字符,UTF-8六个字节两个字符
	dos,close();

	DataInputStream dis = new DataInputStream(new FileInputStream("dos.txt"));
	dis.readInt();
	dis.readBoolean();
	dis.readDouble();

	dis.readUTF();
           

ByteArrayInputStream和ByteArrayOutputStream

在构造时需要接收数据源,一个字节数组。构造时不用定义数据目的,因为内部封装一个可变数组。因为流对象是操作数组,不涉及底层资源调用,不需抛异常,不用关闭且关闭无效。可变长度缓冲区,随数据写入不断增长。

ByteArrayInputStream bis = new ByteArrayInputStream("adk".getBytes());
	ByteArrayOutputStream bos = new ByteArrayOutputStream();

	int by = 0;
	while((by=bis.read())!=-1)
	{
	     bos.write(by);
	}

	bos.writeTo(new FileOutputStream("a.txt"));//将流写入到文件中
           

用流的思想操作数组

操作字符的数组流

CharArrayReader和CharArrayWriter

字符编码

常见码表 ACSII 美国标准信息交换码 用一个字节的7位表示

ISO8859-1 拉丁码表,欧洲码表 用一个字节的8位表示

GB2312 中国的中文编码表 GBK 中国的中文编码表升级,融合更多的中文字符

Unicode 国际标准码,融合了多种文字 用两个字节表示一个文字 UTF-8 最多用三个字节表示一个字符

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf-8"),"UTF-8");//UTF-8编码 InputStreamReader osr = new InputStreamReader(new FileInputStream("utf-8"),"gbk");//gbk解码

编码:字符串变成字节数组

String--->byte[]; str.getBytes();

解码:字节数组变成字符串

byte[]--->new String("".getBytes());

默认编码是GBK

String s = "你好"; Byte[] b1 = s.getByte("GBK");编码 String s1 = new String(b1,"UTF-8");解码

遇到乱码通用解决办法:编码再解码。如果两种码表都识别中文会出现错误。

String s = "你好"; Byte[] b1 = s.getByte("GBK");编码 String s1 = new String(b1,"iso8859-1");解码 Byte[] b2 = s1.getByte("iso8859-1"); String s2 = new String(b2,"GBK");解码

"联通"两字符输入记事本保存再打开会出现乱码 因为中文默认用的JBK编码表 但是"联通"两个字符的字符头恰好符合UTF-8的码表,所以会使用UTF-8码表解码

UTF-8识别编码字节数的头位:

字节1 0

字节1 110 字节2 10

字节1 1110 字节2 10 字节3 10