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

---------------------- 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;
	}
	@Override
	public 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;
	}
	@Override
	public 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培训、期待与您交流! ---------------------- 

你可能感兴趣的:(黑马程序员-管道流-RandomAccessFile-DateInputStream-ByteArrayOutputStream-转换流-InputStreamReader)