黑马程序员----JAVA基础----IO流_1

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

一、IO流

IO流是用来处理设备之间的数据传输,Java对数据的操作是通过流的方式,而这些操作流的对象都在IO包中。

流按数据操作可分为字节流和字符流(处理文本数据);

a,字节流:读取文字字节的数据

b,字符流:在字节流的基础上,不直接操作而是先查找指定编码表,获取对应的文字。简单说:字符流就是字节流+编码表。

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

a,输入流:从外部设备读数据到内存中。

b,输出流:将内存中的数据写到外部设备上。

二、IO流体系

IO流有四个顶层基类:

字节流抽象基类:InputStream、OutputStream

字符流抽象基类:Reader、Writer

对于IO流体系内的类的名称来说:子类都以父类名作为后缀,子类名的前缀表示该类的功能

三、IO流使用

1,创建一个可以向文件中写入数据的字符输出流对象及一些细节问题

import java.io.FileWriter;
import java.io.IOException;

public class IODemo {

	private static final String LINE_SEPARATOR = System.getProperty("line.separator");

	public static void main(String[] args) throws IOException{
		/*
		 * 在创建字符流对象时,必须明确与其关联的文件
		 * 会抛出一个IO异常,原因:可能无法关联
		 */
		// 用字符输出流关联一个文本文件,文件存在,会覆盖其中的内容,如果该文件不存在,则创建一个文本文件
		// 如果需要续写文件,则在构造函数中加入true
		FileWriter fw = new FileWriter("demo.txt");
//		FileWriter fw = new FileWriter("demo.txt",true); //使用该流,就可以续写,而不会发生覆盖
		// 调用FileWriter中的write()方法,写入数据,数据被写入临时数据缓冲区中
		fw.write("abcdefg");
		/*
		 * 换行:在windos系统中换行符:\r\n,在Linux系统中:\n
		 * 有两种方法,一是+\r\n;一种是用系统提供的方法System.getProperty("line.separator")
		 * 第二种方法不用考虑系统问题
		 */
		fw.write("hehe"+"\r\n"+"heihei");
		fw.write("hehe"+LINE_SEPARATOR+"heihei");
		// 运行flus()方法,将缓冲区的数据刷新到文本文件中
		fw.flush();
		// 关闭流,关闭资源,关闭前会调用flush刷新缓冲区的数据到文本文件中,因此flush可以省略
		fw.close();
		// 关闭流后再写入数据,就会引起IOException
//		fw.write("cde");
	}

}
2,IO异常处理

import java.io.FileWriter;
import java.io.IOException;

public class IODemo2 {
	
	private static final String LINE_SEPARATOR = System.getProperty("line.separator");

	public static void main(String[] args) throws IOException {
		// 先创建字符输出流对象
		FileWriter fw = null;
		
		try{
			// 关联文件操作失败会引发IOException,因此将其放到try block中
			fw = new FileWriter("demo.txt");		
			fw.write("abc"+LINE_SEPARATOR+"def");
		}catch(IOException e){
			// 处理异常
		}finally{		// 表示一定要关闭资源
			// 加上判断条件,当fw不为null时才可以关闭,否则会引发NullPointerException
			if(fw!=null)
				try{
					fw.close();
				}catch(IOException e){
					System.out.println(e.toString());
				}
		}
		
	}

}

3,读取一个文件,将文件的内容打印到控制台上。

<pre name="code" class="html">import java.io.FileReader;
import java.io.IOException;

public class IODemo3 {

	public static void main(String[] args) throws IOException {
		// 用读取流关联文件,文件不存在则会引发FileNotFoundException
		FileReader fr = new FileReader("demo.txt");
		// 读一次
//		show1(fr);
		// 循环读取方式
//		show2(fr);
		// 使用字符数组,将数据读取到数组中
		show3(fr);
		fr.close();
	}
	private static void show3(FileReader fr) throws IOException {
		char[] buf = new char[1024];	//一般将数组的大小设为1024,如果数字是固定的,可以将其设置为常量
		int len=0;
		while((len=fr.read(buf))!=-1){
			// 使用String构造函数,将字符数组转换成字符串
			System.out.println(new String(buf,0,len));
		}
	}
	private static void show2(FileReader fr) throws IOException {
		int ch = 0;
		while((ch=fr.read())!=-1){
			System.out.print((char)ch);	//使用强制转换,将int转为char类型
		}
	}
	private static void show1(FileReader fr) throws IOException {
		
		int ch = fr.read();				// 用读取流的read()方法读取数据,返回读取到的字符数,读到结尾返回-1
		System.out.print((char)ch);	//使用强制转换,将int转为char类型
	}

}
 
4,字符流的缓冲区。缓冲区提高了数据的读写效率,对应类:BufferedReader、BufferedWriter。 

缓冲区要结合流才可以使用,在流的基础上对流的功能进行增强。

缓冲区常用方法:readlLine()、newLine()

注意:使用缓冲区一定要使用flusn()方法!!!

