1g File与IO.txt

UP 返回
1.java.io.File	重写了toString()
   1.1 四个静态变量:
	static String pathSeparator 路径分隔符	windows下是; Linux下是:
	static char pathSeparatorChar 路径分隔符
	static String separator 默认名称分隔符	windows下是\ Linux下是/
	static char separatorChar 默认名称分隔符

   1.2 路径	不区分大小写
	绝对路径:从盘符开始的
	相对路径:相对于当前项目的根目录

   1.3 构造方法		创建File对象,只是将字符串封装,不考虑路径的真假。
	File(String fileName)
	File(String parent,String child);	//可以将路径拆开成两个字符串,创建的时候会自动把两个连起来	new File("d:\\","a.txt");
	File(File parent,String child);		//用处同上,参数不同。 new File(new File("d:\\"),"c.txt")

   1.4 方法
	public String getAbsolutePath()	//返回绝对路径
	public String getPath()				//返回构造方法中的路径;toString()调用的就是该方法
	public String getName()			//构造方法传递的结尾部分
	public long length()				//获取文件大小。以字节为单位。文件夹没有大小,返回0。如果文件不存在,返回0
	public boolean exists()				//是否存在
	public boolean isDirectory()		//是否是文件夹
	public boolean isFile()				//是否是文件(如果文件不存在返回false,上同)
	public boolean createNewFile()	//创建文件。创建了则返回true,只能创建文件;路径不存在会抛异常
	public boolean mkdir()				//创建单级文件夹。创建了则返回true,否则返回false;路径不存在返回false
	public boolean mkdirs()			//可创建单级或多级文件夹
	public boolean delete()			//删除文件或文件夹。文件夹中如果有内容,不会删除返回false。删除是从硬盘直接删除不走回收站

	public String[] list()					//遍历文件夹下,返回文件名string数组。若给出的路径不存在或者不是文件夹,会抛出空指针异常,下同
	public File[] listFiles()				//遍历文件夹下,返回File数组

2.文件过滤器 	 
   2.1 File类中有两个listFiles重载的方法,可以传递过滤器
	File[] listFiles(FileFilter filter)
	File[] listFiles(FilenameFilter filter)
   2.2 java.io.FileFilter接口,用于抽象路径名(File对象)的过滤器
	用于过滤文件
	抽象方法:boolean accept(File pathname)	pathname就是使用listFiles遍历得到的每一个文件对象
	   java.io.FilenameFilter接口
	用于过滤文件名
	抽象方法:boolean accept(File dir,String name)	dir是构造方法包中被遍历的目录,name为遍历获取的文件名称
	
	这两个过滤器接口没有实现类,需要自己写,并重写方法accept定义过滤规则
		public class Demo01 {
				public static void main(String[] args) {
					File[] listFile1 = new File("D:\\搜狗高速下载").listFiles((pathname) -> pathname.isDirectory());
			
					File[] listFile2 = new File("D:\\搜狗高速下载").listFiles((d, name) -> new File(d, name).isDirectory());
			
					for (File temp : listFile2) {
						System.out.println(temp.getName());
					}
				}
			}	 

