09--IO知识总结


IO知识总结:

                

1. 字符流

   1.1 专门处理字符数据,文本数据。
   1.2 字符输出流 Writer类,主要方法:
      1.2.1 写入方法
       write(char[] cbuf) 写入字符数组。返回类型为void。
       write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
       write(int c) 写入单个字符。
       write(String str) 写入字符串。
       write(String str, int off, int len) 写入字符串的某一部分。
      1.2.2 刷新
    flush() 刷新该流的缓冲。刷新后会数据会走目的地。
      1.2.3 关闭流
    close() 关闭此流,关闭前会自动调用flush()方法。
   1.3 字符输入流 Reader类, 主要方法:
      1.3.1 读取方法
    read()  读取单个字符。返回值类型为int。
    read(char[] cbuf)  将字符读入数组,返回值为读取的字符数。
    read(char[] cbuf, int off, int len) 将某一部分字符读入数组。
    read(CharBuffer target) 将字符读入指定的字符缓冲区
   1.3. 字符流的缓冲对象
      1.3.1 BufferedWriter  字符输出缓冲流
    BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。
    newLine()    字符缓冲流特有的方法,具有换一行的功能,跨平台。相当于windows下的"\r\n"。
      1.3.2 BufferedReader  字符输入缓冲流
    BufferedReader(Reader in)创建一个使用默认大小输出缓冲区的缓冲字符输出流.
    readLine()     读取一个文本行。
   案例:复制一个文本文件。
	import java.io.BufferedInputStream;
	import java.io.BufferedOutputStream;
	import java.io.FileInputStream;
	import java.io.FileOutputStream;
	import java.io.IOException;
	/*
	 * 要求:练习使用字节流缓冲区对象.对文件通过字节进行复制
	 * BufferedInPutStream(InPutStream)
	 * BufferedOutPutStream(OutPutStream)
	 */
	public class BufferStreamText {

		public static void main(String[] args) {
			long start = System.currentTimeMillis();
			copyByteFile();
			long end = System.currentTimeMillis();
			System.out.println(end - start);  // 计算复制过程所用的时间,单位为毫秒值。
		}
		
		// 定义一个功能,通过字节流对文件进行复制
		public static void copyByteFile(){
			// 声明字节输入流缓冲对象
			BufferedInputStream bis = null;
			// 声明字节输出流缓冲对象
			BufferedOutputStream bos = null;
			try {
				bis = new BufferedInputStream(new FileInputStream("1.avi"));
				bos = new BufferedOutputStream(new FileOutputStream("2.avi"));
				int by = 0;
				while((by = bis.read()) != -1){
					bos.write(by);
				}
			} catch (IOException e) {
				throw new RuntimeException();
			} finally {
				try {
					if(bos != null)
						bos.close();
				} catch (IOException e2) {
					throw new RuntimeException("字节输出流关闭失败");
				}
				try {
					if(bis != null)
						bis.close();
				} catch (IOException e2) {
					throw new RuntimeException("字节输入流关闭失败");
				}
			}
		}
	}


2. 字节流

   2.1 OutputStream 字节输出流,写入方法类似字符输出流,参数和byte有关。
    没有newLine方法。
   2.2 InputStream 字节输入流,写入方法类似字符写入流。
    没有ReadLine方法,字节文件没有行的概念。
    available()  返回此输入流读取的字节个数。
   2.3 BufferedOutputStream 字节输出缓冲流  包装了字节输出流,提高了效率。
    BufferedOutputStream(OutputStream out)   构造方法,将一个字节输出流装饰成字节缓冲输出流。
   2.4 BufferedInputStream 字节输入缓冲流  包装字节输入流
    BufferedInputStream(InputStream in)  构造方法,将一个字节输入流装饰成字节缓冲输入流。
   2.5 OutputStreamWriter 字节输出流转字符输出流,转换后的结果是字符输出流。
    构造方法
    OutputStreamWriter(OutputStream out)  创建使用默认字符编码的 OutputStreamWriter。
    OutputStreamWriter(OutputStream out, Charset cs) 创建使用给定cs字符集的 OutputStreamWriter。
    普通方法
    getEncoding() 获取此流使用的字符编码的名称
   2.6 InputStreamReader 字节输入流装字符输入流,转换后的结果是字符输入流。可以使用字符输入流的方法。
    构造方法
    InputStreamWriter(InputStream in)  创建使用默认字符编码的 OutputStreamWriter。
    InputStreamWriter(InputStream in, Charset cs) 创建使用给定cs字符集的 OutputStreamWriter。


