Java基础系列8——IO流超详细总结

该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架。

在初学Java时,IO流是我遇到的一个很头疼的东西,Java IO 体系看起来类很多,感觉很复杂,但其实是 IO 涉及的因素太多了。在设计 IO 相关的类时,编写者也不是从同一个方面考虑的,所以会给人一种很乱的感觉,并且还有设计模式的使用,更加难以使用这些 IO 类,所以特地对 Java 的 IO 做一个总结。

IO流总览

话不多说,直接上图:

IO流分类:

按照“流”的数据流向,可以将其化分为:输入流输出流

按照“流”中处理数据的单位,可以将其区分为:字节流字符流。在java中,字节是占1个Byte,即8位;而字符是占2个Byte,即16位。而且,需要注意的是,java的字节是有符号类型,而字符是无符号类型!

字节流的抽象基类:

  InputStream,OutputStream

字符流的抽象基类:

  Reader,Writer

由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀,如InputStream的子类FileInputStream,Reader的子类FileReader。

字符流

Writer:字符输出流

Writer是字符输出流的基类,Writer的主要方法如下:

Writer append​(char c) 将指定的字符附加到此作者
Writer append​(CharSequence csq) 将指定的字符序列附加到此作者
Writer append​(CharSequence csq, int start, int end) 将指定字符序列的子序列附加到此作者  
abstract void close​() 关闭流,先刷新
abstract void flush​() 刷新流  
void write​(char[] cbuf) 写入一个字符数组。  
abstract void write​(char[] cbuf, int off, int len) 写入字符数组的一部分  
void write​(int c) 写一个字符  
void write​(String str) 写一个字符串  
void write​(String str, int off, int len) 写一个字符串的一部分

我们知道IO流主要是用于操作文件的,但是从上图中我们发现Writer的直接子类中好像并没有直接操作文件,但是细心的你注意到,在Writer的子类OutputStreamWriter的子类中有一个类叫做FileWriter,File这个单词我们很熟悉——文件,大家可以推测一下这个类是可以用于操作文件的,下面我们来学习一下FileWriter的用法

FileWriter

1、FileWriter的构造方法:

