您的位置:首页 > 职场人生

黑马程序员————IO流2(day19)

2013-08-31 11:41 351 查看
----------------------ASP.Net+Android+IOS开发----------------------期待与您交流!
 
 

IO流2

BufferedWriter


BufferedReader


通过缓冲区复制文本文件


装饰设计模式


LineNumberReader


字节流File读写操作


拷贝图片


字节流的缓冲区


读取键盘录入


读取转换流


写入转换流


流操作规律


异常的日志信息


系统信息

 
 
BufferedWriter
字符流的缓冲区
缓冲区的出现提高了对数据的读写效率。
 
对应类:BufferedWriter
BufferedReader
 
缓冲区要结合流才可以使用,在流的基础上对流的功能进行了增强。
 
缓冲区的出现是为了提高流的操作效率而出现的,所以在创建缓冲区之前,必须要先有流对象。
该缓冲区中提供了一个跨平台的换行符。newLine();
 
示例:
import java.io.*;

class BufferedWriterDemo {
public static void main(String[] args) {
// 创建一个字符写入流对象。
FileWriter fw = null;
BufferedWriter bufw = null;

try {
fw = new FileWriter("buf.txt");

// 为了提高字符写入流效率。加入了缓冲技术。
// 只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
bufw = new BufferedWriter(fw);

for (int x = 1; x < 5; x++) {
bufw.write("abcd" + x);
bufw.newLine();// 换行
bufw.flush();// 记住,只要用到缓冲区,就要记得刷新。
}
} catch (IOException e) {
System.out.println(e.toString());
} finally {
if (bufw != null) {
// 其实关闭缓冲区,就是在关闭缓冲区中的流对象。
try {
bufw.close();
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
}
}


 

BufferedReader
字符读取流缓冲区
该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取,当返回null时,表示读到文件末尾。
readLine()方法返回的时候只返回回车符之前的数据内容。并不返回回车符。
 
示例:
import java.io.*;

class BufferedReaderDemo {
public static void main(String[] args) {
// 创建一个读取流对象和文件相关联。
FileReader fr = null;
// 创建字符流读取缓冲区
BufferedReader bufr = null;

try {
fr = new FileReader("buf.txt");
bufr = new BufferedReader(fr);

// 为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。
String line = null;
while ((line = bufr.readLine()) != null) {
System.out.print(line);
}
} catch (IOException e) {
System.out.println(e.toString());
} finally {
if (bufr != null) {
try {
bufr.close();
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
}
}


 

通过缓冲区复制文本文件
通过缓冲区复制一个.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) {
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("写入关闭失败");
}
}
}
}


 

装饰设计模式
装饰设计模式
当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能,那么自定义的该类称为装饰类。
 
装饰类通常会通过构造方法接收被装饰的对象。并基于被装饰的对象的功能,提供更强的功能。
 
示例:
class Person {
public void chifan() {
System.out.println("吃饭");
}
}

class SuperPerson {
private Person p;

SuperPerson(Person p) {
this.p = p;
}

public void superChifan() {
System.out.println("开胃酒");
p.chifan();
System.out.println("甜点");
System.out.println("来一根");
}
}

class PersonDemo {
public static void main(String[] args) {
Person p = new Person();
SuperPerson sp = new SuperPerson(p);
sp.superChifan();
}
}


 

以前是通过继承将每一个子类都具备缓冲功能,那么继承体系会复杂,并不利于扩展。
现在优化思想,单独描述一下缓冲内容。将需要被缓冲的对象,传递进来,也就是,谁需要被缓冲,谁就作为参数传递给缓冲区,这样继承体系就变得很简单。优化了体系结构。
装饰模式比继承要灵活,避免了继承体系臃肿,而且降低了类于类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能,所以装饰类和被装饰类通常是都属于一个体系中的。
 
 
LineNumberReader
让读取的文本文件带有行号
 
示例:
import java.io.*;

class LineNumberReaderDemo {
public static void main(String[] args) {
FileReader fr = null;
LineNumberReader lnr = null;

try {
fr = new FileReader("PersonDemo.java");
lnr = new LineNumberReader(fr);

String line = null;
//lnr.setLineNumber(100);// 改变行号从101开始
while ((line = lnr.readLine()) != null) {
// 带有行号
System.out.println(lnr.getLineNumber() + ":" + line);
}
} catch (IOException e) {
System.out.println(e.toString());
} finally {
try {
if (lnr != null)
lnr.close();
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
}

 
字节流File读写操作
字节流
字节流类为处理字节式输入/输出提供了丰富的环境。一个字节流可以和其他任何类型的对象并用,包括二进制数据。这样的多功能性使得字节流对很多类型的程序都很重要。因为字节流类以InputStream和OutputStream为顶层。
InputStream
输入字节流,是一个定义类Java流式字节输入模式的抽象类,该类的所有方法在出错时都会引发一个IOException异常。
OutputStream
输出字节流,是定义了流式字节输出模式的抽象类,该类的所有方法返回一个void值并且在出错的情况下引发一个IOException异常。
 
示例:
import java.io.*;

class FileStream {
public static void main(String[] args) {
readFile_3();
}

// 输出字节流,定义刚好的缓冲区
public static void readFile_3() {
FileInputStream fis = null;

try {
fis = new FileInputStream("fos.txt");

byte[] buf = new byte[fis.available()];// 定义一个刚刚好的缓冲区。不用在循环了。
fis.read(buf);
System.out.println(new String(buf));
} catch (IOException e) {
System.out.println(e.toString());
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
System.out.println(e.toString());
}
}
}

// 输出字节流,读一行
public static void readFile_2() {
FileInputStream fis = null;

try {
fis = new FileInputStream("fos.txt");

byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
System.out.println(new String(buf, 0, len));
}
} catch (IOException e) {
System.out.println(e.toString());
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
System.out.println(e.toString());
}
}
}

// 输出字节流,读一个写一个
public static void readFile_1() {
FileInputStream fis = null;

try {
fis = new FileInputStream("fos.txt");

int ch = 0;
while ((ch = fis.read()) != -1) {
System.out.println((char) ch);
}
} catch (IOException e) {
System.out.println(e.toString());
} finally {
try {
if (fis != null)
fis.close();
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
// 输入字节流
public static void writeFile() {
FileOutputStream fos = null;

try {
fos = new FileOutputStream("fos.txt");
fos.write("abcde".getBytes());
} catch (IOException e) {
System.out.println(e.toString());
} finally {
try {
if (fos != null)
fos.close();
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
}


 

拷贝图片
复制一个图片
 
思路:
1.      用字节读取流对象和图片关联。
2.      用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3.      通过循环读写,完成数据的存储。
4.      关闭资源。
 
示例:
import java.io.*;

class CopyPic {
public static void main(String[] args) {
FileOutputStream fos = null;
FileInputStream fis = null;
try {
fos = new FileOutputStream("d:\\2.jpg");
fis = new FileInputStream("d:\\1.jpg");

byte[] buf = new byte[1024];

int len = 0;

while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
} catch (IOException e) {
throw new RuntimeException("复制文件失败");
} finally {
try {
if (fis != null)
fis.close();
} catch (IOException e) {
throw new RuntimeException("读取关闭失败");
}
try {
if (fos != null)
fos.close();
} catch (IOException e) {
throw new RuntimeException("写入关闭失败");
}
}
}
}


 

字节流的缓冲区
演示mp3的复制,通过缓冲区:
BufferedOutputStream
BufferedInputStream
 
示例:
import java.io.*;

class CopyMp3 {
public static void main(String[] args) {
long start = System.currentTimeMillis();
copy_2();
long end = System.currentTimeMillis();

System.out.println((end - start) + "毫秒");
}

public static void copy_2() {
BufferedInputStream bufis = null;
BufferedOutputStream bufos = null;

try {
bufis = new BufferedInputStream(new FileInputStream("d:\\1.mp3"));
bufos = new BufferedOutputStream(new FileOutputStream("d:\\2.mp3"));

int by = 0;
while ((by = bufis.read()) != -1) {
bufos.write(by);
}
} catch (IOException e) {
System.out.println(e.toString());
} finally {
try {
if (bufos != null) {
bufos.close();
}
} catch (IOException e) {
System.out.println(e.toString());
}
try {
if (bufis != null) {
bufis.close();
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
}

// 通过字节流的缓冲区完成复制。
public static void copy_1() {
BufferedInputStream bufis = null;
BufferedOutputStream bufos = null;

try {
bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3"));
bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));

int by = 0;

while ((by = bufis.read()) != -1) {
bufos.write(by);
}
} catch (IOException e) {
System.out.println(e.toString());
} finally {
try {
if (bufos != null) {
bufos.close();
}
} catch (IOException e) {
System.out.println(e.toString());
}
try {
if (bufis != null) {
bufis.close();
}
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
}


 

读取键盘录入
为了支持标准输入输出设备,Java定义了两个特殊的流对象:System.in和System.out。System.in对应键盘,属于InputStream类型,程序使用System.in可以读取从键盘上输入的数据。System.out对应显示器,属于PrintStream类型,PrintStream是OutputStream的一个子类,程序使用System.out可以将数据输出到显示器上。键盘可以被当做一个特殊的输入流,显示器可以被当做一个特殊的输出流。
 
读取键盘录入
System.out:对应的是标准输出设备,控制台。
System.in:对应的标准输入设备:键盘。
 
需求:
通过键盘录入数据。
当录入一行数据后,就将该行数据进行打印。
如果录入的数据是over,那么停止录入。
 
示例:
import java.io.*;

class ReadIn {
public static void main(String[] args) {
InputStream in = System.in;
StringBuilder sb = null;

try {
sb = new StringBuilder();
while (true) {
int ch = in.read();
if (ch == '\r')
continue;
if (ch == '\n') {
String s = sb.toString();
if ("over".equals(s))
break;
System.out.println(s.toUpperCase());
sb.delete(0, sb.length());
} else
sb.append((char) ch);
}
} catch (IOException e) {
System.out.println(e.toString());
}
}
}


 

读取转换流
通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。也就是readLine方法,能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?
 
readLine方法是字符流BufferedReader类中的方法,而键盘录入的read方法是字节流InputStream的方法,那么能不能将字节流转成字符流在使用字符流缓冲去的readLine方法呢?
 
示例:
import java.io.*;

class TransStreamDemo {
public static void main(String[] args) {
// 获取键盘录入对象。
InputStream in = System.in;

InputStreamReader isr = null;
BufferedReader bufr = null;

try {
// 将字节流对象转成字符流对象,使用转换流。InputStreamReader
isr = new InputStreamReader(in);
// 为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
bufr = new BufferedReader(isr);

String line = null;
while ((line = bufr.readLine()) != null) {
if ("over".equals(line))
break;
System.out.println(line.toUpperCase());
}
} catch (IOException e) {
System.out.println(e.toString());
} finally {
try {
if (bufr != null)
bufr.close();
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
}


 

写入转换流
示例:
import java.io.*;

class TransStreamDemo2 {
public static void main(String[] args) {
// 键盘的最常见写法。
BufferedReader bufr = null;
BufferedWriter bufw = null;

try {
bufr = new BufferedReader(new InputStreamReader(System.in));
bufw = new BufferedWriter(new OutputStreamWriter(System.out));

String line = null;

while ((line = bufr.readLine()) != null) {
if ("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
} catch (IOException e) {
System.out.println(e.toString());
} finally {
try {
if (bufr != null)
bufr.close();
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
}


 

流操作规律
1.
源:键盘录入。
目的:控制台。
 
2.需求:想把键盘录入的数据存储到一个文件中。
源:键盘。
目的:文件。
 
3.需求:想要将一个文件的数据打印在控制台上。
源:文件。
目的:控制台。
 
流操作的基本规律:
最痛苦的就是流对象有很多,不知道该用哪一个。
 
通过三个明确来完成
1.明确源和目的。
        
源:输入流。InputStream  Reader
        
目的:输出流。OutputStream  Writer。
2.操作的数据是否是纯文本。
        
是:字符流。
        
不是:字节流。
 
3.当体系明确后,在明确要使用哪个具体的对象。
        
通过设备来进行区分:
        
源设备:内存,硬盘。键盘
        
目的设备:内存,硬盘,控制台。
 
 
1.将一个文本文件中数据存储到另一个文件中。复制文件。
源:因为是源,所以使用读取流。InputStream Reader
是不是操作文本文件。
是!这时就可以选择Reader
这样体系就明确了。
 
接下来明确要使用该体系中的哪个对象。
明确设备:硬盘。上一个文件。
Reader体系中可以操作文件的对象是 FileReader
 
        
是否需要提高效率:是!。加入Reader体系中缓冲区 BufferedReader.
 
 
         FileReader fr = new FileReader("a.txt");
         BufferedReader bufr = new BufferedReader(fr);
 
 
 
 
        
目的:OutputStream Writer
        
是否是纯文本。
        
是!Writer。
        
设备:硬盘,一个文件。
         Writer体系中可以操作文件的对象FileWriter。
        
是否需要提高效率:是!。加入Writer体系中缓冲区 BufferedWriter
        

         FileWriter fw = new FileWriter("b.txt");
         BufferedWriter bufw = new BufferedWriter(fw);
 
2.需求:将键盘录入的数据保存到一个文件中。
        
这个需求中有源和目的都存在。
        
那么分别分析
        
源:InputStream Reader
        
是不是纯文本?是!Reader
        

        
设备:键盘。对应的对象是System.in.
        
不是选择Reader吗?System.in对应的不是字节流吗?
        
为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。
        
所以既然明确了Reader,那么就将System.in转换成Reader。
        
用了Reader体系中转换流,InputStreamReader
 
         InputStreamReader isr = new InputStreamReader(System.in);
 
        
需要提高效率吗?需要!BufferedReader
         BufferedReader bufr = new BufferedReader(isr);
 
 
 
        
目的:OutputStream  Writer
        
是否是存文本?是!Writer。
        
设备:硬盘。一个文件。使用 FileWriter。
         FileWriter fw = new FileWriter("c.txt");
        
需要提高效率吗?需要。
         BufferedWriter bufw = new BufferedWriter(fw);
 
 
         **************
        
扩展一下,想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中。
        

        
目的:OutputStream  Writer
        
是否是存文本?是!Writer。
        
设备:硬盘。一个文件。使用 FileWriter。
        
但是FileWriter是使用的默认编码表。GBK.
        

        
但是存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。
        
所以要使用的对象是OutputStreamWriter。
        
而该转换流对象要接收一个字节输出流。而且还可以操作的文件的字节输出流。FileOutputStream
 
         OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");
 
        
需要高效吗?需要。
         BufferedWriter bufw = new BufferedWriter(osw);
 
所以,记住。转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流。
 
 
异常的日志信息
示例:
import java.io.*;
import java.util.*;
import java.text.*;

class ExceptionInfo {
public static void main(String[] args) throws IOException {
try {
int[] arr = new int[2];
System.out.println(arr[3]);
} catch (Exception e) {

try {
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
String s = sdf.format(d);

PrintStream ps = new PrintStream("exeception.log");
ps.println(s);
System.setOut(ps);

} catch (IOException ex) {
throw new RuntimeException("日志文件创建失败");
}
e.printStackTrace(System.out);
}
}
}


 

系统信息
示例:
import java.io.*;
import java.util.*;

class SystemInfo {
public static void main(String[] args) throws IOException {
Properties prop = System.getProperties();

// System.out.println(prop);
prop.list(new PrintStream("sysinfo.txt"));
}
}


 

 

 

----------------------ASP.Net+Android+IOS开发----------------------期待与您交流!
详情请查看:http://edu.csdn.net
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  黑马程序员