使用缓冲区与流结合高效读写数据,并加上异常处理:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 创建缓冲区对象
		BufferedReader bufr = null;
		BufferedWriter bufw = null;
		try{
			// 与流相关联
			bufr = new BufferedReader(new FileReader("demo.txt"));
			bufw = new BufferedWriter(new FileWriter("copydemo.txt"));
			String line = null;
			// readLine()是读取一行
			while((line=bufr.readLine())!=null){
				bufw.write(line);
				bufw.newLine();			// 换行
				bufw.flush();			// 使用缓冲区一定要刷新
			}
		}catch(IOException e){
			System.out.println(e.toString());
		}finally{
			// 当bufr和bufw不为空时,才可以关闭流
			if(bufr!=null)
				try{
					bufr.close();
				}catch(IOException e){
					
				}
			if(bufw!=null)
				try{
					bufw.close();
				}catch(IOException e){
					
				}
		}
	}

}

5,装潢设计模式:对一组对象的功能进行增强时,就可以使用该模式进行问题的解决

装潢和继承都能进行功能的扩展增强,那么二者的区别是什么呢?用继承来进行功能的扩展,

会导致继承体系越来越臃肿,不够灵活。装饰比继承更为灵活

注意:装饰类和被装饰类必须所属同一个接口或者父类!!!

装饰类:BufferedReader、BufferedWriter、LineNumberReader等。

其中LineNumberReader的特有方法:setLineNumber(int index)、getLineNumber()(返回行号)

6,字节流两个常用子类FileInputStream、FileOutputStream,该类的read()方法一次读取一个字节,available()方法可以

返回与其关联文件的字节数

字符流只可以处理文本文件,而字节流既可以处理文本文件,又可以处理非文本文件。

注意在使用BufferedOutputStream时不用使用flush()方法,原因:

字符流底层使用的还是字节流,因为字符流融合了编码表,所以可以读写字符。

字符流写入文本数据时,需要先将文本数据写入字符流中,对照编码表转换成字节数据,然后flush进目的地。