OutputStreamWriter​(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter 
OutputStreamWriter​(OutputStream out, String charsetName) 创建一个使用命名字符集的OutputStreamWriter
OutputStreamWriter​(OutputStream out, Charset cs) 创建一个使用给定字符集的OutputStreamWriter
OutputStreamWriter​(OutputStream out, CharsetEncoder enc) 创建一个使用给定字符集编码器的OutputStreamWriter  

2、FileWriter的方法列表:

Writer append​(CharSequence csq) 将指定的字符序列附加到此作者。  
Writer append​(CharSequence csq, int start, int end) 将指定字符序列的子序列附加到此作者。  
void close​() 关闭流,先刷新。  
void flush​() 刷新流。  
String getEncoding​() 返回此流使用的字符编码的名称。  
void write​(char[] cbuf, int off, int len) 写入字符数组的一部分。  
void write​(int c) 写一个字符  
void write​(String str, int off, int len) 写一个字符串的一部分。  

3、FileWriter方法的详细讲解:

例1:创建一个文件demo.txt,然后向里面写入字符串abcde

import java.io.*;
class  FileWriterDemo
{
	public static void main(String[] args) throws IOException
	{
		//创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
		//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
		//其实该步就是在明确数据要存放的目的地。
		FileWriter fw = new FileWriter("demo.txt");
		

		//调用write方法,将字符串写入到流中。
		fw.write("abcde");

		//刷新流对象中的缓冲中的数据。
		//将数据刷到目的地中。
		//fw.flush();


		//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
		//将数据刷到目的地中。
		//和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
		fw.close();
	}
}

例2:上面的代码中我们可以看到有异常产生,但是我们并没有处理,而是抛出去了,那么在日常开发中我们不能直接抛出,所以需要对异常进行处理

/*
IO异常的处理方式。
*/
import java.io.*;

class  FileWriterDemo2
{
	public static void main(String[] args) 
	{
		FileWriter fw = null;
		try
		{
			fw = new FileWriter("demo.txt");//可能会有异常产生
			fw.write("abcdefg");

		}
		catch (IOException e)
		{
			System.out.println("catch:"+e.toString());
		}
		finally
		{
			try
			{
				if(fw!=null)
					fw.close();//可能会有异常产生				
			}
			catch (IOException e)
			{
				System.out.println(e.toString());
			}
			
		}		

	}
}

例3:细心的同学可以注意到,上面的那种方式写入文件时,会将之前的文件覆盖了,之前文件中写的内容不存在了,那么如何在已有的文件后面添加内容

/*
演示对已有文件的数据续写。
*/
import java.io.*;
class  FileWriterDemo3
{
	public static void main(String[] args) throws IOException
	{

		//传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。
		FileWriter fw = new FileWriter("demo.txt",true);

		fw.write("nihao\r\nxiexie");

		fw.close();
	}
}

BufferedWriter

BufferedWriter 是缓冲字符输出流。它继承于Writer。
BufferedWriter 的作用是为其他字符输出流添加一些缓冲功能,使用BufferedWriter可以提高我们写入文件的效率。

1、BufferedWriter的构造方法:

BufferedWriter​(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。  
BufferedWriter​(Writer out, int sz) 创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。  

2、BufferedWriter的方法列表:

void close​() 关闭流,先刷新。  
void flush​() 刷新流。  
void newLine​() 写一行行分隔符。  
void write​(char[] cbuf, int off, int len) 写入字符数组的一部分。  
void write​(int c) 写一个字符  
void write​(String s, int off, int len) 写一个字符串的一部分。  

3、BufferedWriter的方法详解:

例:

import java.io.*;
class BufferWriterDemo{
    public static void main(String[] args) throws IOException {
        //创建一个字符写入流对象。
        FileWriter fw = new FileWriter("buf.txt");
        //为了提高字符写入流效率。加入了缓冲技术。
	//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
        BufferedWriter bw=new BufferedWriter(fw);
        char[] c={'a','b','c','d','e'};
        bw.write(c,0,4);

        //换行
        bw.newLine();

        //再次写入
        bw.write(c,2,2);

        //刷新流
        bw.flush();
        //其实关闭缓冲区,就是在关闭缓冲区中的流对象。
        bw.close();
    }
}

CharArrayWriter

CharArrayReader 用于写入数据符,它继承于Writer。操作的数据是以字符为单位!

1、CharArrayWriter的构造函数:

CharArrayWriter​() 创建一个新的CharArrayWriter。  
CharArrayWriter​(int initialSize) 用指定的初始大小创建一个新的CharArrayWriter。  

2、CharArrayWriter的方法列表:

CharArrayWriter append​(char c) 将指定的字符附加到此作者。  
CharArrayWriter append​(CharSequence csq) 将指定的字符序列附加到此作者。  
CharArrayWriter append​(CharSequence csq, int start, int end) 将指定字符序列的子序列附加到此作者。  
void close​() 关闭流。  
void flush​() 冲洗流。  
void reset​() 重置缓冲区,以便您可以再次使用它,而不会丢弃已经分配的缓冲区。  
int size​() 返回缓冲区的当前大小。  
char[] toCharArray​() 返回输入数据的副本。  
String toString​() 将输入数据转换为字符串。  
void write​(char[] c, int off, int len) 将字符写入缓冲区。  
void write​(int c) 将一个字符写入缓冲区。  
void write​(String str, int off, int len) 将一部分字符串写入缓冲区。  
void writeTo​(Writer out) 将缓冲区的内容写入另一个字符流。  

FilterWriter

FilterWriter是字符类型的过滤输出流。

1、FilterWriter的构造函数:

protected  FilterWriter​(Writer out) 创建一个新的过滤的作者。  

2、FilterWriter的方法列表:

void close​() 关闭流,先刷新。  
void flush​() 刷新流。  
void write​(char[] cbuf, int off, int len) 写入字符数组的一部分。  
void write​(int c) 写一个字符  
void write​(String str, int off, int len) 写一个字符串的一部分。  

PrintWriter 

PrintWriter 是字符类型的打印输出流,它继承于Writer。
1、PrintWriter 的构造方法:

PrintWriter​(File file) 使用指定的文件创建一个新的PrintWriter,而不需要自动的线路刷新。  
PrintWriter​(File file, String csn) 使用指定的文件和字符集创建一个新的PrintWriter,而不需要自动进行线条刷新。  
PrintWriter​(OutputStream out) 从现有的OutputStream创建一个新的PrintWriter,而不需要自动线路刷新。  
PrintWriter​(OutputStream out, boolean autoFlush) 从现有的OutputStream创建一个新的PrintWriter。  
PrintWriter​(Writer out) 创建一个新的PrintWriter,没有自动线冲洗。  
PrintWriter​(Writer out, boolean autoFlush) 创建一个新的PrintWriter。  
PrintWriter​(String fileName) 使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新。  
PrintWriter​(String fileName, String csn) 使用指定的文件名和字符集创建一个新的PrintWriter,而不需要自动线路刷新。  

2、PrintWriter 的方法列表:

PrintWriter append​(char c) 将指定的字符附加到此作者。  
PrintWriter append​(CharSequence csq) 将指定的字符序列附加到此作者。  
PrintWriter append​(CharSequence csq, int start, int end) 将指定字符序列的子序列附加到此作者。  
boolean checkError​() 如果流未关闭,请刷新流并检查其错误状态。  
protected void clearError​() 清除此流的错误状态。  
void close​() 关闭流并释放与之相关联的任何系统资源。  
void flush​() 刷新流。  
PrintWriter format​(String format, Object... args) 使用指定的格式字符串和参数将格式化的字符串写入此写入程序。  
PrintWriter format​(Locale l, String format, Object... args) 使用指定的格式字符串和参数将格式化的字符串写入此写入程序。  
void print​(boolean b) 打印布尔值。  
void print​(char c) 打印一个字符  
void print​(char[] s) 打印字符数组。  
void print​(double d) 打印双精度浮点数。  
void print​(float f) 打印浮点数。  
void print​(int i) 打印一个整数。  
void print​(long l) 打印一个长整数。  
void print​(Object obj) 打印一个对象。  
void print​(String s) 打印字符串。  
PrintWriter printf​(String format, Object... args) 使用指定的格式字符串和参数将格式化的字符串写入该writer的方便方法。  
PrintWriter printf​(Locale l, String format, Object... args) 使用指定的格式字符串和参数将格式化的字符串写入该writer的方便方法。  
void println​() 通过写入行分隔符字符串来终止当前行。  
void println​(boolean x) 打印一个布尔值,然后终止该行。  
void println​(char x) 打印一个字符,然后终止该行。  
void println​(char[] x) 打印字符数组,然后终止行。  
void println​(double x) 打印双精度浮点数,然后终止行。  
void println​(float x) 打印一个浮点数,然后终止该行。  
void println​(int x) 打印一个整数,然后终止该行。  
void println​(long x) 打印一个长整型,然后终止行。  
void println​(Object x) 打印一个对象,然后终止该行。  
void println​(String x) 打印一个字符串,然后终止行。  
protected void setError​() 表示发生错误。  
void write​(char[] buf) 写入一个字符数组。  
void write​(char[] buf, int off, int len) 写一个字符数组的一部分。  
void write​(int c) 写一个字符  
void write​(String s) 写一个字符串  
void write​(String s, int off, int len) 写一个字符串的一部分。  

Reader:字符输入流

有输出流那么当然就有输入流,Reader是字符输入流的基类,Reader的方法列表如下:

abstract void close​() 关闭流并释放与之相关联的任何系统资源。  
void mark​(int readAheadLimit) 标记流中的当前位置。  
boolean markSupported​() 告诉这个流是否支持mark()操作。  
int read​() 读一个字符  
int read​(char[] cbuf) 将字符读入数组。  
abstract int read​(char[] cbuf, int off, int len) 将字符读入数组的一部分。  
int read​(CharBuffer target) 尝试将字符读入指定的字符缓冲区。  
boolean ready​() 告诉这个流是否准备好被读取。  
void reset​() 重置流。  
long skip​(long n) 跳过字符  

同Writer一样,我们先来看一下FileReader的基本操作

FileReader

1、FileReader的构造方法:

FileReader​(File file) 创建一个新的 FileReader ,给出 File读取。  
FileReader​(FileDescriptor fd) 创建一个新的 FileReader ,给予 FileDescriptor从中读取。  
FileReader​(String fileName) 创建一个新的 FileReader ,给定要读取的文件的名称。  

2、FileReader的具体使用:

例1:

import java.io.*;

class  FileReaderDemo
{
	public static void main(String[] args) throws IOException
	{
		//创建一个文件读取流对象,和指定名称的文件相关联。
		//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
		FileReader fr = new FileReader("demo.txt");

		//调用读取流对象的read方法。
		//read():一次读一个字符。而且会自动往下读。
		
		int ch = 0;

		while((ch=fr.read())!=-1)
		{
			System.out.println("ch="+(char)ch);
		}

		//关闭流
		fr.close();

	}
}

例2:

/*
第二种方式:通过字符数组进行读取。
*/

import java.io.*;

class FileReaderDemo2 
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr = new FileReader("demo.txt");
		

		//定义一个字符数组。用于存储读到字符。
		//该read(char[])返回的是读到字符个数。
		char[] buf = new char[1024];

		int num = 0;
		while((num=fr.read(buf))!=-1)
		{
			System.out.println(new String(buf,0,num));
		}
		

		fr.close();
	}
}

