java学习笔记Day8:流

1.流

1.1文件

1.1.1定义

相关记录或放在一起的数据的集合

1.1.2存储的位置

硬盘

1.1.3持久化

把数据存入硬盘这个行为,我们把他称之为持久化,而程序的执行,是在内存当中完成的,需要把数据从硬盘读到内存当中,再来执行

1.1.4文件的分类

① 目录:目录的本质上也是一种文件
② 文件:文件是用来保存数据的主体,但是没有谁规定,文件一定要有后缀。

//File是用来描述文件的一种对象
File f = new File("D:\\斌斌和阿玲不得不说的故事.txt");
System.out.println(f.exists());//文件不存在则返回false
System.out.println(f.isFile());//true
System.out.println(f.isDirectory());//false
System.out.println("-----------------------------");
File f1 = new File("D:\\ioTestDir");
System.out.println(f1.exists());//文件存在的时候,返回true
System.out.println(f1.isFile());//false
System.out.println(f1.isDirectory());//true
1.1.5路径的正确表达方式:

① \:这种斜杠需要转义\
② /:这个可以直接用

1.1.6 File:new出来的对象

只是一个对象,可以new,但是并不意味着一定存在

方法名称说明
boolean exists( )判断文件或目录是否存在
boolean isFile( )判断是否是文件
boolean isDirectory( )判断是否是目录
String getPath( )返回此对象表示的文件的相对路径名
String getAbsolutePath( )返回此对象表示的文件的绝对路径名
String getName( )返回此对象表示的文件或目录的名称
boolean delete( )删除此对象指定的文件或目录
boolean createNewFile( )创建名称的空文件,不创建文件夹
long length()返回文件的长度,单位为字节,如果文件不存在,则返回0L
1.1.7路径操作

① 绝对路径:从根目录往后找,叫绝对路径
② 相对路径:以当前文件所在的位置,作为参照,开始寻找目标
③ getPath:你给他相对路径,他就是相对路径,你给他绝对路径,那就是绝对路径
④ getAbsolutePath:获取的是绝对路径,但是,是识别不了.和…/的
⑤ getCanonicalPath:效果和getAbsolutePath类似,但是可以识别.和…/的

File f = new File("../Test1.class");
File f1 = new File("D:\\ioTestDir");
//System.out.println(f.exists());
System.out.println(f.getPath());
System.out.println(f1.getPath());
System.out.println("---------------");
System.out.println(f.getAbsolutePath());
System.out.println(new File(f.getAbsolutePath()).exists());
System.out.println("----------------");
System.out.println(f.getCanonicalPath());
1.1.8创建文件和目录
File f = new File("D:\\ioTestDir\\斌斌的故事");
    f = new File(f.getCanonicalPath());
    System.out.println(f);
    if(!f.exists()){
        boolean r = f.createNewFile();
        System.out.println(r?"文件创建成功":"文件创建失败");
 }
public static void main(String[] args) throws Exception {
//		File f = new File("D:\\ioTestDir\\childDir");
		File f = new File("D:\\ioTestDir\\childDir\\c1\\c2\\c1");
		if(!f.exists()){
//			boolean r = f.mkdir();//只会创建当前目录,如果父目录不存在,则报错
			boolean r = f.mkdirs();//会创建当前目录,如果父目录不存在,则一并创建
			System.out.println(r?"success":"error");
		}
}
1.1.9获取文件和目录
File f = new File("D:\\ioTestDir\\斌斌和阿玲不得不说的故事.txt");
if(f.exists()){
    long length = f.length();//获取文件的字节数
    System.out.println(length);
}

File f = new File("D:\\ioTestDir");
//获取的是儿子辈
String[] list = f.list();//获取所有子文件和子目录的绝对路径名
File[] files = f.listFiles();//获取所有的子文件和子目录
//获取父亲辈
String parent = f.getParent();//获取父目录的绝对路径
File parentFile = f.getParentFile();//获取父路径的文件对象

1.2文件的读写

1.2.1如何读写文件?

通过流来读写文件:

① 流是一组有序的数据序列
② 以先进先出方式发送信息的通道

1.2.2流的分类
1.2.2.1按流向区分:输入流/输出流(I/O)

① Input:以当前程序为参照,从程序外往程序里读叫输入流,Iutputstream和Reader作为基类
② Output:以当前程序为参照,往外写叫输出流,OutputStream和Writer作为基类
③输入输出流是相对于计算机内存来说的

1.2.2.2按照处理数据单元划分
1.2.2.2.1字节流:读写的是byte

字节输入流InputStream基类:必须掌握
① 可以一个字节一个字节的读
② 读的字节,不会超过byte的长度
③ 读字节对文件大小没有限制

InputStream类常用方法

  • int read( )
  • int read(byte[] b)
  • int read(byte[] b,int off,int len)
  • void close( )
  • int available():可以从输入流中读取的字节数目

子类FileInputStream常用的构造方法

  • FileInputStream(File file)
  • FileInputStream(String name)

使用FileInputStream 读文本文件

public static void main(String[] args) {
File f = new File("D:\\ioTestDir\\斌斌和阿玲不得不说的故事.txt");
InputStream in = null;		
try{
    if(!f.exists()){
        throw new Exception("文件不存在");
    }
    in = new FileInputStream(f);
    //the next byte of data, or -1 if the end of thestream is reached.
    byte[] bs = new byte[in.available()];//获取当前流当中,该文件可读字节数
    //			in.read(bs);//通过对地址的访问,直接把读取的字节码保存到指定数组中
        byte b = -1;
        int index = 0;	
        while((b = (byte)in.read()) != -1){
            bs[index++] = b;
        }	
        String str = new String(bs);	
        System.out.println(str);
    }catch(Exception e){
        e.printStackTrace();
    }finally{
        if(in != null){
            try {
                in.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

字节输出流OutStream基类:必须掌握
① 可以一个字节一个字节的往外写
② 需要首先获取数据的字节码
③ 输出流是覆盖,不是追加

OutputStream类常用方法

  • void write(int c)
  • void write(byte[] buf)
  • void write(byte[] b,int off,int len)
  • void close()
  • void flush():强制把缓冲区的数据写到输出流中

子类FileOutputStream常用的构造方法

  • FileOutputStream (File file)
  • FileOutputStream(String name)
  • FileOutputStream(String name,boolean append)
  • 注意:1、前两种构造方法在向文件写数据时将覆盖文件中原有的内容。2、创建FileOutputStream实例时,如果相应的文件并不存在,则会自动创建一个空的文件
public static void main(String[] args) {
		File f = new File("D:\\ioTestDir\\斌斌和阿玲不得不说的故事.txt");
		String str = "第一章\r\n那一天,他和她……\r\n自己脑补";
		//输出流
		OutputStream out = null;
		try {
			if(!f.exists()){
				f.createNewFile();
			}
			out = new FileOutputStream(f);
			byte[] bs = str.getBytes();
//			for(byte b : bs){
//				out.write(b);
//			}	
			out.write(bs);			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			if(out != null)
				try {
					out.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
	}
1.2.2.2.2字符流:读写的是char

字符输入流Reader基类

  1. 字符流读取,不可以直接使用inputstring的读取长度,因为我们读取的是char类型

Reader类常用方法

  • int read( )
  • int read(char[] c)
  • read(char[] c,int off,int len)
  • void close( )

子类InputStreamReader常用的构造方法

  • InputStreamReader(InputStream in)
  • InputStreamReader(InputStream in,String charsetName)
public static void main(String[] args) {
		File f = new File("D:\\ioTestDir\\斌斌和阿玲不得不说的故事.txt");
		Reader in = null;	
		try{
			if(!f.exists()){
				throw new Exception("文件不存在");
			}
			in = new InputStreamReader(new FileInputStream(f));
			StringBuffer sbf = new StringBuffer();
			int item = -1;
			while((item = in.read()) != -1){
				char c = (char)item;
				sbf.append(c);
			}
			System.out.println(sbf.toString());	
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

FileReader类是InputStreamReader的子类

  • FileReader(File file)
  • FileReader(String name)
  • 该类只能按照本地平台的字符编码来读取数据,用户不能指定其他的字符编码类型
  • System.out.println(System.getProperty(“file.encoding”)); 获得本地平台的字符编码类型

字符输出流Writer基类

  1. 一个字符有若干字节组成,所以自带缓冲区,需要调用flush

字节流是 8 位通用字节流,字符流是 16 位 Unicode 字符流

Writer类常用方法

  • write(String str)
  • write(String str,int off,int len)
  • void close()
  • void flush()

子类OutputStreamWriter常用的构造方法

  • OutputStreamWriter(OutputStream out)
  • OutputStreamWriter(OutputStream out,String charsetName)
public static void main(String[] args) {
    File f = new File("D:\\ioTestDir\\斌斌和阿玲不得不说的故事.txt");
    String str = "第一章\r\n那一天,他和她……\r\n自己脑补";
    Writer out = null;
    //输出流
    try {
        if(!f.exists()){
            f.createNewFile();
        }
        out = new OutputStreamWriter(new FileOutputStream(f));
//			for(char c : str.toCharArray()){
//				out.write(c);
//			}
        out.write(str);
        out.flush();//字符流的输出流,自带缓冲区
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally{
        if(out != null)
            try {
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }
}

FileWriter类是OutputStreamWriter的子类

  • FileWriter (File file)
  • FileWriter (String name)
  • 该类只能按照本地平台的字符编码来写数据,用户不能指定其他的字符编码类型
1.2.2.1缓冲流:带缓冲的流
1.2.2.1.1字节流的缓冲流

① 默认缓冲区大小:8192B
② 只要是缓冲流,必须调用flush,一般来说针对输出流

public static void main(String[] args) {
		File f = new File("D:\\ioTestDir\\斌斌和阿玲不得不说的故事.txt");
		InputStream in = null;	
		try{
			if(!f.exists()){
				throw new Exception("文件不存在");
			}
			in = new BufferedInputStream(new FileInputStream(f)); //缓冲输入字节流
			//the next byte of data, or -1 if the end of thestream is reached.
			byte[] bs = new byte[in.available()];//获取当前流当中,该文件可读字节数
//			in.read(bs);//通过对地址的访问,直接把读取的字节码保存到指定数组中	
			byte b = -1;
			int index = 0;	
			while((b = (byte)in.read()) != -1){
				bs[index++] = b;
			}
			String str = new String(bs);		
			System.out.println(str);		
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
public static void main(String[] args) {
    File f = new File("D:\\ioTestDir\\斌斌和阿玲不得不说的故事.txt");
    String str = "第一章\r\n那一天,他和她……\r\n自己脑补";
    //输出流
    OutputStream out = null;
    try {
        if(!f.exists()){
            f.createNewFile();
        }
        out = new BufferedOutputStream(new FileOutputStream(f));//缓冲输出字节流
        byte[] bs = str.getBytes();
        out.write(bs);
        out.flush();//清空缓冲区
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally{
        if(out != null)
            try {
                out.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }
}
1.2.2.1.2缓冲字符流
  1. 输出流:因为有非常优秀的缓冲取,所以不需要考虑一个字符一个字符往外写,直接写,交给缓冲区处理,缓冲区大小8192个char(int)

如何提高字符流写文本文件的效率?

  • 使用FileWriter类与BufferedWriter类

BufferedWriter常用的构造方法

  • BufferedWriter(Writer out)

使用 BufferedWriter 写文件

public static void main(String[] args) {
		File f = new File("D:\\ioTestDir\\斌斌和阿玲不得不说的故事.txt");
		String str = "第一章\r\n那一天,他和她……\r\n自己脑补";
		BufferedWriter out = null;
		//输出流
		try {
			if(!f.exists()){
				f.createNewFile();
			}
			out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
			out.write(str);
			out.flush();//字符流的输出流,自带缓冲区
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			if(out != null)
				try {
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
	}
  1. 输入流:可以一行一行的读

如何提高字符流写文本文件的效率?

  • 使用FileReader类与BufferedReader类

BufferedReader常用的构造方法

  • BufferedReader(Reader in)
  • 子类BufferedReader特有的方法
  • readLine()

使用 BufferedReader读文本文件

public static void main(String[] args) {
    File f = new File("D:\\ioTestDir\\斌斌和阿玲不得不说的故事.txt");
    BufferedReader in = null;	
    try{
        if(!f.exists()){
            throw new Exception("文件不存在");
        }
        in = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
    String line = "";
    while((line = in.readLine()) != null){
        System.out.println(line);
    }
	}catch(Exception e){
		e.printStackTrace();
	}finally{
		if(in != null){
			try {
				in.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
1.2.2.4二进制流

① 作用,是读写数据
② 读和写的顺序需要保持一致

DataInputStream类

  • FileInputStream的子类
  • 与FileInputStream类结合使用读取二进制文件
public static void main(String[] args) {
		File f = new File("D:\\ioTestDir\\objtest.obj");
		DataInputStream in = null;
		try{
			in = new DataInputStream(new FileInputStream(f));
			int id = in.readInt();
			System.out.println(id);
			String name = in.readUTF();
			System.out.println(name);
			int age = in.readInt();
			System.out.println(age);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

DataOutputStream类

  • FileOutputStream的子类
  • 与FileOutputStream类结合使用写二进制文件
public static void main(String[] args) {
		File f = new File("D:\\ioTestDir\\objtest.obj");
		DataOutputStream out = null;
		try{
			if(!f.exists()){
				f.createNewFile();
			}
			out = new DataOutputStream(new FileOutputStream(f));
			out.writeInt(1);
			out.writeUTF("斌斌");
			out.writeInt(18);
			out.flush();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(out != null){
				try {
					out.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
1.2.2.5序列化和反序列化

① 序列化:把内存中的对象,变为二进制的字节流输出

public class Person implements Serializable{
/**
 * 
 */
private static final long serialVersionUID = 1724067472155516781L;

private Integer id;
private String name;
private Integer age;
private Dog dog;
public Integer getId() {
	return id;
}
public void setId(Integer id) {
	this.id = id;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public Integer getAge() {
	return age;
}
public void setAge(Integer age) {
	this.age = age;
}
public Dog getDog() {
	return dog;
}
public void setDog(Dog dog) {
	this.dog = dog;
}
@Override
public String toString() {
	return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
public static void main(String[] args) {
		File f = new File("D:\\ioTestDir\\objtest2.obj");
		Person p = new Person();
		p.setId(1);
		p.setName("ybb");
		p.setAge(18);
		p.setDog(new Dog());
		//序列化
		ObjectOutputStream out = null;
		try{
			if(!f.exists()){
				f.createNewFile();
			}
			out = new ObjectOutputStream(new FileOutputStream(f));
			out.writeObject(p);
			out.flush();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(out != null){
				try {
					out.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}	
	}

② 反序列化:把二进制流的输入,变为对象

public static void main(String[] args) {
		File f = new File("D:\\ioTestDir\\objtest2.obj");
		//反序列化
		ObjectInputStream in = null;
		try{
			in = new ObjectInputStream(new FileInputStream(f));
			Object obj = in.readObject();
			if(obj instanceof Person){
				Person p = (Person)obj;
				System.out.println(p);
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}	
	}

③ 序列化的第一步,是需要制定对象为可序列化对象,以及该类的所有类成员都必须为可序列化对象
④ 序列化的版本ID,在序列化和反序列化时必须保持一致
⑤JDK自带的序列化和反序列化,效果不佳,在真正的大型分布式项目当中,一般使用例如:hessian(jboss)

3.1输入流的本质与缓冲区

3.1.1 I/O流的体系

在这里插入图片描述

3.1.2输入流
public class Test1 {

	public static void main(String[] args) {
		//输入流
		//字节流
		InputStream in1;
		FileInputStream in2;
		FilterInputStream in1;
		ByteArrayInputStream in4;
		BufferedInputStream in5;//缓冲
		DataInputStream in6;//读写的数据是固定长度
		//字符流
		Reader r1;//本质上读取的就是一个char数组
		InputStreamReader r2;//这个类,只是在负责字符集的解码工作

//		StreamDecoder r1;//字符集的解码工作具体是由这个类来完成的
//		new InputStreamReader(new FileInputStream(new File("")),"utf-8");//字符集的解码工作,因为在输出流输出时是已该编码完成的
		BufferedReader r1;//缓冲
		

	}

}
//这个是可以扩展的,不存在读取的上限,当缓冲区用完了,会扩展一倍
class MyBufferedInputStream extends MyFilterInputStream{
	private static int DEFAULT_BUFFER_SIZE = 8192;//缓冲大小
	private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;//最大缓冲区大小
	protected byte buf[];
	protected int count;//上限
	protected int pos;
	public MyBufferedInputStream(MyInputStream in) {//默认长度
		this(in,DEFAULT_BUFFER_SIZE);
	}
	public MyBufferedInputStream(MyInputStream in ,  int size) {//指定长度的
		super(in);
		buf = new byte[size];
	}
	

	public synchronized int read() throws IOException {
	    if (pos >= count) {
	        fill();//扩展缓冲
	        if (pos >= count)
	            return -1;
	    }
	    return getBufIfOpen()[pos++];
	}
	
	private byte[] getBufIfOpen() throws IOException {
	    byte[] buffer = buf;
	    return buffer;
	}
	
	private void fill() throws IOException {
		//检查还有多少没读
		//1.读完了
		//2.没读完
			//剩下来的要么扩展一倍,要么就是MAX_BUFFER_SIZE

//		pos = 0; 
		//newSize
		int nsz = (pos <= MAX_BUFFER_SIZE - pos) ? pos * 2 : MAX_BUFFER_SIZE;
		byte nbuf[] = new byte[nsz];
		count = nbuf.length - pos;
	}
	public synchronized int available() throws IOException {
        int n = count - pos;
        return n;
    }
	public void close() throws IOException {
        MyInputStream input = super.in;
        if (input != null)
            input.close();
        return;
    }
}

//字节数组输入流:这是一个线程安全的字节数组输入流
class MyByteArrayInputStream extends MyInputStream{
	protected byte buf[];
	protected int pos;
	protected int count;
	

	public MyByteArrayInputStream(byte[] buf){
		this.buf = buf;
	    this.pos = 0;
	    this.count = buf.length;
	}
	
	public synchronized int read() throws IOException {
		// TODO Auto-generated method stub
		return buf[pos++];
	}
	
	public synchronized int available() {
	    return count - pos;
	}
	
	public void close() throws IOException {
	}

}


//其实啥也没干
class MyFilterInputStream extends MyInputStream{
	protected MyInputStream in;
	

	public MyFilterInputStream(MyInputStream in){
		this.in = in;
	}
	
	public int read() throws IOException {
	    return in.read();
	}
	
	public int read(byte b[]) throws IOException {
	    return read(b, 0, b.length);
	}
	
	public int read(byte b[], int off, int len) throws IOException {
	    return in.read(b, off, len);
	}
	
	public int available() throws IOException {
	    return in.available();
	}
	
	public void close() throws IOException {
	    in.close();
	}

}

//file的读取,是有本地调用来实现的
class MyFileInputStream extends MyInputStream{
	@Override
	public int read() throws IOException {
		// TODO Auto-generated method stub
		return read0();
	}
	//本地调用:这个代码是不开源的
	private native int read0() throws IOException;
	//本地调用
	public native int available() throws IOException;
	//重写了close
	private FileChannel channel = null;
	public void close() throws IOException {
        if (channel != null) {
           channel.close();
        }
	}
}


abstract class MyInputStream{
	//在于该方法到底如何读取数据的
	public abstract int read() throws IOException;//这是个抽象方法
	public int read(byte b[]) throws IOException {//从偏移量0开始,读所有
        return read(b, 0, b.length);
    }
	public int read(byte b[], int off, int len) throws IOException {
		//读第一个
        int c = -1;
        for (int i= 0 ; i < len ; i++) {
            c = read();
            if (c == -1) {
                break;
            }
            b[off + i] = (byte)c;
        }
		return -1;
	}
	public int available() throws IOException {
        return 0;
    }
	public void close() throws IOException {
		

	}

}
3.1.3输出流
public class Test2 {

	public static void main(String[] args) {
		//输出流
		//字节流
		OutputStream out1;
		FileOutputStream out2;
		FilterOutputStream out1;
		ByteArrayOutputStream out4;
		BufferedOutputStream out5;//缓冲
		DataOutputStream out6;
		//字符流
		Writer w1;
		OutputStreamWriter w2;//主要任务就是负责字符集的编码工作
		//StreamEncoder:实际完成编码,
		BufferedWriter w1;//缓冲
	}

}

//完整的执行过程是:
//缓冲始终没有大于过8192的时候,这个时候,是没有真正往外写的
//往外写的两种情况:
	//1.手动调用了flush
	//2.缓冲满了一次,满的这一次数组里的东西往外写,但是最后剩余的部分,如果不调用flush,则会丢失
class MyBufferedOutputStream extends MyFilterOutputStream{
	protected byte buf[];
	protected int count;
	public MyBufferedOutputStream(MyOutputStream out ){
		this(out,8192);
	}
	public MyBufferedOutputStream(MyOutputStream out , int size){
		super(out);
		buf = new byte[size];
		count = buf.length;
	}
	//所谓的写,是在往buf数组当中添加内容
	//写完了缓冲的长度以后, flushBuffer();
	public synchronized void write(int b) throws IOException {
        if (count >= buf.length) {
            flushBuffer();
        }
        buf[count++] = (byte)b;
    }
	//真正开始写
	private void flushBuffer() throws IOException {
        if (count > 0) {
            super.out.write(buf, 0, count);
            count = 0;
        }
    }
	public synchronized void flush() throws IOException {
        flushBuffer();
        out.flush();
    }
}

class MyFilterOutputStream extends MyOutputStream{
	protected MyOutputStream out;
	public MyFilterOutputStream(MyOutputStream out){
		this.out = out;
	}
	

	@Override
	public void write(int b) throws IOException {
		// TODO Auto-generated method stub
		
	}

}

//是一个可以扩容的数组,长度默认是12
//没有实现flush,就意味着当扩容后的内容如果不足12,那么就以12的倍数算
class MyByteArrayOutputStream extends MyOutputStream{
	protected byte buf[];
	protected int count;
	private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
	public MyByteArrayOutputStream(){
		this(12);
	}
	public MyByteArrayOutputStream(int size){
		buf = new byte[size];
	}
	

	@Override
	public void write(int b) throws IOException {
		// TODO Auto-generated method stub
		buf[count++] = (byte) b;
	}
	//没有实现flush

}

//具体调用不可见
class MyFileOutputStream extends MyOutputStream{
	private native void write(int b, boolean append) throws IOException;
	@Override
	public void write(int b) throws IOException {
		write(b, false);
	}
	//没有实现flush
}
//输出流,write(int b)方法的实现
//flush:在这里没有起到任何作用
abstract class MyOutputStream {
	public abstract void write(int b) throws IOException;
	public void write(byte b[]) throws IOException {
        write(b, 0, b.length);
    }
    public void write(byte b[], int off, int len) throws IOException {
        for (int i = 0 ; i < len ; i++) {
            write(b[off + i]);
        }
    }
    public void flush() throws IOException {
    }
    public void close() throws IOException {
    }
}
3.1.4提醒

①读源码,只是为了帮助我们更好的了解这个java API的用法和特质,最主要的目的是我们以后的API会越来越多
学会翻阅API,如果不想看API的文档,可以适当阅读源码。看源码看的是逻辑,和特性,不是要你背上。
②API手册上的东西,主要是JDK里的内容
③JDK本身的流,其实不完美,性能不高/如果对流的性能有要求(NIO/BIO)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值