------------android培训、java培训、java学习型技术博客、期待与您交流! ------------
1.IO流概述
IO流用来处理设备之间的数据传输,例如与电脑硬盘之前的数据传输操作,JAVA对数据的操作是通过流的方式,JAVA用于操作流的对象都在IO包中
流按操作数据分为两种:字节流与字符流
流按流向分可以分为:输入流,输出流(Inpout/Output)
如何判断是输入流,还是输出流:以内存为参照,如果数据向内存流动,则是输入流,反之则为输出流.
2.常用基类
字节流抽象基类:
InputSteam,OutputStream
字符流抽象基类:
Reader,Writer
注:由这四个类派生出来的子类名称都是以其父类名作不子类名的后缀
如:InputStream的子类FileInputStream。
如:Reader的子类FileReader。
3.字符流
字符流的抽象基类:
|---->Reader:字符输入流
|---->Writer:字符输出流
FileWriter
FileWriter是Writer的一个子类,用来写入字符文件的便捷类
构造方法:
|--->FileWriter(File file)
根据给定的 File 对象构造一个 FileWriter 对象。
|--->FileWriter(File file, boolean append)
根据给定的 File 对象构造一个 FileWriter 对象。
|--->FileWriter(FileDescriptor fd)
构造与某个文件描述符相关联的 FileWriter 对象。
|--->FileWriter(String fileName)
根据给定的文件名构造一个 FileWriter 对象。
根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
可以实现文件的追加写入,第二个参数表示是否追加写入,默认是false,就会重头开始写入,如果是true,就会追加写入
常用方法:
|--->void write(String str):写入字符串。
|--->abstract void flush():刷新该流的缓冲
|--->abstract void close():关闭此流,但要先刷新它。
创建文件步骤:
1.创建流对象,建立数据存放文件,指定目的地
FileWriter fw = new FileWriter(“Test.txt”);
(注:该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖)
2.调用流对象的写入方法,将数据写入流
fw.write(“text”);
3.刷新流对象中的缓冲中的数据,将数据刷到目的地中。
//fw.flush();
4.关闭流资源,并将流中的数据清空到文件中。
fw.close();
注:close()与flush()区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
示例代码:
public class FileWriterDemo
{
public static void main(String[] args)
{
FileWriter fw = null;
try
{
fw = new FileWriter("Test.txt");
/* 1:创建了fw对象
* 2:底层调用了操作系统的资源创建了一个Test.txt文件
* 3:把fw对象指向Test.txt文件
*/
fw.write("text");//调用对象的写方法
fw.flush();刷新缓冲区
}
catch (IOException e)//写入异常
{
System.out.println(e.toString());
}
finally
{
if(fw!=null)
{
try
{
fw.close();//释放资源,关闭之前,会自动去调用flush方法。
}
catch (IOException e)//捕获关闭流异常
{
throw new RuntimeException("关闭流失败");
}
}
}
}
}
在文本后面追加操作示例:public class FileWriterDemo2
{
public static void main(String[] args) throws IOException
{
FileWriter fw = null;
try
{
fw = new FileWriter("fw2.txt",true);
for (int x = 0; x < 4; x++)
{
fw.write(x + "hello\r\n");// 调用writer方法
}
}
catch (IOException e)
{
throw new RuntimeException("写入失败");
}
finally// 释放资源
{
if(fw!=null)
{
try
{
fw.close();
}
catch (IOException e2)
{
throw new RuntimeException("关闭流失败");
}
}
}
}
}
FileReader
FileReader是Reader的一个子类,用来读取字符文件的便捷类
构造方法:
|--->FileReader(File file)
在给定从中读取数据的 File 的情况下创建一个新 FileReader。
|--->FileReader(FileDescriptor fd)
在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。
|--->FileReader(String fileName)
在给定从中读取数据的文件名的情况下创建一个新 FileReader。
两种读取方法:
|--->int read():读取单个字符。
|--->int read(char[] cbuf):将字符读入数组。
两种读取方法示例:
import java.io.*;
public class FileReaderDemo {
public static void main(String[] args)throws IOException
{
//第一种方式read();
FileReader fr = new FileReader("D:\\Demo\\sdfs.txt");
//创建一个文件读取流对象,和指定名称的文件相关联。
//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
int ch = 0;
while((ch = fr.read())!=-1)
{
System.out.print((char)ch);
}
fr.close();
System.out.println("\n-------------");
//第二种方式read(char[]);
FileReader fr2 = new FileReader("D:\\Demo\\sdfs.txt");
int i = 0;
char[] ch2 = new char[1024];
while((i = fr2.read(ch2))!=-1)
{
System.out.print(new String(ch2,0,i));
}
fr2.close();
}
}
练习:将C盘一个文本文件复制到D盘。
/*
复制的原理:
其实就是将C盘下的文件数据存储到D盘的一个文件中。
步骤:
1,在D盘创建一个文件。用于存储C盘文件中的数据。
2,定义读取流和C盘文件关联。
3,通过不断的读写完成数据存储。
4,关闭资源。
*/
import java.io.*;
public class CopyText
{
public static void main(String[] args) throws IOException
{
copy_2();
}
//通过read(char[])方法
public static void copy_2()
{
FileWriter fw = null;
FileReader fr = null;
try
{
//明确源文件和目的文件
fw = new FileWriter("D:\\456_copy.txt");
fr = new FileReader("C:\\456.txt");
//定义字符数组
char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1)//每次将数据读取到字符数组里面
{
fw.write(buf,0,len);//将字符数组里面的数据写到目的文件
}
}
catch (IOException e)//捕获IO操作的异常
{
throw new RuntimeException("读写失败");
}
finally//进行关闭资源操作
{
if(fr!=null)
try
{
fr.close();
}
catch (IOException e)
{
}
if(fw!=null)
try
{
fw.close();
}
catch (IOException e)
{
}
}
}
//从C盘读一个字符,就往D盘写一个字符。
public static void copy_1()throws IOException
{
//创建目的地。
FileWriter fw = new FileWriter("RuntimeDemo_copy.txt");
//与已有文件关联。
FileReader fr = new FileReader("RuntimeDemo.java");
int ch = 0;
while((ch=fr.read())!=-1)//读一个字符
{
fw.write(ch);//写一个字符
}
//关闭流
fw.close();
fr.close();
}
}
注意:
1.定义文件路径时,可以用“/”或者“\\”。
2.在创建一个文件时,如果目录下有同名文 件将被覆盖。
3.在读取文件时,必须保证该文件已存在, 否则出异常。
4.字符流缓冲区
缓冲区的出现提高了对数据的读写效率。要结合流才可以使用,在流的基础上对流的功能进行了增强。
对应类:
BufferedWriter (extends Reader)
BufferedReader (extends Writer)
这两个类同样具有内部缓存机制,并可以以行为单位进行输入/输出.
BufferedWriter
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。该缓冲区中提供了一个跨平台的换行符:newLine();
本类方法(全部方法返回类型void):
|--->close():关闭此流,但要先刷新它。
|--->flush():刷新该流的缓冲。
|--->newLine():写入一个行分隔符。 可跨平台使用
|--->write(char[] cbuf, int off, int len):写入字符数组的某一部分。
|--->write(int c):写入单个字符。
|--->write(String s, int off, int len):写入字符串的某一部分。
示例代码:
import java.io.*;
public class BufferedWriterDemo
{
public static void main(String[] args) throws IOException
{
//创建一个字符写入流对象。
FileWriter fw = new FileWriter("D:\\Demo\\sdfs.txt");
//为了提高字符写入流效率。加入了缓冲技术。
//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
BufferedWriter bufw = new BufferedWriter(fw);
for(int x=1; x<5; x++)
{
bufw.write("第"+x+"次写入");
bufw.newLine();
bufw.flush();//只要用到缓冲区,就要记得刷新。
}
//其实关闭缓冲区,就是在关闭缓冲区中的流对象。
bufw.close();
}
}
特别注意:用到缓冲区,就要记得刷新。
BufferedReader
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
该缓冲区提供了一个一次读一行的方法 readLine(),方便于对文本数据的获取。当返回null时,表示读到文件末尾。(注:readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。)
常用方法:
|--->void close():关闭该流并释放与之关联的所有资源。
|--->int read():读取单个字符。
|--->int read(char[] cbuf, int off, int len):将字符读入数组的某一部分。
|--->String readLine():读取一个文本行。
示例代码:
import java.io.*;
class BufferedReaderDemo
{
public static void main(String[] args) throws IOException
{
//创建一个读取流对象和文件相关联。
FileReader fr = new FileReader("D:\\Demo\\sdfs.txt");
//为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。
BufferedReader bufr = new BufferedReader(fr);
String line = null;//定义一个用作临时存储数据的变量
while((line=bufr.readLine())!=null)//返回值不为null就一直循环
{
System.out.print(line);
}
bufr.close();
}
}
练习:通过缓冲区高效的复制一个.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)//捕获IO操作异常
{
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("写入关闭失败");
}
}
}
}
自定义BufferedReader
自定义缓冲区,模拟BufferedReader代码示例:
import java.io.*;
class MyBufferedReader extends Reader
{
private Reader r;
MyBufferedReader(Reader r)
{
this.r = r;
}
//可以一次读一行数据的方法。
public String myReadLine()throws IOException
{
//定义一个临时容器。原BufferReader封装的是字符数组。
//为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
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类中的抽象方法。
*/
public int read(char[] cbuf, int off, int len) throws IOException
{
return r.read(cbuf,off,len) ;
}
public void close()throws IOException
{
r.close();
}
public void myClose()throws IOException
{
r.close();
}
}
class MyBufferedReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("buf.txt");
MyBufferedReader myBuf = new MyBufferedReader(fr);
String line = null;
while((line=myBuf.myReadLine())!=null)
{
System.out.println(line);
}
myBuf.myClose();
}
}
个人总结
其实个人觉得IO流的操作只要明白是怎么一个步骤就行了,然后就很能容易找到对应的类或者对应的方法,比如你是读取还是写入,是否需要效率。需要特别记住字符缓冲区两个特有的方法:newLine();readLine();有了这两个方法,在文本操作的时候更方便。