---------- android培训、java培训、期待与您交流! ----------
IO流主要是分为两类:字节流和字符流,他们都可以用来操作文件
其中字符流只要操作纯文本文件,里面嵌套了编码表,对文字进行编码。
字节流除了可以操作文本以外,还可以操作图片、音频、视频等文件,所以使用更广泛。
在java中对IO流的实现如下:
字节流的两个基类:InputStream(读)和OutputStream(写)
字符流的两个基类:Reader(读)和Writer(写)
JAVA中IO流整个体系的实现都是基于以上4个类实现的,基本结构是:例如FileWrite是操作文件对象的字符流Writer的子类,前缀名是该对流的功能,后缀名是父类名
下面我来总结下IO流中各个类的用法
字符流:Writer和Reader
FileWriter
FileWriter是用于对纯文本文件进行写入操作。
使用FileWriter读取纯文本文件的步骤:
1.创建一个FileWriter对象,该对象一被初始化就必须要明确杯操作的文件,而且该文件会被创建到指定目录下。如果该目录下已有同名文件,则被覆盖
FileWriter fw = new FileWriter("demo.txt");
2.调用write方法,将字符串写入到流中去。但此时还不会写到文件中去。
fw.write("abcde");
3.刷新该流对象缓冲中的数据,将数据写到指定文件中去
fw.flush();
4.关闭流资源,关闭之前会刷新一次缓冲中的数据。关闭流资源在IO中是必须要做的一件事。
fw.close;
一般完整的创建一个流对象的过程如下:
FileWriter fw = null;//先创建指向null
try{
fw = new FileWriter("d:\\demo.txt");
fw.write("qweqdasda");
}catch(IOException e){
System.out.println(e.toString());
}
finally{
try{
if(fw != null) //防止上面未创建成功,保证代码的健壮性
fw.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
FileReader
和FileWriter相对应的一个流对象,是用于对纯文本文件进行读取操作的。
使用FileReader读取纯文本文件的步骤如下:
1.创建一个FileReader对象,与制定名称的文件相关联。此时,要保证文件时存在的,如果不存在,会发生FileNotFoundException异常。
FileReader fr = new FileReader("demo.txt");
2.调用FileReader对象的read()方法,对文本进行读取,这是一次读一个字符,自动往下读,当读取完毕以后会返回-1
int ch = 0;
while((ch=fr.read())!=-1){
System.out.println(ch);//此时输入的是ASCLL码
}
3.关闭流资源,再次强调任何IO操作最终都要关闭流资源
fr.close();
BufferedWriter和BufferedReader
BufferedWriter和BufferedReader是在Writer和Reader的基础上加入了缓冲区,缓冲区的出现是为了提高流的效率,所以在创建缓冲区之前,必须要有一个流对象
BufferedWriter
在BufferedWriter中提供了一个跨平台的换行符:newLine()
因为换行符在windows下是"\r\n",在Linux下是"\n"
FileWriter fw = new FileWriter("demo.txt");
BufferedWriter bufw = new BufferedWriter(fw);
BufferedReader
该字符读取流缓冲区提高了一个一次读一行的方法readLine(),此方法的出现极大的方便了对文本数据的读取,当返回null的时候,表示读到了文件末尾。
readLine()方法返回一行数据的时候只返回回车符之前的数据内容,不返回回车符,所以要自己打回车符。
String line = null;
while((line=bufr.readLine())!=null){
System.out.print(line);
}
LineNumberReader
可以返回行号(getLineNumber())和设置开始行号(setLineNumber(int))。
字节流:InputStream和OutputStream
在字节流中也存在与上述4个方法类似的方法,他们操作文件的范围更加广泛,不仅可以操作纯文本文件,还可以操作图片、音频、视频等。
它们是FileOutputStream、FileInputStream、BufferedOutputStream、BufferedInputStream,基本操作与上述相对应的流对象类似。
需要注意的是:在BufferedInputStream中不存在一次性读取一行的操作readLine(),BufferedOutputStream中也不存在换行newLine()。
字节流转换为字符流:InputStreamReader和OutputStreamWriter
由于字节流中不存在像readLine()这种一次性读取一行的方法,但是readLine()又十分好用,所以就出现了转换流。
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in) );//最常用的键盘读取,可以一次读取一行
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
在转换流中可以对文本内容打开、读取的编码格式进行设置:
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("demo.txt"),"utf-8");
所以,转换流是连通字节流和字符流之间的桥梁,一般在涉及到字符编码的时候,需要用到转换流。
标准输入、输出设备
标准输入:System.in
标准输出:System.out
输入设备可以分为:键盘、硬盘、内存
输出设备可以分为:控制台、硬盘、内存
我们可以设置标准输入和输出的来源
System.setIn(InputStream in);
System.setOut(PrintStream out);
流操作的基本规律
三个明确:
1.明确源和目的:
源:输入流:InputStream、Reader
目的:输出流:OutputStream、Writer
2.明确操作的数据是否是纯文本
是纯文本:字符流
不是纯文本:字节流
是否要高效:来判断是否加上Buffered
3.明确要使用在哪个具体的对象上
源设备:内存ArrayStream、硬盘FileStream、键盘System.in
目的设备:内存ArrayStream、硬盘FileStream、控制台System.out
File对象
File类常见的方法:
1.创建:
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流一建立读写就会创建文件,如果文件已经存在则会覆盖。
2.删除:
boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();在程序退出时删除指定文件。
3.判断:
boolean exists():文件是否存在
boolean isFile():是否是文件,若文件不存在,还是会返回false
boolean isDirectory:是否是目录
boolean isHidden():是否隐藏
boolean isAbsolute():是否为绝对路径
4.获取信息:
getName():获取文件名
getPath():获取目录,此目录是封装成对象时候的目录
getParent():获取父目录,不存在则返回null
getAbsolutePath() :获取文件的绝对路径
long lastModified():获取文件的最好修改时间,返回时long,可以转换为Date
long length():获取文件的大小
renameTo(File dest) :重命名
5.文件列表
String[] list():返回此目录下的文件和文件件名称
File[] listRoots():得到系统的盘符
IO中的其他流对象
打印流:PrintStream和PrintWriter
该流对象提供了打印方法,可以将各种数据类型的数据原样打印。
字节打印流:PrintStream
构造函数可以接收的参数类型:
1.file对象:File
2.字符串路径:String
3.字节输出流:OutputStream
字符打印流:PrintWriter
1.file对象:File
2.字符串路径:String
3.字节输出流:OutputStream
4.字符输出流:Writer
合并流:SequenceInputStream
可以将2个及2个以上的InputStream对象合并成一个流对象,当有2个以上的InputStream的时候,要用到Enumeration
序列化对象:ObjectInputStream和ObjectOutputStream
ObjectInputStream的readObject(),用于读取对象
ObjectOutputStream的writerObjec(Object obj),用于存对象
这两个流对象是专门用来对对象进行读写的
当一个类,他的对象要被这两个流对象操作时,就必须要实现Serializable接口,这个接口没有任何方法,只是用于标记类。
Serializable接口的作用就在于,给每个要序列化的类一个唯一的UID,用于以后读的时候找到这个类。
但是要注意的时,类中的信息只要一改变,它的UID就会改变,此是就用可能读不出我们想要的数据了。
于是乎我们可以用这个来固定类的UID:static final long serialVersionUID = 42L;这样就算类改变了,还是可以找的到的。
还要注意一点,静态的变量不能被序列化,也就是说,你后期改变了它的值,他还是最初的值,不会变。
如果要想非静态的变量也不要序列化,则在变量前加transient则可以。
当存入多个对象的时候,readObject()会一个一个的去读出来。
管道流PipedInputStream和PipedOutputStream
数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream 读取,相当于一个管道一样,一头读,一头写。
RandomAccessFile
内部封装了一个大型byte数组,而且通过指针对数组的元素进行操作。
可以通过getFilePointer获取指针位置,
同时可以通过seek改变指针的位置。
也就是说可以对文件里面的内容随机访问。
可以实现文件的分段写入:用一个线程控制一段数据,分别写入。
基本数据类型的流对象DataOutputStream和DateInputStream
一系列读写基本数据类型的操作。
其中要注意:
writerUTF(DataInput in):修正后的UTF-8编码,只能用相对应的readUTF()去读取才行。
readUTF()
ByteArrayStream
ByteArrayInputStream
ByteArrayInputStream包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。
关闭 ByteArrayInputStream无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
ByteArrayOutputStream
此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。
---------- android培训、java培训、期待与您交流! ----------
详情请查看:http://edu.csdn.net/heima/