字节流中是字节数据不需要转换,所以可以直接写入目的地。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyMediaDemo {

	public static void main(String[] args) throws IOException {
		// 方法1
//		show1();
		// 方法2
		show2();
	}

	private static void show2() throws FileNotFoundException, IOException {
		FileInputStream fis = new FileInputStream("Desert.jpg");
		FileOutputStream fos = new FileOutputStream("Desert_copy.jpg");
		byte[] buf = new byte[1024];
		int len = 0;
		len=fis.read(buf);
		System.out.println(len);
		// 如果read()方法里不加数组buf,那么len就是读到的字节的值
		// 加上buf后,len表示读进buf的字节数量
//		while((len=fis.read())!=-1){
//			fos.write(buf,0,len);
//		}
		
		while((len=fis.read(buf))!=-1){
			fos.write(buf,0,len);
		}
		fos.close();
	}

	/**
	 * 
	 */
	private static void show1() {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			// 将缓冲区与流相关联
			bis = new BufferedInputStream(new FileInputStream("Desert.jpg"));
			bos = new BufferedOutputStream(new FileOutputStream("Desert_copy.jpg"));
			int ch=0;
			while((ch=bis.read())!=-1){
				/*
				 * 字符流底层使用的还是字节流,因为字符流融合了编码表,所以可以读写字符。
				 * 字符流写入文本数据时,需要先将文本数据写入字符流中,对照编码表转换成字节数据,
				 * 然后flush进目的地。字节流中是字节数据不需要转换,所以可以直接写入目的地
				 */
				bos.write(ch);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 关闭流,释放资源,记着判断流是否为空
			if(bos!=null)
				try {
					bos.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			if(bis!=null)
				try {
					bis.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
		}
	}

}

7,读取键盘录入的数据并打印在控制台上

InputStreamReader 和 OutputStreamWriter是字节流与字符流之间的桥梁

InputStreamReader:字节到字符的桥梁,解码。

OutputStreamWriter:字符到字节的桥梁,编码。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class KeyDemo {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		// 创建字节流接
		InputStream in = System.in;
		// 读取一次
//		show1(in);
		// 无限读取,直到遇到特定标记停止
//		show2(in);
		// 通过字节字符桥梁来完成键盘录入及打印操作
		show3(in);
		// 流关闭后再创建新流会产生异常IOException
//		InputStream in1 = System.in;
//		int ch1 = in.read();
//		System.out.println(ch1);
	}

	private static void show3(InputStream in) throws IOException {
		// InputStreamReader和OutPutStreamWriter是字节流与字符流的桥梁
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
		String str = null;
		while((str=bufr.readLine())!=null){
			if("over".equals(str))
				break;
			bufw.write(str);
			bufw.newLine();
			bufw.flush();
		}
	}

	private static void show2(InputStream in) throws IOException {
		// 创建一个StringBuilder用于接收数据
		StringBuilder sb = new StringBuilder();
		int ch=0;
		while((ch=in.read())!=-1){
			// 当回车时,输出键盘录入的内容
			if(ch=='\r')
				continue;
			if(ch=='\n'){
				String temp = sb.toString();
				// 当输入内容为over时就结束
				if("over".equals(temp))
					break;
				// 将键盘录入数据转成大写输出
				System.out.println(temp.toUpperCase());
				// 输出数据后清空sb
				sb.delete(0, sb.length());
			}else
				sb.append((char)ch);	// 将ch转换成字符存入sb中
		}
	}

	private static void show1(InputStream in) throws IOException {
		int ch = in.read();		// 阻塞式
		System.out.println(ch);
		in.close();
	}

}


8,流的操作规律

a,明确源和目的源:InputStream Reader目的: OutputStream Writer

b,明确数据是否是纯文本数据源:是纯文本用Reader,否InputStream 目的:是纯文本用Writer,否OutputStream

c,明确具体的设备源:硬盘(File)、键盘(System.in)、内存(数组)、网络(Socket流) 目的设备与源相同。

d,是否需要额外功能是否需要高效?是,加Buffer

四、File类

用来将文件或文件夹封装成对象,方便对文件和文件夹的属性进行操作,File对象可作为参数传递给流的构造函数。

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;

public class FileDemo {

	public static void main(String[] args) throws IOException {
		// 可以建一个存在的和不存在的文件或者目录封装成对象
		// 构造函数的集中不同形式
		File f1 = new File("demo.txt");
		File f2 = new File("D:\\JAVA\\Blog\\","demo.txt");
		File f3 = new File("D:\\JAVA\\Blog\\");
		File f4 = new File(f3,"demo.txt");
		// 字段	File.separator 对于不同的操作系统都可以应用
		File f5 = new File("D:"+File.separator+"JAVA"+File.separator+"Blog"+File.separator+"demo.txt");
		/*
		 * File类常见方法
		 * 1,获取:文件名称、大小、路径、修改时间等
		 * 2,创建与删除
		 * 3,判断:
		 */
		// 获取
		System.out.println("getName():"+f1.getName());
		System.out.println("length():"+f1.length());
		System.out.println("path:"+f1.getPath());
		System.out.println("absolutePath:"+f1.getAbsolutePath());	//获取绝对路径
		System.out.println("lastModified:"+f1.lastModified());
		// 创建与删除
		File file = new File("aaa.txt");
		// 和输出流不一样,如果文件不存在则创建,如果存在就不创建。输出流是在与不在都会创建,在就覆盖
		boolean b = file.createNewFile();
		boolean b1 = file.delete();	// 删除文件
		// 创建目录
		File file1 = new File("abc");
		boolean b2 = file1.mkdir();
		boolean b3 = file1.delete();// 注意:如果要删除的文件内部有其他文件,则无法删除
		// 创建多级目录
		File file2 = new File("abc\\def\\mnk\\ss");
		boolean b4 = file2.mkdirs();
		boolean b5 = file2.delete();// 删除的ss文件夹,不会都删除
		// 判断
		File file3 = new File("demo.txt");
		System.out.println(file3.exists());	//是否存在,当文件是未知时,应该先判断是否存在
		System.out.println(file3.isDirectory());//是不是目录
		System.out.println(file3.isFile());// 是不是文件
		// renameTo()	
		File file4 = new File("demo.txt");
		File file5 = new File("DEMO.txt");
		File file6 = new File("d:\\demo_copy.txt");
//		file4.renameTo(file5);	//同目录下重命名,
//		file4.renameTo(file6);	//非同文件下,移动并重命名
		// listRoots	获取根目录列表
		File[] file7 = File.listRoots();
		for(File files:file7){
			System.out.println(files);
		}
		//
		File file8 = new File("d:\\");
		System.out.println(file8.getFreeSpace());	// 盘符的可用空间
		System.out.println(file8.getUsableSpace());	// 盘符的可用空间
		System.out.println(file8.getTotalSpace());	// 盘符的大小
		// list	获取当前目录下的文件及文件夹名称,包含隐藏文件
		// 注意:调用list方法的File类对象中封装的必须是目录,否则会发生NullPointerException
		// 如果访问系统级目录也会发生NullPointerException
		// 如果目录存在但没有内容,会返回一个长度为0的数组
		String[] names = file8.list();
		for(String name:names){
			System.out.println(name);
		}
		// FilenameFilter 获取指定类型的文件
		File file9 = new File("E:\\数据\\BLS900");
		String[] strs = file9.list(new FilterByMnd());
		for(String str:strs){
			System.out.println(str);
		}
		File[] files = file9.listFiles(new FilterByHidden());
		for(File f:files){
			System.out.println(f);
		}
	}

}

class FilterByMnd implements FilenameFilter{
	//创建构造函数,可以方便过滤某后缀的文件
//	private String suffix;
//	
//	public FilterByMnd(String suffix) {
//		super();
//		this.suffix = suffix;
//	}
//	@Override
//	public boolean accept(File dir, String name) {
//		// TODO Auto-generated method stub
//		return name.endsWith(suffix);
//	}

	@Override
	public boolean accept(File dir, String name) {
		// TODO Auto-generated method stub
		return name.endsWith(".mnd");
	}
	
}
class FilterByHidden implements FileFilter{

	@Override
	public boolean accept(File pathname) {
		// TODO Auto-generated method stub
		return !pathname.isHidden();
	}
	
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值