黑马程序员 java之io流一

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------



IO概述与字符流。

1、概述     

IO流用来处理设备之间的数据传输

Java对数据的操作是通过流的方式

Java用于操作流的对象都在IO包中

流按操作数据分为两种:字节流和字符流 ASCII  JBK  UTF-8

按流向分为输入流和输出流。

字符流:在内部融合不同编码表。用于处理文字。

字节流:用于处理图片等,通用。

字节流抽象基类

InputStream            OutputStream

字符流抽象基类

Reader             Writer。

 

2、字符流

(1)文件写入 

需求:在硬盘上,创建一个文件并写入一些文字数据。

参看下面代码。

import java.io.*;
public class FileWriterDemo {
	public static void main(String[] args) throws IOException{
		//1、创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。
		//而且该文件会被创建到指定的目录下。如果该目录已有同名文件,将被覆盖。
		//其实这一步就是在明确数据要存放的目的地。
		FileWriter fw = new FileWriter("demo.txt");
		//2、调用write方法,将字符串写入流中。
		fw.write("abcef");
		//3、刷新流对象中缓冲中的数据。
		//将数据刷到目的地。
		fw.flush();
		//4、关闭流资源,但是关闭之前会刷新一次内部的缓冲。
		//将数据刷到目的地中。和flush区别在于刷新后将流关闭。
		fw.close();
	}
}

(2)异常处理

import java.io.*;
public class FileWriterDemo2 {
	public static void main(String[] args) {
		FileWriter fw = null;
		try{
			fw = new FileWriter("Demo.txt");
			fw.write("woshichaoren");
			
		}
		catch(IOException e){
			System.out.println(e.toString());
		}
		finally{
			try{
				if(fw!=null)
					fw.close();
			}
			catch(IOException e){
				System.out.println(e.toString());
			}
		}
	}
}

(3)文件读取

 文件读取有两种方式:一种是一个字符一个字符的读取,一种是通过字符数组进行读取

import java.io.*;
public class FileReader1 {
	public static void main(String[] args) throws IOException{
		fileRead_1();
		fileRead_2();
	}
	public static void fileRead_1() throws IOException{
		//创建一个文件读取流对象,和指定名称的文件相关联。
		//要保证该文件是已经存在的。如果不存在,会发生异常:FileNotFoundException
		FileReader fr= new FileReader("Demo.txt");
		//调用读取流对象方法。
		//read方法一次读一个字符,而且会自动往下读。
		int ch=0;
		System.out.println("单个字符读取:");
		while((ch=fr.read())!=-1){
			System.out.print((char)ch);
		}
		System.out.println("\r\n\r\n");
		fr.close();
	}
	public static void fileRead_2()throws IOException{
		FileReader fr = new FileReader("demo.txt");
		//定义一个字符数组,用于存储读到的字符。
		//该Read返回的是读到的字符个数。
		char[] buf=new char[1024];
		int num = 0;
		System.out.println("字符数组读取:");
		while((num=fr.read(buf))!=-1){
			System.out.println(new String(buf,0,num));
		}
		fr.close();
	}
}

(4)文件拷贝 

         原理:其实就是讲C盘下的文件数据存储到D盘的一个文件中。

         步骤:1、在D盘创建一个文件,用于存储C盘文件中的数据。

     2、定义一个读取流和C盘文件关联。

     3、通过不断的读写完成数据的存储。

     4、关闭资源。

import java.io.*;
public class CopyDemo {
	public static void main(String[] args) {
		copy_2();
	}
	public static void copy_2(){
		FileWriter fw = null;
		FileReader fr = null;
		try{
			fw=new FileWriter("FileReader2_copy222.java");
			fr=new FileReader("FileReader2.java");
			
			char[] buf = new char[1024];
			int len = 0;
			while((len = fr.read(buf))!=-1){
				fw.write(buf,0,len);
			}
		}
		catch(IOException e){
			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("FileReader2_COPY.java");
		
		//与已有文件关联。
		FileReader fr = new FileReader("FileReader2.java");
		
		int ch = 0;
		while((ch=fr.read())!=-1){
			fw.write(ch);
		}
		
		fw.close();
		fr.close();
	}
}

缓冲与装饰类

1、基本

缓冲区的出现是为了提高流的操作效率。所以在创建缓冲区之前必须要先有流对象。

import java.io.*;
public class BufferedWriterDemo {
	public static void main(String[] args)throws IOException {
		//创建字符写入流对象。
		FileWriter fw = new FileWriter("buf.txt");
		//为了提高字符写入流的效率加入了缓冲技术。
		//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
		BufferedWriter bufw = new BufferedWriter(fw);
		for(int x=1;x<5;x++){
			bufw.write("abc"+x);
			bufw.newLine();
			bufw.flush();
		}
		//需要记住的是,只要用到缓冲区,就要刷新。
		//bufw.flush();
		//其实关闭缓冲区,就是在关闭缓冲区中的流对象。所以不用再写fw.close()。
		bufw.close();
	}
}

字符读取流缓冲区:

该缓冲区提供了一次读一行的代码,方便于对文本数据的获取。

当返回null,表示读到文件末尾。

import java.io.*;
public class BufferedReaderDemo {
	public static void main(String[] args)throws IOException {
		//创建一个读取流对象和文件相关联。
		FileReader fr = new FileReader("buf.txt");
		//为了提高效率加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数哦
		BufferedReader bufr = new BufferedReader(fr);
		String line = null;
		while((line=bufr.readLine())!=null){
			System.out.println(line);
		}
		bufr.close();
	}
}
缓冲复制

需求:通过缓冲区复制一个文本文件。

import java.io.*;
public class CopyTextByBuf {
	public static void main(String[] args) {
		BufferedReader bufr = null;
		BufferedWriter bufw = null;
		
		try{
			bufr = new BufferedReader(new FileReader("BufferedReaderDemo.java"));
			bufw = new BufferedWriter(new FileWriter("BufferedReaderDemo_copy2.java"));
			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("写入关闭失败!");
			}
		}
	}
}

