IO常用流及文件总结

一、 java.io.File类的使用

二、 IO原理及流的分类

三、 节点流(或文件流)

FileInputStream  /  FileOutputStream  /  FileReader  /  FileWriter

四、 处理流之一:缓冲流

BufferedInputStream / BufferedOutputStream

BufferedReader / BufferedWriter

五、 处理流之二:转换流

InputStreamReader  /  OutputStreamWriter

六、 处理流之三:标准输入/输出流

System.in / System.out

七、处理流之:四打印流

PrintStream  /  PrintWriter

八、处理流之:五数据流

DataInputStream  /  DataOutputStream

九、处理流之六对象流 (涉及序列化、反序列化)

ObjectInputStream  /  ObjectOutputStream

十、 随机存取文件流

RandomAccessFile

一、File类的使用

  •  java.io.File类:文件和目录路径名的抽象表示形式,与平台无关
  •  File 能新建、删除、重命名文件和目录, File 不能访问文件内容本身如果需要访问文件内容本身,则需要使用输入/输出流。般我们都会将File作为参数传入到IO流对象的构造器中。)
  •  File对象可以作为参数传递给流的构造器

1)访问文件名

getName()

getPath()

getAbsoluteFile()

getAbsolutePath()

getParent()

toPath()

renameTo(File newName)

2) 、文件检测

exists()

canWrite()

canRead()

isFile()

isDirectory()

3) 、获取常规文件信息

lastModified()

length()

4) 、文件操作相关

createNewFile()

delete()

5) 、目录操作相关

mkdir()

mkdirs()

delete()

list()

listFiles()

1)

绝对路径 :包含盘符在内的完整路径

相对路径 :相对某个项目的路径

renameTo(File newName) : 在同一个目录下:进行操作 - 可以重命名

不同的目录下:将当前文件移动到新的目录下然后重命名为   newName

3)

lastModified() //获取最后一次修改的时间

length() //文件大小

5)

mkdir() //创建目录,如果父目录存在则创建成功,否则创建失败

mkdirs() //创建目录,无论是否是父目录都会创建成功

delete() //删除目录

list() //String类型返回  目录下的  所有文件和目录名

listFiles() //File类型的方式返回 目录下 所有的文件和目录。

@Test

public void test(){

File file = new File("D:\\io\\io\\a\\a");

File file2 = new File("D:\\io\\io\\b\\b");

File file3 = new File("D:\\io");

String[] list = file3.list();

for (String string : list) {

System.out.println(string);

}

System.out.println("--------------------------");

File[] listFiles = file3.listFiles();

for (File file4 : listFiles) {

System.out.println(file4);

}

}

二、 IO流原理及流的分类

 

1IO流的原理

输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。

输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中

注:IO流是以程序为中心

 

2、流的分类

l 按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)  

l 按数据流的流向不同分为:输入流,输出流

l 按流的角色的不同分为:节点流,处理流

JavaIO流共涉及40多个类,实际上非常规则,都是从如下4个抽象基类派生的。由这四个类派生出来的子类名称都是以其父类名作为子类名后缀

 

节点流和处理流

l 节点流可以从一个特定的数据源读写数据

处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能

注:处理流/过滤流 有:缓冲流,转换流

 

InputStream & Reader

1)、InputStream Reader 是所有输入流的基类。

2)、InputStream:字节流(典型实现:FileInputStream

(1) int read()

(2) int read(byte[] c)

(3) int read(byte[] c, int off, int len)

3)、Reader:字符流(典型实现:FileReader

(4) int read()

(5) int read(char [] c)

(6) int read(char [] c, int off, int len)

4)、程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源

 

OutputStream & Writer

OutputStream Writer 也非常相似:

void write(int b/int c);

void write(byte[] b/char[] cbuf);

void write(byte[] b/char[] buff, int off, int len);

void flush();

void close(); 需要先刷新,再关闭此流

注:因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来替换字符数组,即以 String 对象作为参数

void write(String str);

void write(String str, int off, int len);

三、节点流(文件流)

    所有的文件在硬盘或在传输时都是以字节的方式进行的,包括图片等都是按字节的方式存储的,而字符是只有在内存中才会形成,所以在开发中,字节流使用较为广泛

   而且注意缓冲区是指在内存中,所以字节流可以字节操作文本而不需要经过缓存,即不用考虑关流也可以输出内容,但字符流需要在内存中缓存,当关闭字符流时缓存区里的内容才会输出,否则不会输出结果,即字符流使用了缓冲区,而字节流没有使用缓冲区。

