------- android培训、java培训、期待与您交流! ----------
IO流是java很重要的知识点,在这里总结一下IO的一些知识点,常用的类以及用法。
按照操作的数据类型分,IO流分成两种:字节流和字符流。字节流抽象基类:InputStream,OutputStream;
字符流抽象基类:Reader,Writer;
IO流有很多衍生的类,但是大多以基类名称结尾,可以根据类名是以什么结尾的来区分是那种IO流;
缓冲区:提高数据读写效率。java对文件的读写效率相对比较低,次数越多,程序执行速度越低下,用缓冲区技术目的是减少对文件的读写次数,以此提高IO性能。缓冲区是针对流进行操作的,因此是和流结合使用的。以Buffered开头。
一.字符流常用类
(1)FileWriter类使用示例
<span style="font-size:14px;"> /**
FileWriter类使用示例
@param args
*/
public static void main(String[] args) {
FileWriter fw = null;
try {
// 此处会抛出异常,D盘下output.txt会被创建,此处true表示不覆盖之前同名的文件,新数据追加在后面
fw = new FileWriter("D:\\output.txt", true);
// 此处会抛出异常,写入流中,不会直接写入文件
fw.write("\n123abc");
} catch (IOException e) {
System.err.println(e.toString());
} finally {
try {
// 为了防止初始化失败(第10行)使此处fw为null出现空指针异常,需要进行空判断
if (null != fw) {
fw.close();//刷新并关闭
}
} catch (IOException e) {
System.err.println(e.toString());
}
}
}</span>
FileWriter 常用方法write()写字符,flush()刷新流程,close()先刷后关。
(2)FileReader类使用示例
文本文件读取示例,读取D盘下一个名字叫Input.txt的文本文件,不用担心换行,换行符会读取到并原样打印出来
<span style="font-size:14px;">/**
FileReader类使用示例
@param args
*/
public static void main(String[] args) {
FileReader fr = null;
char[] ch = new char[1024];
try {
// 读取D盘下的Input.txt文件,不存在抛出文件找不到异常
fr = new FileReader("D:\\Input.txt");
int num = 0;
while ((num = fr.read(ch)) != -1) {// 文件结尾时返回为-1,read(char[] ch)返回读取到的字符数
System.out.println(new String(ch));
}
} catch (IOException e) {
System.err.println("error info:" + e);
} finally {
try {
fr.close();
} catch (IOException e) {
System.err.println("error info" + e);
}
}
}</span>
FileReader 常用方法read:
可以读一个字符,也可以读一个数据,一般都是读数组,如上面的例;
read(char[] ch)返回读取的字符的个数,read()返回读取字符的ASCII码。字符流通过读取一个数组的方式复制一个文件(比较常用,推荐)
<span style="font-size:14px;">public static void main(String[] args) {
FileWriter fw = null;
FileReader fr = null;
try {
fw = new FileWriter("D:\\MyWorkSpace\\java\\IoDemoTest.txt");
fr = new FileReader("Exception.java");
char[] ch = new char[1024];
int len = 0;
while ((len = fr.read(ch)) != -1) {
fw.write(ch, 0, len);
}
} catch (IOException e) {
throw new RuntimeException("读写失败");
} finally {
if (null != fw) {
try {
fw.close();
} catch (IOException e) {
throw new RuntimeException("流关闭失败");
}
}
if (null != fr) {
try {
fr.close();
} catch (IOException e) {
throw new RuntimeException("流关闭失败");
}
}
}
}
</span>
(3)字符流缓冲区
字符流缓冲区示例,通过字符流缓冲区来复制一个文件
<span style="font-size:14px;">public static void main(String[] args) {
FileWriter fw = null;
FileReader fr = null;
BufferedWriter bufw = null;
BufferedReader bufr = null;
try {
fw = new FileWriter("D:\\BufferedReaderTest.txt");
fr = new FileReader("Exception.java");
bufw = new BufferedWriter(fw);
bufr = new BufferedReader(fr);
String strReadLine = "";
while ((strReadLine = bufr.readLine()) != null) {
bufw.write(strReadLine);
bufw.newLine();
bufw.flush();
}
} catch (IOException e) {
System.err.println("error info:" + e);
} finally {
try {
bufw.close();// 应该分别关这里图省事
bufr.close();
} catch (IOException e) {
System.err.println("error info" + e);
}
}
}</span>
二.字节流常用类
(1)FileInputStream,FileOutputStream类
使用示例,用字节流复制图片
<span style="font-size:14px;">public static void main(String[] args) {
FileOutputStream fos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream("D:\\1.bmp");
fos = new FileOutputStream("D:\\2.bmp");
int len = 0;
byte[] b = new byte[1024];
while ((len = fis.read(b)) != -1) {
fos.write(b, 0, len);
}
} catch (IOException e) {
System.err.println("error info:" + e);
} finally {
if (null != fis) {
try {
fis.close();
} catch (IOException e) {
throw new RuntimeException("文件输入流关闭失败");
}
}
if (null != fos) {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException("文件输出流关闭失败");
}
}
}
}</span>
FileInputStream 常用方法read(byte[] b)读取字节数组,close()关闭;
FileOutputStream 常用方法write(byte[] b, int off, int len),将字节数组中的固定起始的内容写入文件输出流,close关闭;
区别:FileOutputStream的flush继承自OutputStream,而OutputStream的flush不执行任何操作。因此FileOutputStream不需要执行flush。
(2)用字节流缓冲区复制Mp3
用法同之前的FileInputStream和FileOutputStream
<span style="font-size:14px;"><span style="font-size:12px;">public static void main(String[] args) {
BufferedInputStream bufIS = null;
BufferedOutputStream bufOS = null;
try {
bufIS = new BufferedInputStream(new FileInputStream("1.mp3"));
bufOS = new BufferedOutputStream(new FileOutputStream("2.mp3"));
int by = 0;
long start = System.currentTimeMillis();
while ((by = bufIS.read()) != -1) {
bufOS.write(by);
}
long end = System.currentTimeMillis();
System.out.println(end - start + "毫秒");
} catch (IOException e) {
throw new RuntimeException("error info" + e);
} finally {
try {
bufIS.close();
} catch (IOException e) {
throw new RuntimeException("error info" + e);
}
try {
bufOS.close();
} catch (IOException e) {
throw new RuntimeException("error info" + e);
}
}
}</span></span>
System.in返回的的是键盘的输入字节流
<span style="font-size:14px;">public static void main(String[] args) {
InputStream in = System.in;
int x = 0;
try {
while ((x = in.read()) != -1) {
System.out.println((char) (x + 1));
}
} catch (IOException e) {
throw new RuntimeException("键盘流读取失败啦");
} finally {
try {
in.close();
} catch (IOException e) {
throw new RuntimeException("键盘流读取失败啦");
}
}
}</span>
上面这种方法已经过时,在java 5以后 已经有新的类可以使用Scanner,Scanner的用法后面继续总结。
三.转换流
用来将字节流转换为字符流,方便使用字符流的readLine()等方法操作数据
(1)InputStreamReader,写入转换流
使用示例
<span style="font-size:14px;">/**
* 读取转换流示例
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
InputStream in = System.in;
// InputStreamReader将字节流转化为了字符流;
InputStreamReader inr = new InputStreamReader(in);
BufferedReader bufr = new BufferedReader(inr);
String str = "";
while ((str = bufr.readLine()) != null) {
if ("over".equals(str)) {
break;
}
System.out.println(str.toUpperCase());
}
}</span>
转化后,可以应用字符流缓冲区的readLine()方法来操作输入流;
(2) OutputStreamWriter,输出转换流
使用示例
<span style="font-size:14px;"> /**
* 输出转换流
* @param args
*/
public static void main(String[] args) {
BufferedReader bufr = new BufferedReader(new InputStreamReader(
System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(
System.out));
String str = "";
try {
while ((str = bufr.readLine()) != null) {
if ("over".equals(str)) {
break;
}
bufw.write(str);
bufw.newLine();// 相当于输出换行符
bufw.flush();
}
} catch (IOException e) {
throw new RuntimeException("转换流失败");
} finally {
try {
bufr.close();
} catch (IOException e) {
throw new RuntimeException("字符读取缓冲区关闭失败");
}
try {
bufw.close();
} catch (IOException e) {
throw new RuntimeException("字符输出缓冲区关闭失败");
}
}
}</span>
上例中展示的是转化后,可以应用字符流缓冲区的newLine()方法来输出跨平台的换行;
注意:OutputStreamWriter可以指定编码表,当涉及编码格式转化时也需要转换流。
1.IO异常的处理,需要格外注意,IO的new方法,读写,流的刷新关闭都会抛出IO异常,
2.流使用以后必须关闭,因此常把流的关闭放在finally代码块中。
3.流的建立遵循先建立引用,后建立对象,目的是将对象建立时候会抛出的异常放在try中捕获,同时不影响finally代码块中针对流对象的关闭。
4.流关闭的时候也会抛出异常,因此在finally中对流的关闭再次捕获异常。
5.对象初始化异常后,finally代码块就不需要再关闭,因此需要对流对象进行空判断。
(是不是很麻烦,习惯就好,这样最保险,养成好习惯最重要)
6.文件路径\\的问题,\表示转义,两个\才能表示\,例如:D:\\java\\1.txt