3. 装饰设计模式Decorator

   3.1 什么叫装饰设计模式?
    动态给一个对象添加一些额外功能,增强原有对象的功能。
   3.2 装饰模式的好处
    我们通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的子类很繁多,那么势必生成很多子类,
    增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的.
    而使用装饰模式后,这些功能需要由用户动态决定加入的方式和时机.
    Decorator提供了"即插即用"的方法,在运行期间决定何时增加何种功能.
   3.3 如何使用,下面例子中我们使用装饰模式,加强reader这个方法的功能,实现一次读取一行数据。

	import java.io.IOException;
	import java.io.Reader;
	/*
	 * 要求:自定义类,实现类似BufferedReader类中的readLine读取一行文本的功能
	 * 
	 * 分析:
	 * 1,此功能调用Reader类的read方法的功能。
	 * 2,采用读一个字符就存入缓冲区,缓冲区可以用StringBuilder来实现
	 * 3,采用循环来重复2的操作,read方法返回不为-1作为循环条件
	 * 4,在循环中判断字符为\r就continue,如果是\n则返回字符缓冲区对应的字符串
	 * 5,在循环外面判断缓缓冲区是否为空,不为空则将返回缓冲区转换的字符串。
	 *   (保证在文本结束后没有一个换行也能把最后一行文本输出来。)
	 */
	public class MyReadLine {
		private Reader r;

		// 带Reader参数的构造方法
		MyReadLine(Reader r) {
			this.r = r;
		}

		public String myReadLine() throws IOException {
			// 定义一个字符缓冲容器
			StringBuilder sb = new StringBuilder();
			// 定义一个变量,用于临时存每次读取出来的单个字符
			int ch = 0;
			// 循环,读取
			while ((ch = r.read()) != -1) {
				// 判断字符为\r就continue
				if (ch == '\r')
					continue;
				// 是\n则返回字符缓冲区对应的字符串
				if (ch == '\n')
					return sb.toString();
				sb.append((char) ch);
			}
			// 不为空则将返回缓冲区转换的字符串
			if (sb.length() != 0)
				return sb.toString();
			return null;
		}

		public void myClose() throws IOException {
			r.close();
		}
	}

4. 流操作的基本规律:适当的条件下选择合适的流。需要名确3点。

   4.1 明确数据源和数据目的
    数据源    InputStream   Reader
    数据目的   OutputStream  Writer
   4.2 所操作数据是否是纯文本
    是  字符流   Reader  Writer   高效用BufferedReader BufferedWriter
    否  字节流   InputStream    OutputStream    高效用   BufferedInputStream   BufferedOutputStream
   4.3 明确使用哪个具体的对象,通过设备来区分。
    源设备       键盘   内存   硬盘(本地文件)
    目的设备     控制台  内存   硬盘(本地文件)