另:如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点

1)、读取文件步骤:

1.建立一个流对象,将已存在的一个文件加载进流。

FileReader fr = new FileReader(Test.txt);

2.创建一个临时存放数据的数组。

char[] ch = new char[1024];

3.调用流对象的读取方法将流中的数据读入到数组中。

fr.read(ch);


2)、写入文件

1.创建流对象,建立数据存放文件

FileWriter fw = new FileWriter(Test.txt);

2.调用流对象的写入方法,将数据写入流

fw.write(text); 

3.关闭流资源,并将流中的数据清空到文件中。

fw.close();

 

注:

  • 定义文件路径时,注意:可以用“/”或者“\\”。
  • 在写入一个文件时,如果目录下有同名文件将被覆盖。 
  • 在读取文件时,必须保证该文件已存在,否则出异常。

注:字节流和字符流的使用:

  1.字符流常用来展示一些文本信息

  2.字节流一般用来复制文件,复制中文文本是不会出现乱码的

IOTest.java

public class IOTest {
	/*
	 * 字节流和字符流的使用:
	 * 1.字符流用来展示一些文本信息
	 * 2.字节流一般用来复制文件,复制中文文本是不会出现乱码的
	 */
	/*
	 * 字符流
	 */
	@SuppressWarnings("resource")
	@Test
	public void test() throws IOException{
		
		//第一步创建File对象
		//第二步创建流的对象
		//创建一个输入流
		FileReader fr = new FileReader(new File("aaa.txt"));
		//创建一个输出流
		FileWriter fw = new FileWriter(new File("bbb.txt"));
		//第三步读取数据
		char[] c = new char[100];
		int len = 0;
		while((len = fr.read(c))!= -1){
//		输出1、	System.out.println(new String(c,0,len));
//		输出2、	for (int i = 0; i < len; i++) {
//					System.out.print(c[i]);
//				}
			
			fw.write(c, 0, len);
		}		
		//第四步关流
		fr.close();
		fw.close();
	}
	/*
	 * 字节流
	 */
	@Test
	public void test2() throws Exception{
		FileInputStream fis = new FileInputStream(new File("char8.txt"));
		FileOutputStream fos = new FileOutputStream(new File("char9.txt"));
		
		byte[] b = new byte[1024];
		int len = 0;
		while((len = fis.read(b)) != -1){
//		输出1、	System.out.println(new String(b,0,len));
//		输出2、	for (int i = 0; i < len ; i++) {
//				System.out.print((char)b[i]);			
//			}
	
			fos.write(b, 0, len);
		}
		
		fis.close();
		fos.close();
		
	}
	
}

 

四、处理流之一 :缓冲流

1为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组

2对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush()将会使内存中的数据立刻写出

3根据数据操作单位可以把缓冲流分为:

BufferedInputStream BufferedOutputStream

BufferedReader BufferedWriter

4缓冲流“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法

注意:1)、关闭过滤流时,会自动关闭它所包装的底层节点流。但是我们最好还是要手动关闭字节流,应该如果字节流发生异常,我们需要处理,而包装在过滤流中可能就找不到包错的地方了。

2)、这里在读取文件时必须保证文件已存在

IOTest2.java

public class IOTest2 {