3.字节流	一切皆为字节	java.io
   3.1 字节输出流:OutputStream,所有字节输出流最顶层的超类(abstract)
	public void close() :关闭此输出流并释放与此流相关联的任何系统资源。 
	public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。 
	public void write(byte[] b) :将 b.length字节从指定的字节数组写入此输出流。 
	public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 o 开始输 出到此输出流。 
	public abstract void write(int b) :将指定的字节输出流。

   3.2 文件字节输出流:FileOutputStream,把内存中数据写入到磁盘文件
	FileOutputStream(String name)	name写入数据的目的路径
	FileOutputStream(File file)
	FileOutputStream(String name,boolean append)	 append追加flag
	FileOutputStream(File file,boolean append)
	构造方法作用:创建一个对象;根据路径或文件创建一个空文件;将该对象指向创建的文件  
		try {
				FileOutputStream fos = new FileOutputStream("01.txt");		//没有文件会自动创建新的
				fos.write(65);				//该方法会将该int对应ascii码的字符写入文件
				fos.close();

				byte[] bytes = { -65, -66, -67, 68, 69 };
				fos.write(bytes);			//如果写入的第一个字节是正数(0-127),那么显示的时候会查ascii码表;如果是负数,那么会取两个字节组成一个中文显示,查询系统默认码表
				fos.write(bytes,1,2);			
				fos.write("你好".getBytes());	//通过获取字符串的bytes写入文件,看到的就是写入的
				fos.write("\r\n".getBytes());		//换行。windows:\r\n	Linux:/n	mac:/r
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

   3.3 字节输入流:FileInputStream
	FileInputStream(String name)
	FileInputStream(File file)
	构造方法作用:创建一个对象;对象指向对应文件
		FileInputStream fis = new FileInputStream("01.txt");
		int len = 0;
		while ((len = fis.read()) != -1) {		//一次读取一个字节
			System.out.println(len);
		}
		byte[] bytes = new byte[1024];			//一次读取多个字节
		while ((len = fis.read(bytes)) != -1) {		//一般定义成1024(1kb或者1024的整数倍)起到缓冲的作用,该方法返回的是每次读取到的字节个数
			// System.out.println(Arrays.toString(bytes));	//查看的是字节int数组
			System.out.println(new String(bytes));		//使用bytes创建String便于查看(String(byte[] bytes) / String(byte[] bytes,int offset,int length))
			System.out.println(new String(bytes,0,len));	//只打印读取出来的长度。上面那句即是不够1024也会打印出1024长度的字符串
		}
		fis.close();

   3.4 文件复制
		FileInputStream fis = new FileInputStream("01.txt");
		FileOutputStream fos = new FileOutputStream("02.txt");
		byte[] bytes = new byte[1024];
		int len = 0;
		while ((len = fis.read(bytes)) != -1) {
			fos.write(bytes, 0, len);	//加上len可以保证最后一次写入的长度是len,不然写入的是数组的大小1024,会导致复制的文件比源文件要大
		}
		fos.close();
		fis.close();

   3.5 字节流读取中文的问题
	一个中文:GBK	占用2字节
				UTF-8	占用3字节
	字节读取是一个一个字节来读,故中文显示会出现乱码。此时需要用字符流(复制文件并不影响,只是影响显示)

4.字符流	
   4.1 字符输入流:java.io.Reader	,抽象类,所有字符输入流最顶层的超类
	int read()	读取单个字符并返回
	int read(char[] cbuf)	一次读入多个字符到数组
	void close()	关闭流

   4.2 文件字符输入流:FileReader	extends InputStreamReader extends Reader		将文件以字符流的形式读入内存
	FileReader(String fileName)	
	FileReader(File file)
	构造方法作用:创建对象;将对象指向文件
		FileReader fr = new FileReader("01.txt");
		int len = 0;
		while ((len = fr.read()) != -1) {		//每次都会读取一个字符,故可以正常显示
			System.out.println((char) len);
		}
		fr.close();
	上述读取也可以改成读取字符数组:
		char[] cs = new char[1024];
		while ((len = fr.read(cs)) != -1) {
			System.out.println(new String(cs, 0, len));
		}

   4.3 字符输出流:java.io.Writer,抽象类
	void write(int c)	写入单个字符
	void write(char[] cbuf)
	abstract void write(char[] cbuf,int off,int len)
	void write(String str)	写入字符串
	void write(String str,int off,int len)
	void flush()		刷新该流的缓冲
	void close()	关闭流,需要先刷新

   4.4 文件字符输出流:FileWriter		extends OutputStreamWriter extends Writer		把内存字符数据写入文件
	FileWriter(String fileName)	//两个构造方法同样有续写开关:FileWriter(String fileName,boolean append)
	FileWriter(File file)
	构造方法作用:创建对象;根据构造方法传递的文件或路径创建文件;对象指向创建的文件
	字符输出流使用步骤(同字节有区别):
		1.创建FileWriter对象
		2.使用write,把数据写入内存缓冲区(字符转换为字节的过程)
		3.使用flush,把内存缓冲区中的数据刷新到文件中
		4.释放资源(会先把内存缓冲区中的数据刷新到文件中)
			FileWriter fw = new FileWriter("01.txt");
			fw.write(97);
			fw.close();		//只有flush或者close后缓冲区的数据才会被写入文件

			cha[] cs={'a','b','c','d'}
			fw.write(cs,1,2);
			fw.write("你好啊");
			fw.write("你好啊",1,2);		//换行写入的字符规则同文件字节输出流一样

5.处理流异常
   jdk1.7之前,使用:
	try{
	}catch{
	}finally{}

   JDK7新特性:在try后面可以增加一个(),在括号中可以定义流对象,这个流对象就在整个try作用域有效,try中代码执行完毕会自动把流对象释放,不用写finally
	try(FileInputStream fis=new FileInputStream("01.txt");
		FileOutputStream fos=new FileOutputStream("02.txt"); ){
			int len = 0;
			while ((len = fis.read()) != -1) {		
				fos.write(len);
			}
	}catch(IOException e){
		System.out.println(e);
	}

   JDK9新特性:try前可以定义对象,在try后的()中可以直接引入流对象的名称,在try中执行完毕后,流也可以释放掉,不用finally
	FileInputStream fis=new FileInputStream("01.txt");
	FileOutputStream fos=new FileOutputStream("02.txt"); 
	try(fis;fos){
		int len = 0;
		while ((len = fis.read()) != -1) {		
			fos.write(len);
		}
	}catch(IOException e){
		System.out.println(e);
	}

6.java.util.Properties集合		extends Hashtable<k,v> implements Map<k,v>	表示一个持久的属性集,可保存在流中或从流中读取。属性列表中每个键值都是字符串,是唯一一个与IO流相结合的集合
   6.1 可以使用方法store保存集合到硬盘,使用load把文件中键值读取
	Object setProperty(String key ,String value)	调用Hashtable中的put方法
	String getProperty(String key)		获取key的value,相当于map中的get(key)
	Set<String> stringPropertyNames()	返回键集,相当于map中的keySet
	void store(OutputStream out,String comments)	字节输出流,不能写入中文;comments:注释,用来解释保存的文件是做什么用的,不能使用中文会乱码,默认Unicode,一般使用空字符串即可,下同
	void store(Writer writer ,String comments)	字符输出流,可以写入中文
	void load(InputStream inStream)		不可读取中文(存储键值对的文件中,键值间的连接符号可以用=,空格(其他符号);文件可以使用#进行注释;文件键值默认为字符串,不用再加引号)
	void load(Reader reader)		可以读取中文
	保存:
		Properties prop = new Properties();
		prop.setProperty("1", "good");
		prop.setProperty("2", "好的");
		prop.setProperty("3", "bad");
		prop.setProperty("4", "坏的");
		FileWriter fw = new FileWriter("prop.txt");
		prop.store(fw, "save data");
	读取:
		Properties prop = new Properties();
		prop.load(new FileReader("prop.txt"));	//读入文件
		Set<String> keySet = prop.stringPropertyNames();	//获取键值set
		for (String key : keySet) {
			System.out.println(key + "=" + prop.getProperty(key));	//遍历打印
		}

7.缓冲流
   7.1 java.io.BufferedOutputStream extends OutputStream  字节缓冲输出流
	BufferedOutputStream(OutputStream out)
	BufferedOutputStream(OutputStream out, int size)	//out 字节输出流,可以传递FileOutputStream,缓冲流会给他增加一个缓冲区,提高效率;size 指定缓冲流内部缓冲区大小,不指定就默认
	使用步骤:
		1.创建FileOutputStream对象,构造方法中绑定输出的目的地
		2.创建BufferedOutputStream对象,构造方法中传递FileOutputStream对象
		3.使用BufferedOutputStream中的write,把数据写入到内部缓冲区
		4.使用BufferedOutputStream中的flush,把内部缓冲区中的数据刷新到文件中
		5.释放资源(会先调用flush,第4步可省略)
			FileOutputStream fos = new FileOutputStream("01.txt");
			BufferedOutputStream bos = new BufferedOutputStream(fos);
			bos.write("AAAA".getBytes());
			bos.close();		//缓冲流关闭会自动关闭字节流,可以不用再对fos进行关闭。下面的bis同理
   7.2 java.io.BufferedInputStream extends InputStream   字节缓冲输入流
	BufferedInputStream(InputStream in)
	BufferedInputStream(InputStream in, int size)		//in 字节输入流,可以传递FileInputStream
	使用步骤:
		1.创建FileInputStream对象,构造方法绑定读取的数据源
		2.创建BufferedInputStream对象,构造方法传递FileInputStream对象
		3.使用FileInputStream对象的read,读取文件
		4.释放资源
			FileInputStream fis = new FileInputStream("02.txt");
			BufferedInputStream bis = new BufferedInputStream(fis);
			int len = 0;
			while ((len = bis.read()) != -1) {
				System.out.println(len);
			}

			byte[] bytes = new byte[1024];		//存储每次读取的数据
			len = 0;								//记录每次读取的有效字节个数
			while ((len = bis.read(bytes)) != -1) {
				System.out.println(new String(bytes, 0, len));
			}
			bis.close();		//参bos,无需单独对fis做关闭
   7.3 java.io.BufferedWriter extends Writer   字符缓冲输出流
	BufferedWriter(Writer out)
	BufferedWriter(Writer out, int size)	//out  字符输出流,可以传递FileWriter
	特有的成员方法:
		void newLine()		//写入一个行分隔符。会根据不同的操作系统,获取不同的行分隔符
	使用步骤:
		1.创建字符缓冲输出流对象,构造方法中传递字符输出流
		2.调用字符缓冲输出流中的write,写入数据到缓冲区
		3.调用字符缓冲输出流中的flush,将缓冲区数据刷新到文件中
		4.释放资源
			BufferedWriter br = new BufferedWriter(new FileWriter("03.txt"));
			for (int i = 0; i < 10; i++) {
				br.write("好的");
				br.newLine();
			}
			br.close();
   7.4 java.io.BufferedReader   字符缓冲输入流
	BufferedReader(Reader in)
	BufferedReader(Reader in, int size)	//in 字符输入流,可以传入FileReader,提高读取效率
	特有的成员方法:
		String readLine()	读取一个文本行(\r,\n或者\r\n即认为是一行;返回值不包含任何终止符,文件末尾返回null)
	使用步骤:
		1.创建字符缓冲输入流,构造方法中传递字符输入流
		2.使用字符缓冲输入流中的read/readLine读取文本
		3.释放资源
			BufferedReader br = new BufferedReader(new FileReader("03.txt"));
			String tempString;
			while ((tempString = br.readLine()) != null) {
				System.out.println(tempString);
			}
			br.close();

8.转换流
	windows创建文件时,默认保存的编码是ANSI,也就是GBK。用FileReader读取时就会乱码
	FileReader和FileWriter都只能使用ide默认的编码方式(UTF-8)
   8.1 java.io.OutputStreamWriter extends Writer   是字符流通向字节流的桥梁,可使用指定的编码方式将要写入流中的字符编码成字节
	OutputStreamWriter(OutputStream out)
	OutputStreamWriter(OutputStream out, String charsetName)	//out 字节输出流;charsetName 指定的编码,不区分大小写,不指定的话默认utf-8
	使用步骤:
		1.创建OutputStreamWriter对象,构造方法中传递字节输出流和编码表名称
		2.使用OutputStreamWriter对象中的write,把字符转换为字节存储缓冲区
		3.使用OutputStreamWriter中的flush,刷新
		4.释放资源
			OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("03.txt"), "GBK");
			osw.write("你好");
			osw.flush();
			osw.close();
   8.2 java.io.InputStreamReader extends Reader   是字节流通向字符流的桥梁,可使用指定的编码方式将读取的字节解码为字符
	InputStreamReader(InputStream in)
	InputStreamReader(InputStream in, String charsetName)	//in 字节输入流;charsetName 指定的编码,不区分大小写,不指定的话默认utf-8
	使用步骤:
		1.创建InputStreamReader对象,构造方法中传递字节输入流和编码表名称(编码应与文件编码相同,否则会乱码)
		2.使用InputStreamReader对象中的read,读取文件
		3.释放资源
	  		InputStreamReader isr = new InputStreamReader(new FileInputStream("03.txt"), "gbk");
			int len = 0;
			while ((len = isr.read()) != -1) {
				System.out.println((char) len);
			}

9.序列化
   9.1 java.io.ObjectOutputStream extends OutputStream		对象的序列化流,把对象以流的形式写入到文件中
	ObjectOutputStream(OutputStream out)		创建写入指定OutputStream的ObjectOutputStream。out 字节输出流
	特有方法:
		void writeObject(Object obj)
	使用步骤:
		1.创建ObjectOutputStream对象,构造方法中传递字节输出流
		2.使用ObjectOutputStream中的writeObject,把对象写入文件
		3.释放资源
	序列化和反序列化时,会抛出java.io.NotSerializableException没有序列化异常。类通过实现java.io.Serializable 接口以启用其序列化功能,未实现该接口将无法使用其任何状态序列化或反序列化。
	Serializable接口也叫标记型接口,实现后会给类添加一个标记,进行序列化反序列化时会检测这个标记,有即可进行,没有就会抛出该异常
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("04.txt"));
		oos.writeObject(new Person("大王", 19));// 抛出异常java.io.NotSerializableException	//Person实现序列化接口
		oos.close();

	对多个对象进行读写序列化时,读的顺序应该和写入的顺序相同,否则会抛异常(待验证)

   9.2 java.io.ObjectInputStream extends InputStream	对象的反序列化流,把文件中保存的对象以流的方式读取出来使用
	ObjectInputStream(InputStream in)	创建从指定的InputStream读取的ObjectInputStream
	特有方法:
		Object readObject()	
	使用步骤:
		1.创建ObjectInputStream对象,构造方法中传递字节输入流
		2.使用ObjectInputStream中的readObject读取保存的对象(类必须存在对应的class文件)
		3.释放资源
		4.使用对象
			ObjectInputStream ois = new ObjectInputStream(new FileInputStream("04.txt"));
			Person pp = (Person) ois.readObject();
			ois.close();
			System.out.println(pp);

   9.3 transient 瞬态关键字
	static是静态关键字,静态优先于非静态加载到内存中,优先于对象进入到内存中,被其修饰的成员变量不能被序列化,因为序列化的都是对象(如果将9.1 9.2的Person中的某个变量定义为static,序列化反序列化都无法将该变量的值传入,得到的只是默认值)
	transient修饰的成员变量,也不能序列化
		private static int age;
		private transient int age; 	//效果相同

   9.4 编译器(javac.exe)将类编译生成class文件,如果类实现了序列化接口,就会根据类的定义,给class文件添加一个序列号serialVersionUID,序列化进入文件;
	   反序列化的时候,会使用class文件中的序列号和序列化生成的文件中的序列号比较,如果相同则反序列化成功,不同则会抛出InvalidClassException(比如序列化后修改了类中变量的定义,后面没有序列化就直接反序列化,就会抛出异常)
	   可以自己设置一个serialVersionUID,来保持永远不变,必须为static final long serialVersionUID
		private static final long serialVersionUID=1L;
		private String name;
		private int age;

10.打印流 	java.io.PrintStream extends OutputStream	PrintStream只负责数据输出,不负责读取;永远不会抛出IOException;有特有的方法print和println
	PrintStream(File file)	输出的目的地是一个文件
	PrintStream(OutputStream out)	输出的目的地是一个字节输出流
	PrintStream(String filename)	输出的目的地是一个文件路径
	如果使用继承自父类的write方法写数据,那么查看数据的时候会查询编码表 97->a;如果使用自己特有的方法print println写数据,写的数据原样输出 97->97
		PrintStream ps = new PrintStream("05.txt");
		ps.write(97);
		ps.println(97);
		ps.close();
	可以改变输出语句的目的地(打印流方向):输出语句默认在控制台输出,使用System.setOut方法可以切换	static void setOut(PrintStream out) 
		PrintStream out = new PrintStream("05.txt");
		System.out.println("输出控制台");
		System.setOut(out);			
		System.out.println("输出在文件中");
		out.close();










DOWN 返回