5. File类

   5.1 静态变量
    separator      与系统有关的默认名称分隔符,windows下为"\",即跨平台。
    pathSeparator   与系统有关的路径分隔符,windows";",也是跨平台的。
   5.2 构造方法
    File(File parent, String child) 根据parent抽象路径名和child字符串表示的路径组合成的一个路径和文件(夹).
    File(String pathname) 通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例.
    File(String parent, String child)    根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
   5.3 创建方法
    createNeFile()  在指定位置创建文件,如果存在则不会创建,返回一个false,创建成功返回true。
    mkdir()         只能创建一级目录,如果有则不创建,返回false。
    mkdirs()        既能创建一级目录又能创建多级目录。有则不创建。
   5.4 删除
    delete()        删除文件(夹),不存在则会返回false。
    delectOnecute() 在程序退出时删除文件,没有返回值。
   5.5 判断
    isDirectory()   判断是否是文件夹,是则返回true。不存在则返回false。
    isFile()        是否是文件。不存在则返回false。
    isHidden()      是否是隐藏文件(夹)
    isAbsolute()    是否是绝对路径(windows下带盘符即为绝对路径)。
   5.6 获取
    getName()            获取文件(夹)名称的字符串
    getPath()            获取文件的路径,是个相对路径,即构造方法中参数表示的路径。文件可不存在。
    getAbsolutePath()    获取文件(夹)的绝对路径的字符串表示形式。文件可不存在。
    getAbsoluteFile()    获取文件(夹)的绝对路径的File对象。文件可不存在。
    getParet()           获取文件(夹)的父目录的字符串。文件可不存在。
    length()             获取文件的大小。字节为单位。
    lastModified()       获取文件的最后修改是时间,结果是龙long类型的。
   5.7 其它方法
    renameTo(File)            给文件或文件夹重新命名
    listRoots()               静态方法,返回本机系统盘符,结果是File类型的数组
    list()                    返回指定路径下的所有一级文件及一级目录,包括隐藏。返回String类型的数组。调用此方法的file对象必须封装了一个目录,并且存在.
    list(FilenameFilter)      返回指定过滤后的子文件和文件夹的String类型的数组。
    listFiles()               返回指定路径下一级文件及一级文件夹所组成的File类型的数组。
    listFiles(FilenameFilter)  返回指定过滤后的子文件和文件夹的File类型的数组。
  综合练习例子

	import java.io.File;
	import java.util.ArrayList;
	/*
	 * 要求:列出某个目录下所有满足条件的文件和文件夹,将查找出来的文件以及文件夹的路径打印在控制台上。
	 * 分析:
	 * 1,获取指定文件的文件名,看是否满足条件
	 * 2,将满足条件的文件名,将其文件路径存入集合中
	 * 3,遍历集合,将集合中的元素写入到输出流中
	 */
	public class LookupFile {

		public static void main(String[] args) {
			File file = new File("E:\\java");
			printFile(file,"es");
		}
		// 在指定目录查找符合要求的的文件及文件名,打印到控制台
		public static void printFile(File file, String s){
			// 定义一个集合,用来装满足条件的文件的路径的字符串形式
			ArrayList<String> al = new ArrayList<String>();
			// 获取此目录下的一级子文件夹及子文件所组成的数组
			File[] files = file.listFiles();
			if(file.getName().contains(s)){
				al.add(file.getAbsolutePath());
			}
			// 遍历数组
			for(File f : files){
				// 如果仍然是文件夹,则递归调用此方法
				if(f.isDirectory()){
					printFile(f,s);
				}else{
					if(f.getAbsolutePath().contains(s))
						al.add(f.getAbsolutePath());
				}
			}
			// 将集合中的元素打印到控制台上
			for(String str : al){
				System.out.println(str);
			}
		}
	}

	import java.io.File;
	import java.io.FileInputStream;
	import java.io.FileOutputStream;
	import java.io.IOException;
	/*
	 * 要求:复制一个一级目录,目录下还有文件夹
	 * 分析:
	 * 1,在指定目录下创建一个空文件夹,文件夹名称为要复制文件夹名
	 * 2,通过字节输入流和字节输出流将文件复制到新建的文件夹
	 */
	public class CopyFiles {

		public static void main(String[] args) {
			File f1 = new File("D:\\test"); // 要复制的文件夹
			File f2 = new File("E:\\123");
			copy(f1, f2);
		}

		// 定义一个方法,传入两个File参数,一个作为源,一个作为目的,完成复制操作
		public static void copy(File soure, File file) {
			// 从源中获取文件夹名称
			String sourename = soure.getName();
			// 在指定目的创建文件夹
			File f = new File(file.toString() + File.separator + sourename);
			f.mkdirs();
			// 如果要复制的是文件不是文件夹
			if (soure.isFile()) {
				// 调用复制文件的方法
				copyFile(soure, f);
			} else {
				File[] files = soure.listFiles();
				// 遍历数组
				for (File fil : files) {
					// 调用复制文件的方法
					copyFile(fil, new File(f, fil.getName()));
				}
			}
		}

		// 定义一个方法,用来复制文件到指定目录
		public static void copyFile(File file_1, File file_2) {
			// 声明字节输入流
			FileInputStream fis = null;
			// 声明字节输出流
			FileOutputStream fos = null;
			try {
				fis = new FileInputStream(file_1); // 要复制的文件
				fos = new FileOutputStream(file_2); // 复制出来的文件
				int len = 0;
				byte[] buf = new byte[1024];
				while ((len = fis.read(buf)) != -1) {
					fos.write(buf, 0, len);
				}
			} catch (IOException e) {
				e.printStackTrace();
				throw new RuntimeException("文件复制失败");
			} finally {
				// 关闭资源
				try {
					if (fos != null)
						fos.close();
				} catch (IOException e2) {
					e2.printStackTrace();
					throw new RuntimeException("输出流关闭失败");
				}
				try {
					if (fis != null)
						fis.close();
				} catch (IOException e2) {
					e2.printStackTrace();
					throw new RuntimeException("输入流关闭失败");
				}
			}
		}
	}

6. Properties

    它是hashTable的子类,存储的都是键值对,都是字符串。
   6.1 普通方法
    StringProperNames()   获取由键组成的Set集合
    SetProperty()         通过键设置值
   6.2 关于流的方法
    list(printWriter或者printStream)   将集合中的键输出到指定打印流
    load(Reader或者InputStream)        将IO中的数据以键值对的形式存到集合中
    store(Writer或者OutputStream,注释) 将集合中保存的键值对存回到文件中   
    