BufferedReader

1、BufferedReader的构造方法

BufferedReader​(Reader in) 创建使用默认大小的输入缓冲区的缓冲字符输入流。  
BufferedReader​(Reader in, int sz) 创建使用指定大小的输入缓冲区的缓冲字符输入流。  

2、BufferedReader的方法列表:

void close​() 关闭流并释放与之相关联的任何系统资源。  
Stream lines​() 返回一个 Stream ,其元素是从这个 BufferedReader读取的行。  
void mark​(int readAheadLimit) 标记流中的当前位置。  
boolean markSupported​() 告诉这个流是否支持mark()操作。  
int read​() 读一个字符  
int read​(char[] cbuf, int off, int len) 将字符读入数组的一部分。  
String readLine​() 读一行文字。  
boolean ready​() 告诉这个流是否准备好被读取。  
void reset​() 将流重置为最近的标记。  
long skip​(long n) 跳过字符  

3、BufferedReader的具体使用:

例1:

/*
字符读取流缓冲区:
该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。
当返回null时,表示读到文件末尾。

readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。


*/

import java.io.*;

class  BufferedReaderDemo
{
	public static void main(String[] args) throws IOException
	{
		//创建一个读取流对象和文件相关联。
		FileReader fr = new FileReader("buf.txt");

		//为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。
		BufferedReader bufr = new BufferedReader(fr);
		

		String line = null;

		while((line=bufr.readLine())!=null)
		{
			System.out.print(line);
		}

          //关闭流
		bufr.close();
	}

}

