1.介绍
在实际开发过程中经常会用到数据的输入/输出操作,本篇博客着重分析一下,java中经经常使用到的有关IO操作的类。而在java中能够将经常使用的流分为两个部分:字节流和字符流。
1.流的抽象基类
字节流 字符流 输入流 InputStream Reader 输出流 OutPutStream Writer 正如上图表格所看到的。字符和字节流都有自己的基类,其余的都是继承基类的扩展流的操作。以下会着重的解说一下。(仅仅要会了字符流,字节流与其操作一样,仅仅只是操作的文件类型不一致而已)
2.字符流
专门用于读写文本数据。凡是能够用记事本打开的文件比如txt、java、html都数据字符流的操作范围
1.字符输出流——FileWriter
字符输出流一般应用的是FileWriter,然后调用其构造函数,传递字符串的文件名称,将字符写在这个文件里。其次调用父类方法Write(String str)写字符串。在这里须要注意的是字符流写数据,不会直接写在目的文件里。而是写在内存中,必须走一个方法,刷新。将内存中的数据刷新到目的文件里,字符流写数据必须刷新。一般调用的是Void Flush()方法,最后用完后须要关闭流对象。
<span style="font-family:SimSun;font-size:18px;"><span style="font-family:SimSun;font-size:18px;">package com.IO; import java.io.FileWriter;
import java.io.IOException; public class FileWriterDemo1 { public static void main(String[] args) {
FileWriter fw = null;
try {
//採用这样的形式的话。每次都会覆盖曾经的数据信息
// fw=new FileWriter("c:\\exception.txt");
//採用这样的构造器的话,将会採用追加的形式加入数据。
//查询本机默认编码表示GBK
fw=new FileWriter("c:\\exception.txt",true); fw.write("abd");
fw.flush();
fw.write("弄H啊哦吗");
fw.flush();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("文件写入失败"); }finally{
try {
//必须在这里进行推断否则,报错。可能会报空指针的异常信息。 if(fw!=null){
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("关闭资源失败");
}
}
} }
</span></span>FileWriter写文本文件操作例如以下
单个字符的形式。调用的父类Write(int c)方法
<span style="font-family:SimSun;font-size:18px;"><span style="font-family:SimSun;font-size:18px;">package cn.Io.iostream; import java.io.*;
class FileWriterDemo1
{
public static void main(String[] args)
{ //创建输出流对象
FileWriter fw = null;
try{
fw = new FileWriter("c:\\1.txt");
fw.write("abc");
fw.flush();
fw.write("adb");
//将内存中的数据刷新到文件里
fw.flush();
}catch(IOException e){
e.printStackTrace();
throw new RuntimeException("写入数据失败");
}finally{
try{
if(fw!=null)
fw.close();
}catch(IOException e){
e.printStackTrace();
throw new RuntimeException("关闭流对象失败");
} }
}
}
</span></span>字符数组的形式,调用的方法例如以下
~write(char[] ch)传递整个字符数组
~write(char[] ch,int off,int len)写数组的一部分,off開始下标。len个数
<span style="font-family:SimSun;font-size:18px;"><span style="font-family:SimSun;font-size:18px;">package cn.IO.iostream;
/*
* FileWriter以数组的形式写入文件
*
*/
import java.io.*;
public class FileWriterDemo2 {
public static void main(String[] args) throws IOException {
//调用此输出流的构造函数,将会以追加的形式写入到文件内容中
FileWriter fw = new FileWriter("c:\\demo.txt",true); fw.write(97); char[] ch= {'a','b','c'};
fw.write(ch,1,1);
fw.write("sefser");
fw.flush();
fw.close();
}
}
</span></span>注意,假设要想文件里追加写入内容,而不是覆盖原来的内容的话。仅仅需在创建输入流对象的时候,调用其
FileWriter(String fileName, boolean append)构造方法就可以
2.字符输入流
字符输入流一般应用的是FileReader读取文本文件。然后调用其构造方法,创建输入流对象。传递字符文件名称,比如new FileReader('文件名称')。读取一个字符 int read()方法。每次仅仅读取一个字符,然后指定的read()方法,会自己主动的向后读取一个,读到末尾的时候,将会返回-1
读取单个字符
<span style="font-family:SimSun;font-size:18px;"><span style="font-family:SimSun;font-size:18px;">package cn.IO.iostream;
/*
* 採用字符输入流对象。进行读取文件操作
*/
import java.io.*; public class FileReaderDemo {
public static void main(String[] args) throws IOException{
//创建输入流对象
FileReader fr = new FileReader("c:\\demo.txt");
//调用Read方法。每次仅仅读取一个字符操作
int x = 0;
while((x = fr.read())!=-1){
System.out.print((char)x);
}
fr.close();
}
} </span></span>读取字符数组操作
int read(char[] cbuf):读取方法,传递字符数组。返回值int代表有效读取的字符个数,此方法读取效率高
<span style="font-family:SimSun;font-size:18px;"><span style="font-family:SimSun;font-size:18px;">package cn.itcast.iostream;
/*
* 採用字符输入流对象进行字符数组的读取
*/
import java.io.*;
public class FileReaderDemo1 {
public static void main(String[] args) throws IOException{
FileReader fr = new FileReader("c:\\demo.txt");
//创建一个字符数组
char[] ch = new char[1024];//通常是1024的倍数
int x = 0 ;
while(( x = fr.read(ch))!=-1){
//String(char[] value, int offset, int count)
System.out.print(new String(ch,0,x));
}
fr.close();
}
}
</span></span>拷贝文件操作
利用字符流的输入和输出流,来操作文件的复制功能
第一种方式,读一个字符,写一个字符
<span style="font-family:SimSun;font-size:18px;"><span style="font-family:SimSun;font-size:18px;">package cn.IO.iostream;
/*
* 採用字符流来实现复制的功能
*/
import java.io.*;
public class CopyText {
public static void main(String[] args) {
long start = System.currentTimeMillis();
//创建字符输入和输出流的对象
FileReader fr = null;
FileWriter fw = null;
try{
//分别调用其构造函数
fr = new FileReader("c:\\demo.txt");
fw = new FileWriter("d:\\demo.txt");
//定义变量来报错单个字符读取的值
int len = 0 ;
while((len = fr.read())!=-1){
fw.write(len);
fw.flush();
}
}catch(IOException e){
throw new RuntimeException("复制失败");
}finally{
try{
if(fw!=null)
fw.close();
}catch(IOException e){
throw new RuntimeException("关闭写入流失败");
}finally{
try{
if(fr!=null)
fr.close();
}catch(IOException e){
throw new RuntimeException("关闭输入流失败");
}
}
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
</span></span>另外一种方法:读一个字符数组。写一个字符数组
<span style="font-family:SimSun;font-size:18px;"><span style="font-family:SimSun;font-size:18px;">package cn.IO.iostream;
/*
*採用输入和输出流完毕复制的功能操作
*/
import java.io.*;
public class CopyText2 {
public static void main(String[] args) {
long start = System.currentTimeMillis();
//分别创建字符输入和输出流对象
FileReader fr = null;
FileWriter fw = null;
try{
//分别调用其构造函数实例化
fr = new FileReader("c:\\e.html");
fw = new FileWriter("d:\\1.html");
//定义要读取的字符数组
char[] ch = new char[1024];
int len = 0 ;
while((len = fr.read(ch))!=-1){
fw.write(ch,0,len);
fw.flush();
}
}catch(IOException e){
throw new RuntimeException("复制失败");
}finally{
try{
if(fw!=null)
fw.close();
}catch(IOException e){
throw new RuntimeException("关闭输出流失败");
}finally{
try{
if(fr!=null)
fr.close();
}catch(IOException e){
throw new RuntimeException("关闭输入流失败");
}
}
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
</span></span>注意:利用读取字符数组的形式,效率会快非常多
3.缓冲流
在读写的时候。也能够採取缓冲流的形式对字符或者字节进行缓冲,从而实现字符、数组和行的高效读写操作。
字符 字节 缓冲输入流 BufferedReader BufferedInputStream 缓冲输出流 BufferedWriter BufferedOutputStream 主要是在缓冲流中能够採取读取一行方式。来操作源文件。
全部的操作都是一致的,都是通过构造方法的形式,传递字符或者字节流,比如BufferedReader(Reader r),来传递进去FileReader,通过String ReadLine()方法来读取文件的一行,当读到文件末尾的时候,将返回null值
<span style="font-family:SimSun;font-size:18px;">package com.IO; import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException; /*
* 字符输入流。BufferedReader,读取文本一行的功能
*/
public class BufferedReaderDemo { public static void main(String[] args) throws IOException { //建立字符输入流缓冲区对象,传递字符输入对象
BufferedReader bfr=new BufferedReader(new FileReader("c:\\1.txt")); //開始读取文本一行。返回string
String line=bfr.readLine();
System.out.println(line); } }
</span>其余的BufferedInputStream、BufferedOutPutStream、BufferedReader、BufferedWriter使用方法一致。參照上面写法就可以。
採用缓冲流实现文件复制的效果。
<span style="font-family:SimSun;font-size:18px;">package com.IO; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; import javax.management.RuntimeErrorException; /*
* 利用字符流缓冲区来赋值
* 读写行,写换行
*/
public class CopyTest2 {
public static void main(String[] args) {
// 匿名对象的形式。创建流对象和缓存去对象 BufferedReader bfr = null; BufferedWriter brw = null; try {
bfr = new BufferedReader(new FileReader("c:\\1.txt"));
brw = new BufferedWriter(new FileWriter("c:\\2.txt"));
// 读取一行,写一行,写换行
String line = null;
while ((line = bfr.readLine()) != null) {
brw.write(line);
//进行换行的功能
brw.newLine();
brw.flush();
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("复制失败");
}finally{
try {
if(bfr!=null){
bfr.close();
}
} catch (IOException e2) {
throw new RuntimeException("写入关闭失败");
}finally{
try {
if(brw!=null){
brw.close();
}
} catch (IOException e3) {
throw new RuntimeException("读入关闭失败");
}
}
}
} }
</span>
4.转换流
Java中的转换流一般有两个各自是,OutPutStreamWriter、InputStreamReader。是字符流通向字节流的桥梁。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbHVja3l6aG91c3Rhcg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
正如上图所看到的,通过缓冲流就能够把字节流转换成为字符流来处理,通过缓冲区一包装,就能够读取行的操作了。
<span style="font-family:SimSun;font-size:18px;">package com.IO; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter; public class TranseDemo3 {
public static void main(String[] args) throws IOException {
/*//控制台输入的字节流
InputStream in=new FileInputStream("c:\\1.java");
//创建转换流对象,传递字节输入流
InputStreamReader isr=new InputStreamReader(in);
//既然已经将in转换成了字符流isr,能够使用字符流缓冲区对象BufferedReader,行读取
BufferedReader bfr=new BufferedReader(isr); OutputStream out=System.out;
OutputStreamWriter osw=new OutputStreamWriter(out);
BufferedWriter bfw=new BufferedWriter(osw);*/ BufferedReader bfr=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter brw=new BufferedWriter(new OutputStreamWriter(System.out));
String line=null;
while ((line=bfr.readLine())!=null) {
brw.write(line);
brw.flush();
brw.newLine();
} brw.close();
bfr.close(); }
}
</span>