7. 打印流

   7.1 打印流永远不会抛出IOException异常,提供能自动刷新的构造方法。
   7.1 printStream  字节打印流
      构造方法
    PrintStream(File file) 创建具有指定文件且不带自动行刷新的新打印流。
         PrintStream(File file, String csn) 创建具有指定文件名称和字符集且不带自动行刷新的新打印流。
    PrintStream(OutputStream out) 创建新的打印流。       
    PrintStream(OutputStream out, boolean autoFlush) 创建新的打印流。并且能够自动刷新。
    PrintStream(OutputStream out, boolean autoFlush, String encoding) 创建新的打印流。自动刷新和指定编码。           
    PrintStream(String fileName) 创建具有指定文件名称且不带自动行刷新的新打印流。           
    PrintStream(String fileName, String csn) 创建具有指定文件名称和字符集且不带自动行刷新的新打印流。
      方法
    println()   很多重载形式,有自动刷新功能。
   7.2 printOutputStream   字符打印流
      构造方法
    PrintWriter(File file) 使用指定文件创建不具有自动行刷新的新 PrintWriter。
    PrintWriter(File file, String csn) 创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。
        PrintWriter(OutputStream out) 根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。  
    PrintWriter(OutputStream out, boolean autoFlush) 通过现有的 OutputStream 创建新的 PrintWriter。
        PrintWriter(String fileName) 创建具有指定文件名称且不带自动行刷新的新 PrintWriter。
        PrintWriter(String fileName, String csn) 创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。
        PrintWriter(Writer out) 创建不带自动行刷新的新 PrintWriter。
        PrintWriter(Writer out, boolean autoFlush) 创建新 PrintWriter。
          

8. 对象的序列化和反序列化

   8.1 概念:把Java对象转换为字节序列的过程称为对象的序列化。
         把字节序列恢复为Java对象的过程称为对象的反序列化。
   8.2 对象的序列化主要有两种用途:
      8.2.1 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中。
      8.2.2 在网络上传送对象的字节序列。
   8.3 只有实现了Serializable和Externalizable接口的类的对象才能被序列化。
       Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,
       而仅实现Serializable接口的类可以采用默认的序列化方式 。
   8.4 对象序列化包括如下步骤:
      8.4.1 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流。
      8.4.2 通过对象输出流的writeObject()方法写对象。
   8.5 对象反序列化的步骤如下:
      8.5.1 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流。
      8.5.2 通过对象输入流的readObject()方法读取对象。
   8.6 实现Serializable接口
      8.6.1 ObjectOutputStream只能对Serializable接口的类的对象进行序列化。
            默认情况下,ObjectOutputStream按照默认方式序列化,这种序列化方式仅仅对对象的非transient的实例变量进行序列化,
        而不会序列化对象的transient的实例变量,也不会序列化静态变量。
      8.6.2 当ObjectOutputStream按照默认方式反序列化时,具有如下特点:
         8.6.2.1 如果在内存中对象所属的类还没有被加载,那么会先加载并初始化这个类。
        如果在classpath中不存在相应的类文件,那么会抛出ClassNotFoundException;
         8.6.2.2 在反序列化时不会调用类的任何构造方法。
   8.7 实现Externalizable接口
      8.7.1 Externalizable接口继承自Serializable接口,如果一个类实现了Externalizable接口,那么将完全由这个类控制自身的序列化行为。
      Externalizable接口声明了两个方法:
    public void writeExternal(ObjectOutput out) throws IOException   负责序列化操作
    public void readExternal(ObjectInput in) throws IOException , ClassNotFoundException   负责反序列化操作。
   8.8 可序列化类的不同版本的序列化兼容性
      8.8.1 凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
    private static final long serialVersionUID;


	import java.io.FileInputStream;
	import java.io.FileOutputStream;
	import java.io.ObjectInputStream;
	import java.io.ObjectOutputStream;

	/*
	 * 要求:练习对象序列化的使用,将对象保存在本地.
	 * 使用两个类:ObjectInputStream    和    ObjectOutputStream
	 */
	public class ObjectStreamTest {

		public static void main(String[] args) throws Exception {
			readObj();
			// writerObj();
		}
		// 读
		public static void readObj() throws Exception {

			ObjectInputStream ois = new 
					ObjectInputStream(new FileInputStream("d:\\111.txt"));
			Object o = ois.readObject();
			System.out.println(o);
		}
		// 写
		public static void writerObj() throws Exception {
			person2 p = new person2("张三", 45);

			ObjectOutputStream oos = new 
					ObjectOutputStream(new FileOutputStream("d:\\111.txt"));
			oos.writeObject(p);
		}
	}
	// 序列化person对象
	class person2 implements java.io.Serializable {
		private String name;
		private int age;
		public person2(String name, int age) {
			super();
			this.name = name;
			this.age = age;
		}
		@Override
		public String toString() {
			return "person2 [name=" + name + ",   age=" + age + "]";
		}
	}

   总结:刚刚学完IO的知识的时候,感觉知识点太多,都记不住,写了一篇博客,回顾了学习的知识点,又加深了印象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值