例2:通过缓冲区复制文件:

/*
通过缓冲区复制一个.java文件。

*/
import java.io.*;

class  CopyTextByBuf
{
	public static void main(String[] args) 
	{
		BufferedReader bufr = null;
		BufferedWriter bufw = null;

		try
		{
			bufr = new BufferedReader(new FileReader("BufferedWriterDemo.java"));
			bufw = new BufferedWriter(new FileWriter("bufWriter_Copy.txt"));

			String line = null;

			while((line=bufr.readLine())!=null)
			{
				bufw.write(line);
				bufw.newLine();
				bufw.flush();

			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("读写失败");
		}
		finally
		{
			try
			{
				if(bufr!=null)
					bufr.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("读取关闭失败");
			}
			try
			{
				if(bufw!=null)
					bufw.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("写入关闭失败");
			}
		}
	}
}

字节流

字节流的基本操作和字符流类相同,但它不仅可以操作字符,还可以操作其他媒体文件

InputStream字节输入流

InputStream类是字节输入流的抽象类,是所有字节输入流的父类,InputStream类具有层次结构如下图所示:

InputStream的常用方法:

int available​() 从下一次调用此输入流的方法返回可从该输入流读取(或跳过)的字节数,而不会阻塞。  
void close​() 关闭此输入流并释放与流相关联的任何系统资源。  
void mark​(int readlimit) 标记此输入流中的当前位置。  
boolean markSupported​() 测试此输入流是否支持 mark和 reset方法。  
abstract int read​() 从输入流读取数据的下一个字节。  
int read​(byte[] b) 从输入流中读取一些字节数,并将它们存储到缓冲器阵列 b 。  
int read​(byte[] b, int off, int len) 从输入流读取最多 len个字节的数据到字节数组。  
byte[] readAllBytes​() 从输入流读取所有剩余字节。  
int readNBytes​(byte[] b, int off, int len) 将所请求的字节数从输入流读入给定的字节数组。  
void reset​() 将此流重新定位到最后在此输入流上调用 mark方法时的位置。  
long skip​(long n) 跳过并丢弃来自此输入流的 n字节的数据。  
long transferTo​(OutputStream out) 从该输入流中读取所有字节,并按读取的顺序将字节写入给定的输出流。  

FileInputStream 

1、FileInputStream的构造方法:

FileInputStream​(File file) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。  
FileInputStream​(FileDescriptor fdObj) 通过使用文件描述符 fdObj创建 FileInputStream ,该文件描述符表示与文件系统中的实际文件的现有连接。  
FileInputStream​(String name) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。  

2、FileInputStream的方法列表:

int available​() 返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。  
void close​() 关闭此文件输入流并释放与流相关联的任何系统资源。  
protected void finalize​() 已过时。 
finalize方法已被弃用。 为了执行清理而覆盖finalize子类应该修改为使用替代清理机制,并删除覆盖的finalize方法。 当覆盖finalize方法时,其实现必须明确确保按照super.finalize()所述调用super.finalize() 。 有关迁移选项的更多信息,请参阅Object.finalize()的规范。  
FileChannel getChannel​() 返回与此文件输入流相关联的唯一的FileChannel对象。  
FileDescriptor getFD​() 返回表示与此 FileInputStream正在使用的文件系统中的实际文件的连接的 FileDescriptor对象。  
int read​() 从该输入流读取一个字节的数据。  
int read​(byte[] b) 从该输入流读取最多 b.length个字节的数据到一个字节数组。  
int read​(byte[] b, int off, int len) 从该输入流读取最多 len个字节的数据到字节数组。  
long skip​(long n) 跳过并从输入流中丢弃 n字节的数据。  

3、FileInputStream的具体使用:

import java.io.*;
class  FileStream
{
	public static void main(String[] args) throws IOException
	{
		readFile_3();
	}

