黑马程序员-管道流-RandomAccessFile-DateInputStream-ByteArrayOutputStream-转换流-InputStreamReader

来源:互联网 发布:有道翻译无网络连接 编辑:程序博客网 时间:2024/09/21 06:35
---------------------- android培训、java培训、期待与您交流! ---------------------- 
IO包中的其他类(操作对象)
serializable
果某个类实现 以下两个接口,, 那么他们的序列化方式会有某种不同, 而真正来处理实现序列化的操作就是   ObjectInputStreamObjectOutputStream
interface Serializable    是 一个标记性接口,,实现该接口,则由JVM 自动实现, 实现类的 序列化和反序列化。
PipedInpStream和PipedOutputStream(管道流)
管道流的主要作用是可以进行两个线程之间的通信,分为管道输出流和管道输入流,如果想要进行管道输出,则必须把输出流连在输入流之上。
线程1->PipedOutputStream(输出流)|PipedInputStream(输入流)->线程2
要注意使用connect连接

PipedOutputStream PipedInputStream 连接起来就是一个管道,管道输出流可以向管道写入数据 管道输入流可以从管道读取数据这种Decorator 装饰 的设计模式 大大增强了java流的功能可以在构造流的时候连接 管道输入输出流 也可以通过connect函数连接

应用:
一个文件可以分为若干块,让不同的线程负责读写不同的快,(多线程下载)

练习代码:

public class PiedInputStreamDemo {public static void main(String[] args) {PipedInputStream pi  = new PipedInputStream();PipedOutputStream po = new PipedOutputStream();try {pi.connect(po);} catch (IOException e) {throw new RuntimeException("管道流连接异常");}Read read= new Read(pi);Write write = new Write(po);new Thread(read).start();new Thread(write).start();}}class Read extends Thread{PipedInputStream pi;Read(PipedInputStream pipi){this.pi = pipi;}@Overridepublic void run() {try {byte[] value = new byte[1024];int len = 0;len = pi.read(value);System.out.println(new String(value,0,len));} catch (Exception e) {throw new RuntimeException("管道流读取异常");}finally{try {pi.close();} catch (IOException e) {throw new RuntimeException("管道流关闭异常");}}}}class Write extends Thread{PipedOutputStream po;Write(PipedOutputStream pipo){this.po = pipo;}@Overridepublic void run() {try {po.write("管道流写入的数据.........".getBytes());} catch (IOException e) {throw new RuntimeException("管道流写入异常");}finally{try {po.close();} catch (IOException e) {throw new RuntimeException("管道流关闭异常");}}}}


