操作图片数据就要用到字节流。
字符流使用的是字符数组char[],字节流使用的是字节数组byte[]。针对文件的读写,JDK专门提供了两个类,分别是FileInputStream和FileOutputStream。
FileInputStream是InputStream的子类,它是操作文件的字节输入流,专门用于读取文件中的数据
FileOutputStream,它是OutputStream的子类,专门用于读取文件中的数据 如果是通过FileOutputStream向一个已经存在的文件中写入数据,那么该文件中的数据首先会被清空,再写入新的数据。若希望在存在的文件内容之后追加新内容,则可使用FileOutputStream的构造函数FileOutputStream(String fileName, boolean append)来创建文件输出流对象,并把append 参数的值设置为true
FileInputStream 读FileOutputstream 写
读取
FileInputStream fis=new FileInputStream ("a.txt"); byte[] buf=new byte[fis].available(0)]; //定义一个刚刚好的缓冲区,不用再循环了fis.read(buf);
System.out.println(new String(buf));
fis.close();FileInputStream(FileDescriptor fdObj) 参数fdObj为文件描述符,通过文件描述符创建类
FileInputStream(String name) 参数name为文件路径名,通过文件路径创建类void close() 关闭文件输入流,同时释放系统资源
protected void finalize() 确认文件输入流不在被引用的状态,并可以调用close方法java.io.channels.FileChannel getChannel() 返回与该文件输入流有关的FileChannel对象
FileDescriptor getFD() 返回连接到文件系统(正被该FileInputStream使用)中实际文件的FileDescriptor对象int read() 从该输入流中读取一个数据字节,并以int类型返回
int read(byte[] b) 读取输入流中b.length个字节的数据,并存入字节数组b中int read(byte[] b, int off, int len) 读取输入流中从偏移量off开始的len个字节的数据,并存入字节数组b中
long skip(long n) 跳过输入流中的数据,同时丢弃n个字节的数据FileOutputStream(File file) 通过file对象创建FileOutputSteam
FileOutputStream(File file, boolean append) 通过file对象创建类,append为true或false表示是否在文件末尾追加
FileOutputStream(FileDescriptor fdObj) 参数fdObj为文件描述符,通过文件描述符创建FileOutputStreamFileOutputStream(String name) 参数name为文件路径名,通过文件路径创建FileOutputStream
FileOutputStream(String name, boolean append) 参数name为文件路径名,通过文件路径创建FileOutputStream, append为true或false表示是否在文件末尾追加
void close() 关闭该文件输出流,同时释放系统资源
protected void finalize() 断开到文件的连接,确认该文件输出流不处在被引用状态,并可以调用close方法
FileDescriptor getFD() 返回与该流有关的文件描述符FileDescriptor对象void write(byte[] b) 将b.length个字节的数据从指定字节数组写入到该文件输出流中
void write(byte[] b, int off, int len) 将指定字节数组中的部分数据(从偏移量off开始的len个字节)写入到该文件输出流 void write(int b) 将指定字节b写入到该文件输出流public void close() 该方法用于关闭输入流,并释放系统资源
public void mark(int readlimit) 该方法用于标记输入流中的当前位置 public boolean markSupported() 该方法用于测试该输入流是否支持mark和reset方法public int read() 该方法用于从输入流中读取一个数据字节
public int read(byte[] b) 该方法用于从输入流中读取byte.length个字节的数据并存入到一个字节数组b中public int read(byte[] b,int off,int len) 该方法用于从输入流中读取从偏移量off开始len个字节的数据并存入到一个字节数组b中
public void reset() 该方法用于将流重新定位到对该输入流最后一次调用mark方法时的位置
public long skip(long n) 该方法用于跳过输入流中n个字节的数据,并丢弃文件的拷贝就需要通过输入流来读取文件中的数据,通过输出流将数据写入文件。
练习:复制图片
FileOutputStream fw=null; FileInputStream fr=null; try { fos=new FileOutputStream("b.jpg"); fis=new FileInputStream("a.jpg"); byte[] buf=new byte[1024]; int num=0; while ((num=fis.read(buf))!=-1) { fis.write(buf,0,num); } } catch (IOException e) { e.printStackTrace(); } finally { try { if(fis!=null) fis.close(); } catch (IOException e) { e.printStackTrace(); } try { fos.close(); } catch (IOException e) { e.printStackTrace(); } }在IO包中提供两个带缓冲的字节流,分别是BufferedInputStream和BufferdOutputStream,这两个流都使用了装饰设计模式。它们的构造方法中分别接收InputStream和OutputStream类型的参数作为被包装对象,在读写数据时提供缓冲功能。
为了提高效率也可以定义一个字节数组作为缓冲去。在拷贝文件时,可以一次性读取多个字节的数据,并保存在字节数组中,然后将字节数组中的数据一次性写入文件
是InputStream类的间接子类,其直接父类是FilterInputStream。
BufferedInputStream(InputStream in) 以InputStream对象in为参数创建类
BufferedInputStream(InputStream in, int size) 以InputStream对象in为参数创建类,并且通过参数size指定缓存区大小public void close() 该方法用于关闭输入流,并释放系统资源
public void mark(int readlimit) 该方法用于标记输入流中的当前位置public boolean markSupported() 该方法用于测试输入流是否支持mark和reset方法
public int read() 该方法用于从输入流中读取下一个数据字节
public int read(byte[] b,int off,int len) 读取字节输入流中的从偏移量off开始的len个字节并存入到指定的byte数组b中
public void reset() 将此流重新定位到最后一次调用mark方法时所处的位置
public long skip(long n) 跳过并且放弃输入流中的n个字节数据BufferedOutputStream(OutputStream out) 以InputStream对象in为参数创建类
BufferedOutputStream(OutputStream out, int size) 以OutputStream对象out为参数创建类,并且通过size指定缓存区大小public void flush() 该方法用于刷新输出流
public void write(byte[] b,int off,int len) 将字节数组中从偏移量off开始的len个字节写入到输出流public void write(int b) 将指定的字节b写入到输出流
flush()方法用于强制将缓冲区的内容立即写入输出流。在使用缓存区机制的输出流时,调用write()方法后数据并没有立即写入输出流,而是先放到缓存区中。所以,在必要的地方可以调用flush()方法强制刷新缓冲区。
public int available() 以不受阻塞地从输入流中读取字节。该方法返回读取字节数
public void mark(int readlimit) 在此输入流中标记当前的位置public boolean markSupported() 判断输入流是否支持mark()和reset()方法。如果支持则返回true。
public int read(byte[] b) 从输入流中读取一定数量的字节并将其存储在缓冲区数组b中。该方法返回读入缓冲区的总字节数
public int read(byte[] b,int off,int len) 从off处开始读取流中len长度的字节并将其存储在数组b中。返回读取到的字节数public void reset() 将此流重新定位到输入流最后调用mark方法时的位置
public long skip(long n) 跳过此输入流中的n个字节。参数n表示要跳过的字节数。该方法返回实际跳过的字节数public void close() 关闭输入流
public void writer (byte[] b) 将字节数组写入输出流
public void writer (byte[] b, int off, int len) 将指定字节数组b中以off开始的len个字节写入输出流public void flush() 刷新输出流
public void close() 关闭输出流当想要对已有的独享进行功能增强时,可以定义类,将已有的对象传入,基于已经有的功能,并提供加强功能,那么自定义的该类称为装饰类
装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
已知类: Person() { public void chifan() { } } 增强类: superPerson() { private Person p; superPerson(Person p) { this.p=p; } public void superchifan() { p.chifan(); ......... { } 自定义装饰类 package com.io; import java.io.*; public class MyBufferedReader { private Reader r; public MyBufferedReader(Reader r) { super(); this.r = r; } //可以一次读取一行的方法 public String myReadLine() throws IOException { //定义一个临时容器。StringBulider容器,应用于存储字符数组 StringBuilder sb=new StringBuilder(); int ch=0; while((ch=r.read())!=-1) { if(ch=='\r') continue; if(ch=='\n') return sb.toString(); else sb.append((char)ch); } if(sb.length()!=0) return sb.toString(); return null; } //复写reader中的抽象方法 //复写close方法 public void close() throws IOException { r.close(); } //复写read方法 public int read (char[] c,int off,int len) throws IOException { return r.read(c, off, len); } } 装饰设计模式就是通过包装一个类,动态地为它增加功能的一种设计模式。