	/*
	 * 缓冲流
	 */
	@SuppressWarnings("resource")
	@Test
	public void test() {
		BufferedReader br = null;
		FileReader fr = null;
		FileWriter fw = null;
		BufferedWriter bw = null;
	 

		try {
			File file = new File("aaa.txt");
			// 创建流
			fr = new FileReader(file);
			// 创建缓冲流
			br = new BufferedReader(fr);

			// 创建流
			fw = new FileWriter(new File("fff.txt"));
			// 创建缓冲流
			bw = new BufferedWriter(fw);

			// 一边读一边写
			char[] c = new char[100];
			int len = 0;
			while ((len = br.read(c)) != -1) {
				bw.write(c, 0, len);
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			// 关流
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (fw != null) {
				try {
					fw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (fr != null) {
				try {
					fr.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

		}

	}

	/*
	 * readLine() : 读取一行字符
	 */
	@Test
	public void test2() throws Exception {
		BufferedReader br = null;
		FileReader fr = null;
		FileWriter fw = null;
		BufferedWriter bw = null;

		File file = new File("fff.txt");
		// 创建流
		fr = new FileReader(file);
		// 创建缓冲流
		br = new BufferedReader(fr);

		// 创建流
		fw = new FileWriter(new File("eee.txt"));
		// 创建缓冲流
		bw = new BufferedWriter(fw);

		// 一边读一边写
//		String string = br.readLine();
//		System.out.println(string);
//		System.out.println(br.readLine());
		
		String str = null;
		while((str = br.readLine()) != null){
			bw.write(str);
			bw.newLine();
		}
		//关流
		bw.close();
		br.close();
		fw.close();
		fr.close();

	}
}

 五、处理流之二:转换流


转换流提供了在字节流和字符流之间的转换

Java API提供了两个转换流:

InputStreamReaderOutputStreamWriter

字节流中的数据都是字符时,转成字符流操作更高效。

Reader和Writer最重要的子类是InputStreamReader和OutputStreamWriter类。

InputStreamReader类包含了一个底层输入流可以从中读取原始字节。它根据指定的编码方式,将这些字节转换为Unicode字符。

OutputStreamWriter从运行的程序中接收Unicode字符,然后使用指定的编码方式将这些字符转换为字节,再将这些字节写入底层输出流中。


作用一

1)、InputStreamReader:用于将 字节流中读取到的字节 按指定字符集解码成字

2)OutputStreamWriter:用于将 要写入到字节流中的字符 按指定字符集编码成字

 构造方法

public InputStreamReader(InputStream in)
public InputSreamReader(InputStream in, String charsetName)

 构造方法
public OutputStreamWriter(OutputStream out)
public OutputSreamWriter(OutputStream out,String charsetName)

作用二

 注意一下这个标红的是可以在转换的过程指定要转化的编码集

 

InputStreamTest.java
public class InputStreamTest {
	/*
	 * InputStreamReader
	 * 两个作用:
	 * 1.可以将字节流转换成字符流
	 * 2.可以改变文本的编码集- 比如读取文件是gbk那么写出的文件可以转成utf-8
	 */
	@Test
	public void test() throws Exception{
		
		File file = new File("fff.txt");
		FileInputStream fis = new FileInputStream(file);
		InputStreamReader isr = new InputStreamReader(fis);	
		//BufferedReader br = new BufferedReader(isr);	
		
		
		char[] c = new char[100];
		int len = 0;
		while((len = isr.read(c)) != -1){
			for (int i = 0; i < len; i++) {
				System.out.print(c[i]);
			}
		}
		
		isr.close();
		fis.close();
	}
	/*
	 * 一边读一边写
	 */
	@Test
	public void test2() throws Exception{
		
		File file = new File("char8.txt");
		FileInputStream fis = new FileInputStream(file);
		/*
		 * InputStreamReader(InputStream in, String charsetName)
		 * 
		 * charsetName :编码集
		 * 
		 * 注意:读取的文件的编码集必须和charsetName编码集格式一致
		 */
		InputStreamReader isr = new InputStreamReader(fis,"gbk");
		File file2 = new File("xiaocang2.txt");
		FileOutputStream fos = new FileOutputStream(file2);
		OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
		
		
		char[] c = new char[100];
		int len = 0;
		while((len = isr.read(c)) != -1){
			osw.write(c, 0, len);
		}
		
		osw.close();
		isr.close();
		fos.close();
		fis.close();
	}
}

什么时候用转化流?

1)、源设备或目标设备是字节流,但是操作的却是文本数据

2)、一旦操作文本涉及到具体的指定编码表时,必须使用转换流

另: 

常见的字符编码表:

  • ASCII:美国标准信息交换码。
    用一个字节的7位可以表示。
  • ISO8859-1:拉丁码表。欧洲码表
    用一个字节的8位表示。
  • GB2312:中国的中文编码表。
  • GBK:中国的中文编码表升级,融合了更多的中文文字符号。
  • Unicode:国际标准码,融合了多种文字。
    所有文字都用两个字节来表示,Java语言使用的就是unicode
  • UTF-8:最多用三个字节来表示一个字符

  1. 编码:字符串→字节数组
  2. 解码:字节数组→字符串

六、处理流之三:标准输入/输出流

  • System.in和System.out分别代表了系统标准的输入和输出设备
        默认输入设备是键盘,输出设备是显示器
  • System.in的类型是InputStream,System.out的类型是PrintStream,其是FilterOutputStream 的子类、OutputStream的子类
  • 通过System类的setIn,setOut方法对默认设备进行改变。
    public static void setIn(InputStream in)

    public static void setOut(PrintStream ou)

SystemTes.java

public class SystemTest {

	@Test
	public void test(){
		
		System.out.println("aaaa");
		
		new Scanner(System.in);
	}
	