	//打开文件,一次读取刚刚好内容的字节
	public static void readFile_3()throws IOException
	{
		FileInputStream fis = new FileInputStream("fos.txt");
		
		//available()返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。 
		byte[] buf = new byte[fis.available()];//定义一个刚刚好的缓冲区。不用在循环了。

		fis.read(buf);

		System.out.println(new String(buf));

		fis.close();
	}


	//打开文件,一次读取多个字节
	public static void readFile_2()throws IOException
	{
		FileInputStream fis = new FileInputStream("fos.txt");

		byte[] buf = new byte[1024];
		int len = 0;
		while((len=fis.read(buf))!=-1)
		{
			System.out.println(new String(buf,0,len));
		}

		fis.close();
		
	}


	//打开文件,一次读取一个字节
	public static void readFile_1()throws IOException
	{

		FileInputStream fis = new FileInputStream("fos.txt");

		int ch = 0;

		while((ch=fis.read())!=-1)
		{
			System.out.println((char)ch);
		}

		fis.close();
	}

}

 

OutputStream 字节输出流

OutputStream字节输出流的方法:

void close​() 关闭此输出流并释放与此流相关联的任何系统资源。  
void flush​() 刷新此输出流并强制任何缓冲的输出字节被写出。  
void write​(byte[] b) 将 b.length字节从指定的字节数组写入此输出流。  
void write​(byte[] b, int off, int len) 从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。  
abstract void write​(int b) 将指定的字节写入此输出流。  

FileOutPutStream

1、FileOutPutStream的构造方法:

FileOutputStream​(File file) 创建文件输出流以写入由指定的 File对象表示的文件。  
FileOutputStream​(FileDescriptor fdObj) 创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。  
FileOutputStream​(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。  
FileOutputStream​(String name) 创建文件输出流以指定的名称写入文件。  
FileOutputStream​(String name, boolean append) 创建文件输出流以指定的名称写入文件。  

2、FileOutPutStream的方法列表:

void close​() 关闭此文件输出流并释放与此流相关联的任何系统资源。  
protected void finalize​() 已过时。 
finalize方法已被弃用。 为了执行清理,覆盖finalize子类应被修改为使用替代的清理机制,并删除覆盖的finalize方法。 当覆盖finalize方法时,其实现必须明确确保按照super.finalize()中所述调用super.finalize() 。 有关迁移选项的更多信息,请参阅Object.finalize()的规范。  
FileChannel getChannel​() 返回与此文件输出流相关联的唯一的FileChannel对象。  
FileDescriptor getFD​() 返回与此流相关联的文件描述符。  
void write​(byte[] b) 将 b.length字节从指定的字节数组写入此文件输出流。  
void write​(byte[] b, int off, int len) 将 len字节从指定的字节数组开始,从偏移量 off开始写入此文件输出流。  
void write​(int b) 将指定的字节写入此文件输出流。  

3、FileOutPutStream的具体使用:

import java.io.*;

public class FileStreamTest {

    private static final String FileName = "file.txt";

    public static void main(String[] args) {
        testWrite();
    }

    /**
     * FileOutputStream 演示函数
     *
     * 运行结果:
     * 在源码所在目录生成文件"file.txt",文件内容是“abcdefghijklmnopqrstuvwxyz0123456789”
     *
     * 加入,我们将 FileOutputStream fileOut2 = new FileOutputStream(file, true);
     *       修改为 FileOutputStream fileOut2 = new FileOutputStream(file, false);
     * 然后再执行程序,“file.txt”的内容变成"0123456789"。
     * 原因是:
     * (01) FileOutputStream fileOut2 = new FileOutputStream(file, true);
     *      它是以“追加模式”将内容写入文件的。即写入的内容,追加到原始的内容之后。
     * (02) FileOutputStream fileOut2 = new FileOutputStream(file, false);
     *      它是以“新建模式”将内容写入文件的。即删除文件原始的内容之后,再重新写入。
     */
    public static void testWrite() {
        try {
            // 创建文件“file.txt”对应File对象
            File file = new File(FileName);
            // 创建文件“file.txt”对应的FileOutputStream对象,默认是关闭“追加模式”
            FileOutputStream fileOut1 = new FileOutputStream(file);
            // 创建FileOutputStream对应的PrintStream,方便操作。PrintStream的写入接口更便利
            PrintStream out1 = new PrintStream(fileOut1);
            // 向“文件中”写入26个字母
            out1.print("abcdefghijklmnopqrstuvwxyz");
            out1.close();

            // 创建文件“file.txt”对应的FileOutputStream对象,打开“追加模式”
            FileOutputStream fileOut2 = new FileOutputStream(file, true);
            // 创建FileOutputStream对应的PrintStream,方便操作。PrintStream的写入接口更便利
            PrintStream out2 = new PrintStream(fileOut2);
            // 向“文件中”写入"0123456789"+换行符
            out2.println("0123456789");
            out2.close();

        } catch(IOException e) {
            e.printStackTrace();
        }
    }

  
}

File

JavaIo流中还有一个非常常用的类:File。

File 是“文件”和“目录路径名”的抽象表示形式。
File 直接继承于Object,实现了Serializable接口和Comparable接口。实现Serializable接口,意味着File对象支持序列化操作。而实现Comparable接口,意味着File对象之间可以比较大小;File能直接被存储在有序集合(如TreeSet、TreeMap中)。

1、File的构造方法:

File​(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例。  
File​(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。  
File​(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例。  
File​(URI uri) 通过将给定的 file: URI转换为抽象路径名来创建新的 File实例。  

2、File的方法列表:

boolean canExecute​() 测试应用程序是否可以执行此抽象路径名表示的文件。  
boolean canRead​() 测试应用程序是否可以读取由此抽象路径名表示的文件。  
boolean canWrite​() 测试应用程序是否可以修改由此抽象路径名表示的文件。  
int compareTo​(File pathname) 比较两个抽象的路径名字典。  
boolean createNewFile​() 当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。  
static File createTempFile​(String prefix, String suffix) 在默认临时文件目录中创建一个空文件,使用给定的前缀和后缀生成其名称。  
static File createTempFile​(String prefix, String suffix, File directory) 在指定的目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。  
boolean delete​() 删除由此抽象路径名表示的文件或目录。  
void deleteOnExit​() 请求在虚拟机终止时删除由此抽象路径名表示的文件或目录。  
boolean equals​(Object obj) 测试此抽象路径名与给定对象的相等性。  
boolean exists​() 测试此抽象路径名表示的文件或目录是否存在。  
File getAbsoluteFile​() 返回此抽象路径名的绝对形式。  
String getAbsolutePath​() 返回此抽象路径名的绝对路径名字符串。  
File getCanonicalFile​() 返回此抽象路径名的规范形式。  
String getCanonicalPath​() 返回此抽象路径名的规范路径名字符串。  
long getFreeSpace​() 通过此抽象路径名返回分区 named中未分配字节的数量。  
String getName​() 返回由此抽象路径名表示的文件或目录的名称。  
String getParent​() 返回此抽象路径名的父目录的路径名字符串,如果此路径名未命名为父目录,则返回 null 。  
File getParentFile​() 返回此抽象路径名的父目录的抽象路径名,如果此路径名不指定父目录,则返回 null 。  
String getPath​() 将此抽象路径名转换为路径名字符串。  
long getTotalSpace​() 通过此抽象路径名返回分区 named的大小。  
long getUsableSpace​() 通过此抽象路径名返回分区 named上此虚拟机可用的字节数。  
int hashCode​() 计算此抽象路径名的哈希码。  
boolean isAbsolute​() 测试这个抽象路径名是否是绝对的。  
boolean isDirectory​() 测试此抽象路径名表示的文件是否为目录。  
boolean isFile​() 测试此抽象路径名表示的文件是否为普通文件。  
boolean isHidden​() 测试此抽象路径名命名的文件是否为隐藏文件。  
long lastModified​() 返回此抽象路径名表示的文件上次修改的时间。  
long length​() 返回由此抽象路径名表示的文件的长度。  
String[] list​() 返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。  
String[] list​(FilenameFilter filter) 返回一个字符串数组,命名由此抽象路径名表示的目录中满足指定过滤器的文件和目录。  
File[] listFiles​() 返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件。  
File[] listFiles​(FileFilter filter) 返回一个抽象路径名数组,表示由此抽象路径名表示的满足指定过滤器的目录中的文件和目录。  
File[] listFiles​(FilenameFilter filter) 返回一个抽象路径名数组,表示由此抽象路径名表示的满足指定过滤器的目录中的文件和目录。  
static File[] listRoots​() 列出可用的文件系统根。  
boolean mkdir​() 创建由此抽象路径名命名的目录。  
boolean mkdirs​() 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。  
boolean renameTo​(File dest) 重命名由此抽象路径名表示的文件。  
boolean setExecutable​(boolean executable) 为此抽象路径名设置所有者的执行权限的便利方法。  
boolean setExecutable​(boolean executable, boolean ownerOnly) 设置该抽象路径名的所有者或每个人的执行权限。  
boolean setLastModified​(long time) 设置由此抽象路径名命名的文件或目录的最后修改时间。  
boolean setReadable​(boolean readable) 一种方便的方法来设置所有者对此抽象路径名的读取权限。  
boolean setReadable​(boolean readable, boolean ownerOnly) 设置此抽象路径名的所有者或每个人的读取权限。  
boolean setReadOnly​() 标记由此抽象路径名命名的文件或目录,以便只允许读取操作。  
boolean setWritable​(boolean writable) 一种方便的方法来设置所有者对此抽象路径名的写入权限。  
boolean setWritable​(boolean writable, boolean ownerOnly) 设置此抽象路径名的所有者或每个人的写入权限。  
Path toPath​() 返回从此抽象路径构造的一个java.nio.file.Path对象。  
String toString​() 返回此抽象路径名的路径名字符串。  
URI toURI​() 构造一个表示此抽象路径名的 file: URI。  
URL toURL​() 已过时。 此方法不会自动转义URL中非法的字符。 建议在新的代码转换的抽象路径到URL通过先转换成URI,经由toURI方法,然后经由转换URI为URL URI.toURL方法。  

3、File的具体使用:

例1:

import java.io.*;

/*
File类常见方法:
1,创建。
	boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
						和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。

	boolean mkdir():创建文件夹。
	boolean mkdirs():创建多级文件夹。
2,删除。
	boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
	void deleteOnExit();在程序退出时删除指定文件。


3,判断。
	boolean exists() :文件是否存在.
	isFile():
	isDirectory();
	isHidden();
	isAbsolute();

4,获取信息。
	getName():
	getPath():
	getParent():

	getAbsolutePath() 
	long lastModified() 
	long length() 

*/


class FileDemo 
{
	public static void main(String[] args) throws IOException
	{
		method_5();
	}

	public static void method_5()
	{
		File f1 = new File("c:\\Test.java");
		File f2 = new File("d:\\hahah.java");

		sop("rename:"+f2.renameTo(f1));

	}

	public static void method_4()
	{
		File f = new File("file.txt");

		sop("path:"+f.getPath());
		sop("abspath:"+f.getAbsolutePath());
		//该方法返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。
		//如果相对路径中有上一层目录那么该目录就是返回结果。
		sop("parent:"+f.getParent());						


	}
	
	public static void method_3()throws IOException
	{
		File f = new File("d:\\java1223\\day20\\file2.txt");
		//f.createNewFile();

		//f.mkdir();

		//记住在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在。
		//通过exists判断。
		sop("dir:"+f.isDirectory());
		sop("file:"+f.isFile());

		sop(f.isAbsolute());
	}


	public static void method_2()
	{
		File f = new File("file.txt");

		//sop("exists:"+f.exists());

		//sop("execute:"+f.canExecute());

		//创建文件夹
		File dir = new File("abc\\kkk\\a\\a\\dd\\ee\\qq\\aaa");

		sop("mkdir:"+dir.mkdirs());
	}
	

	public static void method_1()throws IOException
	{
		File f = new File("file.txt");
		sop("create:"+f.createNewFile());
		//sop("delete:"+f.delete());
		
	}


	//创建File对象
	public static void consMethod()
	{
		//将a.txt封装成file对象。可以将已有的和为出现的文件或者文件夹封装成对象。
		File f1 = new File("a.txt");

		File f2 = new File("c:\\abc","b.txt");

		File d = new File("c:\\abc");
		File f3 = new File(d,"c.txt");

		sop("f1:"+f1);
		sop("f2:"+f2);
		sop("f3:"+f3);

		File f4 = new File("c:"+File.separator+"abc"+File.separator+"zzz"+File.separator+"a.txt");


	}

	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

例2:递归列出指定目录下的文件或者文件夹

/*
列出指定目录下文件或者文件夹,包含子目录中的内容。
也就是列出指定目录下所有内容。

因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。
在列出过程中出现的还是目录的话,还可以再次调用本功能。
也就是函数自身调用自身。
这种表现形式,或者编程手法,称为递归。

递归要注意:
1,限定条件。

2,要注意递归的次数。尽量避免内存溢出。


*/

import java.io.*;

class FileDemo3 
{
	public static void main(String[] args) 
	{
		File dir = new File("E:\\Book");
		showDir(dir,0);
		
	}
	public static String getLevel(int level)
	{
		StringBuilder sb = new StringBuilder();
		sb.append("|--");
		for(int x=0; x

你可能感兴趣的:(Java基础系列8——IO流超详细总结)