RandomAccessFile
该类不算是IO体系中子类,而是直接继承自Object。但是它是IO包中成员,因为它具备读和写功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。
其实完成读写的原理就是内部封装了字节输入流和输出流。
通过构造函数可以看出,该类只能操作文件,而且操作文件还有模式:只读r,读写rw;
如果模式为只读r。不会创建文件,会去读取一个已存在的文件,如果该文件不存在,则会出现异常。
如果模式为rw。操作的文件不存在,会自动创建,如果存在,则不覆盖。
public class RandomAccessDemo {static File file = new File("RandomAccessFileTest.txt");public static void main(String[] args) {method_1();method_2();}public static void method_1(){RandomAccessFile raf = null;try {raf = new RandomAccessFile(file, "rw");raf.write("张三".getBytes());//写入一个字节,也就是8位二进制数,不能完全保留数据//raf.write(69);//按四个字节将 int 写入该文件,先写高字节raf.writeInt(69);raf.write("李四".getBytes());raf.writeInt(23);} catch (FileNotFoundException e) {throw new RuntimeException("随机读取流创建失败");}catch(IOException ex){throw new RuntimeException("读取写入数据异常");}finally{if(raf != null)try {raf.close();} catch (IOException e) {throw new RuntimeException("随机读取流关闭异常");}}}public static void method_2(){RandomAccessFile raf = null;try {raf = new RandomAccessFile(file, "r");byte[] value = new byte[4];//设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。raf.seek(8);//尝试跳过输入的 n 个字节以丢弃跳过的字节。//raf.skipBytes(8);raf.read(value);System.out.println("name=" + new String(value));//再次调用read()指针会自增System.out.println("age=" + raf.readInt());} catch (Exception e) {throw new RuntimeException("随机读文件流异常");}finally{if(raf != null){try {raf.close();} catch (IOException e) {throw new RuntimeException("随机读取流关闭异常");}}}}}


DateInputStream DateOutputStream
可以用于操作基本数据类型的数据的对象 
练习代码:
/* *可以操作基本数据类型的对象 */public class DateStreamDemo {public static void main(String[] args) {write_1();read_1();writeUTF();readUTF();}public static void write_1(){DataOutputStream dato = null;try {dato = new DataOutputStream(new FileOutputStream("DataOutputStream.txt"));dato.write(234);dato.writeBoolean(true);dato.writeDouble(2.654);} catch (Exception e) {throw new RuntimeException("数据流异常");}finally{if(dato != null){try {dato.close();} catch (IOException e) {throw new RuntimeException("数据流关闭异常");}}}}public static void read_1(){DataInputStream dis = null;try {dis = new DataInputStream(new FileInputStream("DataOutputStream.txt"));int num =dis.read();boolean b = dis.readBoolean();double d = dis.readDouble();System.out.println("num=" + num+ "\nboolean=" + b + "\ndouble=" + d);} catch (Exception e) {throw new RuntimeException("数据流读取异常");}finally{if(dis != null){try {dis.close();} catch (IOException e) {throw new RuntimeException("数据读取流关闭异常");}}}}public static void writeUTF(){DataOutputStream dos = null;try {dos = new DataOutputStream(new FileOutputStream("UTF.txt"));dos.writeUTF("你好");//用这种方法写入的数据只能用DataInputStream对象读取
} catch (Exception e) {throw new RuntimeException("数据写入流异常");}finally{if(dos != null){try {dos.close();} catch (IOException e) {throw new RuntimeException("数据写入流关闭异常");}}}}public static void readUTF(){DataInputStream dis = null;try{dis = new DataInputStream(new FileInputStream("UTF.txt"));System.out.println(dis.readUTF());}catch(IOException e){throw new RuntimeException("数据读取流异常");}finally{if(dis != null){try {dis.close();} catch (IOException e) {throw new RuntimeException("数据读取流关闭异常");}}}}}


ByteArrayOutputStream(操作字节数组)
ByteArrayInputStream:在构造的时候,需要接受数据源,而且数据源是一个字节数组。
ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可以改变长度的字节数组。这就是数据目的地。
因为这两个流对象都操作数组,并没有使用系统资源。所以,不用进行close关闭。
在流操作规律讲解时:
源设备
  • 键盘 System.in,硬盘 FileStream,内存 ArrayStream
目的设备
  • 控制台 System.out,硬盘 FileStream,内存 ArrayStream
同理
  • CharArrayReader与CharArrayWrite(操作字符数组)
  • StringReader与StringWrite(操作字符串)
都是以内存为目的和源的操作
练习代码:
public class ByteArrayStreamDemo { public static void main(String[] args) {//ByteArrayInputStream 是InputStream的子类,所以可以调用父类的方法ByteArrayInputStream bin = new ByteArrayInputStream("hello world!".getBytes());ByteArrayOutputStream bot = new ByteArrayOutputStream();int i = 0;while((i = bin.read()) != -1){bot.write(i);}System.out.println(bot.size());System.out.println(bot.toString());}}


转换流的字符编码
字符流的出现为了方便操作字符
更重要的是加入了编码转换
通过子类转换流来完成
  • InputStreamReader
  • OutputStreamWriter
在两个对象进行构造的时候可以加入字符集

编码表的由来
  • 计算机只能识别二进制数据,早起留来是电信号
  • 为了方便应用计算机,让他可以识别各个国家的文字。
  • 就将各个国家的文字用数字来表示,并一一对应,形成一张表。
  • 这就是编码表
常见的编码表
  1. ASCII:美国标准信息交换码。用一个字节的7位可以表示。
  2. ISO8859-1:拉丁码表。欧洲码表。用一个字节的8位表示。
  3. GB2312:中国的中文编码表。
  4. GBK:中国的中文编码表升级,融合了更多的中文文字符号。
  5. Unicode:国际标准码,融合了多种文字。所以文字都用两个字节来表示,java语言使用的就是Unicode
  6. UTF-8:最多用三个字节来表示一个字符。
  7. ......
编码:字符串变成字节数组
解码:直接数组变成光字符串。
String-->byte[]:str.getBytes(charsetName);
byte[] -->String:new String(byte[],charsetName);
练习代码:
public class EncodeDemo {public static void main(String[] args) {method_1();encode();}public static void method_1(){OutputStreamWriter outw = null;try {//指定编码格式outw = new OutputStreamWriter(new FileOutputStream("utf.txt"),"utf-8");outw.write("你好");//outw.flush();} catch (Exception e) {// TODO: handle exception}finally{if(outw != null){try {outw.close();} catch (IOException e) {throw new RuntimeException("转换写入流关闭异常");}}}}//编码:字符串变成字节数组//解码:直接数组变成光字符串。//String-->byte[]:str.getBytes(charsetName);//byte[] -->String:new String(byte[],charsetName);public static void encode (){String s = "你好";try {byte[] value = s.getBytes("gbk");System.out.println(Arrays.toString(value));System.out.println(new String(value,"gbk"));//如果出现解码错误,需要用解码的格式编码后解码String str = new String(value,"ISO8859-1");System.out.println(str);byte[] temp = str.getBytes("ISO8859-1");System.out.println(Arrays.toString(temp));System.out.println(new String(temp,"gbk"));} catch (UnsupportedEncodingException e) {throw new RuntimeException("编码异常");}}}


字符编码-联通
---------------------- android培训、java培训、期待与您交流! ---------------------- 

0 1
原创粉丝点击