	/*
	 * 从键盘输入字符串,要求将读取到的整行字符串转成大写输出。
	 * 然后继续进行输入操作,直至当输入“e”或者“exit”时,退出程序。
	 */
	@Test
	public void test2() throws Exception{
		//创建一个转换流
		InputStreamReader isr = new InputStreamReader(System.in);
		//创建一个缓冲流
		BufferedReader br = new BufferedReader(isr);
		
		String str = null;
		
		while((str = br.readLine()) != null){
			if("e".equalsIgnoreCase(str) || "exit".equalsIgnoreCase(str)){
				//关流
				br.close();
				isr.close();
				return;
			}else{
				System.out.println(str.toUpperCase());
			}
		}
		
		br.close();
		isr.close();
	}
}
七、处理流之四:打印流

  • 实现将基本数据类型的数据格式转化为字符串输出
  • 打印流:PrintStream和PrintWriter提供了一系列重载的print和println方法,用于多种数据类型的输出
  • PrintStream和PrintWriter的输出不会抛出异常
  • PrintStream和PrintWriter有自动flush功能
  • System.out返回的是PrintStream的实例

PrintStreamTest.java

public class PrintStreamTest {

	@Test
	public void test() {
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(new File("text.txt"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} 
		
		// 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
		PrintStream ps = new PrintStream(fos, true);
		if (ps != null) { 
			// 把标准输出流(控制台输出)改成文件
			System.setOut(ps);
		}
		for (int i = 0; i <= 255; i++) { // 输出ASCII字符
			System.out.print("A");
			if (i % 50 == 0) { // 每50个数据一行
				System.out.println(); // 换行
			}
		}
		ps.close();

	}
}

八、处理流之五:数据流

  • 为了方便地操作Java语言的基本数据类型的数据,可以使用数据流。
  • 数据流有两个类:(用于读取和写出基本数据类型的数据)
        DataInputStream 和 DataOutputStream
        分别“套接”在 InputStream 和 OutputStream 节点流上
  • DataInputStream中的方法
     boolean readBoolean() byte readByte()
     char readChar()         float readFloat()
     double readDouble()         short readShort()
     long readLong()         int readInt()
     String readUTF()                         void readFully(byte[] b)
  • DataOutputStream中的方法
        将上述的方法的read改为相应的write即可。

DataTest.java

public class DataTest {

	@Test
	public void test() throws Exception{
		
		FileInputStream fis = new FileInputStream(new File("ccc.dat"));
		DataInputStream dis = new DataInputStream(fis);
		
		
		String string = dis.readUTF();
		double readDouble = dis.readDouble();
		boolean readBoolean = dis.readBoolean();
		int readInt = dis.readInt();
		
		System.out.println(readDouble);
		System.out.println(readBoolean);
		System.out.println(readInt);
		System.out.println(string);
		
		dis.close();
		fis.close();
		
	}

	@Test
	public void test2() throws Exception{
		
		FileOutputStream fos = new FileOutputStream(new File("ccc.dat"));
		DataOutputStream dos = new DataOutputStream(fos);
		
		dos.writeUTF("abcdef");
		dos.writeDouble(12.3);
		dos.writeBoolean(true);
		dos.writeInt(15);
		
		
		dos.close();
		fos.close();
	}
}


九、处理流之六:对象流

  • ObjectInputStream和OjbectOutputSteam
            用于存储和读取基本数据类型数据或对象的处理流。 它的强大之处就是可以把Java中的对象写入到数据源中也能把对象从数据源中还原回来

  • 序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
  • 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
  • ObjectOutputStream和ObjectInputStream不能序列化static修饰的成员变量
  • 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
  • 序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原
  • 序列化是 RMI(Remote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI 是 JavaEE 的基础。因此序列化机制是 JavaEE 平台的基础
  • 如果需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:

            Serializable
            Externalizable

  • 凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
    private static final long serialVersionUID;
    serialVersionUID用来表明类的不同版本间的兼容性
  •     如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的源代码作了修改,serialVersionUID 可能发生变化。故建议,显示声明
  • 显示定义serialVersionUID的用途:
        希望类的不同版本对序列化兼容,因此需确保类的不同版本具有相同的serialVersionUID
        不希望类的不同版本对序列化兼容,因此需确保类的不同版本具有不同的serialVersionUID

    强调:如果某个类的字段不是基本数据类型或 String  类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的 Field 的类也不能序列化

1)、序列化

若某个类实现了 Serializable 接口,该类的对象就是可序列化的:

创建一个 ObjectOutputStream
调用 ObjectOutputStream 对象的 writeObject(对象) 方法 输出可序列化对象。 注意写出一次,操作flush()
2)、反序列化
创建一个 ObjectInputStream
调用 readObject() 方法 读取流中的对象

person.java

/*
 * 序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
 * 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
 */
public class ObjectTest {
	@Test
	public void test2() throws Exception{
		
		FileInputStream fis = new FileInputStream("abc.txt");
		ObjectInputStream ois = new ObjectInputStream(fis);
		
		Person p = (Person) ois.readObject();
		System.out.println(p.toString());
		
		ois.close();
		fis.close();		
	}
	