装饰设计类

当想要对已有的对象进行功能增强时,可以将定义一个类,将已有对象传入,基于已有功能,提供加强功能。

自定义的该类就称为装饰类。 

装饰通常会通过构造方法接收被装饰的对象,并基于被装饰对象的功能,提供加强功能。

装饰和继承的区别:

装饰模式比继承更加灵活,避免了继承体系的臃肿,减弱了类与类之间的关系。

装饰类因为增强已有对象,具备的功能和已有对象是相同的,只不过提供了更强的功能。

所以装饰类和被装饰类,通常都属于一个体系中。

另外建议继承不要写的过多,不要以继承为主。会引起体系臃肿。可以通过装饰类来增强功能。

可以通过下面的例子理解掌握装饰类:

import java.io.*;
class MyBufferedReader{
	private FileReader r;
	MyBufferedReader(FileReader r){
		this.r=r;
	}
	//可以一次读取一行数据的方法。
	public String myReadLine()throws IOException{
		//定义一个临时容器,原BufferedReader中封装的是字符数组。
		//定义一个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;
	}
	public void myClose()throws IOException{
		r.close();
	}
}
public 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();
	}
}

字节流与流操作规律

1、字节流读写操作

InputStream输入读 OutputStream输出写

import java.io.*;
public class FileStreamDemo {
	public static void main(String[] args) throws IOException{
		readFile_2();
	}
	public static void readFile_2()throws IOException{
		FileInputStream fis = new FileInputStream("fos.txt");
		byte[] buf = new byte[fis.available()];
		fis.read(buf);
		System.out.println(new String(buf));
		fis.close();
	}
	public static void readFile()throws IOException{
		FileInputStream 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));
		}
		fis.close();
	}
	public static void writeFile()throws IOException{
		FileOutputStream fos = new FileOutputStream("fos.txt");
		
		fos.write("woshichaoren".getBytes());
		
		fos.close();
	}}
字节流缓冲区

需求:通过字节流缓冲区完成Mp3文件的复制。

通过下面的事例,可以掌握字节流缓冲区,并扩展一个自定义缓冲区。

import java.io.*;
public class CopyMp3 {
	public static void main(String[] args) throws IOException{
		long start=System.currentTimeMillis();
		copy_2();
		long end = System.currentTimeMillis();
		System.out.println("2运行时间为:"+(end-start)+"毫秒");
		long start1=System.currentTimeMillis();
		copy_1();
		long end1 = System.currentTimeMillis();
		System.out.println("1运行时间为:"+(end1-start1)+"毫秒");
	}
	//通过自定义字节流缓冲区复制。
	public static void copy_2()throws IOException{
		MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("D:\\传奇.MP3"));
		BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("D:\\传奇_Copy2.MP3"));
		int by = 0;
		while((by=bufis.myRead())!=-1){
			bufos.write(by);
		}
		bufos.close();
		bufis.myClose();
	}
	//通过字节流的缓冲区完成复制。
	public static void copy_1()throws IOException{
		BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("D:\\传奇.MP3"));
		BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("D:\\传奇_Copy1.MP3"));
		int by = 0;
		while((by=bufis.read())!=-1){
			bufos.write(by);
		}
		bufos.close();
		bufis.close();
	}
}
class MyBufferedInputStream{
	private InputStream in;
	private byte[] buf=new byte[1024];
	private int pos=0,count =0;
	MyBufferedInputStream(InputStream in){
		this.in=in;
	}
	public int myRead()throws IOException{
		if(count==0){
			count = in.read(buf);
			if(count<0)
				return -1;
			pos=0;
			byte b = buf[pos];
			count--;
			pos++;
			return b&0xff;
		}
		else if(count>0){
			byte b = buf[pos];
			count--;
			pos++;
			return b&0xff;
		}
		return -1;
	}
	public void myClose()throws IOException{
		in.close();
	}
}
流操作规律

//最常用键盘录入写法

BufferedReaderbufr = new BufferedReader(new InputStreamReader(System.in));

//最常用键盘读取写法

BufferedWriterbufw = new BufferedWriter(new OutputStreamWriter(System.out));

流操作的基本规律:当流对象有很多,需要明确应该用哪一个。

通过下面步骤来完成。前两部明确体系,后一步明确设备。

1、明确源和目的。

源 :输入流         InputStream  Reader

目的:输出流         OutputStreamWriter

2、操作的数据是否是纯文本。

是:字符流

否:字节流

3、当体系明确后,再明确使用哪个具体的对象。通过设备来进行区分。

源设备:内存,硬盘,键盘。

目的设备:内存,硬盘,控制台。

有时候还要判断是否需要加入缓冲技术提高效率。

 
  


你可能感兴趣的:(黑马程序员 java之io流一)