	/*
	 * 要求:
	 * 1.需要被序列化对象的类,必须实现Serializable接口。
	 * 类中的属性除基本类型外也需要实现Serializable接口
	 * 2.private static final long serialVersionUID;用来表明类的不同版本间的兼容性
	 * 实体类中可以省略,系统会自动生成
	 */
	@Test
	public void test() throws Exception{
		FileOutputStream fos = new FileOutputStream("abc.txt");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		
		Person person = new Person(18, "小容" ,new Address("110"));
		oos.writeObject(person);
		
		oos.close();
		fos.close();
	}
}


注:test()中通过序列化写入文本中一个对象,但文本中显示的是乱码,需要通过test2()反序列化输出到控制台就可以看到完整内容了

十、随机存取文件流

  • RandomAccessFile 类支持 “随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件
    支持只访问文件的部分内容
    可以向已存在的文件后追加内容
  • RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。RandomAccessFile 类对象可以自由移动记录指针:
    long getFilePointer():获取文件记录指针的当前位置
    void seek(long pos):将文件记录指针定位到 pos 位置

  • RandomAccessFile 类支持 “随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件
    支持只访问文件的部分内容
    可以向已存在的文件后追加内容
  • RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。RandomAccessFile 类对象可以自由移动记录指针:
    long getFilePointer() :获取文件记录指针的当前位置
    void seek(long pos) :将文件记录指针定位到 pos 位置

RandomAccessTest.java

/*
 * 随机存取文件流 :即可以读也可以写
 * 
 * 
 */
public class RandomAccessTest {

	/*
	 * 读
	 */
	@Test
	public void test() throws Exception{
		RandomAccessFile raf = new RandomAccessFile("AA.txt", "rw");
		byte[] b = new byte[100];
		int len = 0;
		while((len = raf.read(b)) != -1){
			System.out.println(new String(b,0,len));
		}
		raf.close();
	}
	
	/*
	 * 写
	 */
	@Test
	public void test2() throws Exception{
		RandomAccessFile raf = new RandomAccessFile("AA.txt", "rw");
		raf.write("hello heng".getBytes());
		raf.close();
	}
	/*
	 * 实现文件内容的插入
	 * 功能 :在abcdefg 的 b和c的位置插入AAA,在一行的插入文本
	 */
	@Test
	public void test3() throws Exception{
		RandomAccessFile raf = new RandomAccessFile("BB.txt", "rw");
		//第一步  移动指针到c的位置
		raf.seek(2);
		//第二步  读取c到最后的数据。注意:指针会移到最后
		String str = raf.readLine();
		//第三步 指针回移
		raf.seek(2);
		//第四步 写插入的内容
		raf.write("AAA".getBytes());
		//第五步 写读取的内容
		raf.write(str.getBytes());
		//第六步 关流
		raf.close();
	}
	
	/*
	 *  功能 :在
	 *  abcdefg
	 *  bbb
	 *  ccc
	 *  dd
	 *  的 b和c的位置插入AAA
	 *  在多行文本的插入
	 */
	@Test
	public void test4() throws Exception{
		RandomAccessFile raf = new RandomAccessFile("BB.txt", "rw");
		//第一步  移动指针到c的位置
		raf.seek(2);
		//第二步  读取c到最后的数据。注意:指针会移到最后
		String str = "";
		byte[] b = new byte[100];
		int len = 0;
		while((len = raf.read(b)) != -1){
			str += new String(b,0,len);
		}
		
		//第三步 指针回移
		raf.seek(2);
		//第四步 写插入的内容
		raf.write("AAA".getBytes());
		//第五步 写读取的内容
		raf.write(str.getBytes());
		//第六步 关流
		raf.close();
	}
}



猜你喜欢

转载自blog.csdn.net/mxcsdn/article/details/80294010