黑马程序员--Java--IO流

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

IO流

1.1 IO流概述
 IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式,Java用于操作流的对象都放在IO包中。

 输入流和输出流是相对于内存而言的:
将外设中的数据读取到内存中:输入。
将内存中的数据写到外设上:输出。
 
 流按操作分为两种:字节流和字符流。

 字符流的由来:其实就是字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字信息,在对这个文字操作。简单理解为:字节流+编码表
1.2 IO流中常见的基类--字符流
 字节流的抽象类:InputStream,OutputStream

 字符流的抽象类:Reader,Writer

 其他有着四个类派生出来的子类都是以其父类为后缀名。

如把文字写入硬盘中的例子:
ps:这里使用 FileWriter

代码:
import java.io.*;

class  FileWriterDemo
{
	public static void main(String[] args) throws IOException//IO流存在IO异常需要处理
	{
		FileWriter fw = new FileWriter("a.txt");//使流与文件相关联,如文件不存在则创建,如存在则覆盖

		fw.write("abcdef");//调用Writer的write方法写数据,其实把数据写入到缓冲区里了

		fw.flush();//刷新,将数据写到目的地中。

		fw.close();//关闭流,关闭资源。
	}
}

注意:如果构造函数为,FileWriter fw = new FileWriter("a.txt",true);那么是对文件进行续写。
      close方法为关闭流。一般在finally语句中。而且有几个流对象就要对应关闭几个流。

练习:
  读取一个文件,将读到的字符打印到控制台上。
1.read()方法:读取一个字符对应的ASK码值,若读到最后返回-1。
代码:
import java.io.*;

class  FileWriterDemo
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr = new FileReader("a.txt");

		int c ;
		
		while ((c=fr.read())!=-1)
		{
			System.out.print((char)c);
		}

		fr.close();
	}
}

2.read(char[])方法:读取一定长度的数据。读到末尾返回-1。
代码:
import java.io.*;

class  FileWriterDemo
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr = new FileReader("a.txt");

		char[] arr = new char[3];

		int len = 0;
		
		while ((len=fr.read(arr))!=-1)
		{
			System.out.print(new String(arr,0,len));
		}

		fr.close();//
	}
}

字符流缓冲区:缓冲区的出现提高了数据的书写效率。

对应的类为:BufferedReader(对应有readLien())和BufferedWriter(对应有newLine())

LineNumberReader
 跟踪行号的缓冲字符流:此类定义了方法setLineNumber(int)和getLineNumber(),他们可以分别用于设置和获取当前行号。
1.3 IO流常见的基类--字节流
字节流不仅可以操作字符,还可从操作媒体文件。
字节流的三种读取方式:
 1、read(new byte[fis.available]):当文件字节数很少的时候,通过available()方法获得其长度,创建一个刚好的数组。
 2、read(new byte[1024]):一次读取1024个字节。
 3、read():一次读取一个,效率太低。

字节流也有对应的缓冲区:BufferedInputStream和BufferedOutputStream 缓冲区的出现提高了效率。
1.4 转换流(把字节流转换成字符流)
分别为:InputStreamReader和OutputSreamWriter
  接收的对象分别为InputStream和OutPutStream;其实字节流转字符流就是解码过程,就应该有对应的编码表,不写则为默认的GBK。

转换流的简写:
 键盘录入(因为键盘录入都是字符,而底层System.in为字节流,因此用到了转换流提高效率):
BufferedReader bufr = new BufferedReader(new InputStream(System.in));
 ps:键盘录入一般都写了判断终止的语句。

什么时候用转换流呢:
1、源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁,提高对文本操作的便捷。
2、操作涉及到编码表时,必须使用转换流

练习:读取一个键盘录入数据,并变成大写打印在控制台上。
代码:
import java.io.*;
class  ReadKey
{
	public static void main(String[] args) throws IOException
	{
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

		String line;

		while((line=bufr.readLine())!=null){
			if(line.equals("over"))
				break;
			else{
				System.out.println(line.toUpperCase());
			}
		}

		bufr.close();
	}
}

总结流操作的基本规律:
1、明确源和目的:
 源:输入流 InputStream和Reader
 目的: 输出流 OutputStream和Writer
2、数据操作是否为纯文本。
 是:字符流
 否:字节流
3、是否要使用具体的对象:
 源设备:内存、硬盘、键盘
 目的设备:内存、硬盘、控制台
4、是否需要额外的更能增强。
 是就用Buffered

例:
需求1: 复制一个文本文件
1、明确源和目 的。
 源: InputStream Reader
 目的: OutputStream Writer
2、是否是纯文本?
 是!
 源:Reader
 目的:Writer
3、明确具体设备。
 源:硬盘 File
 目的:硬盘 File
 FileReader fr = new FileReader("a.txt");
 FileWriter fw = new FileWriter("b.txt");
4、需要额外功能吗?
 需要高效
 BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
 BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));


需求2:读取键盘录入信息, 并写入到一个文件中
1、明确源和目的。
 源:InputStream Reader
 目的:OutputStream Writer
2、是否是纯文本?
 是!
 源:Reader
 目的:Writer
3、明确具体设备。
 源:键盘 System.in
 目的:硬盘 File
 FileReader fr = new System.in;
 FileWriter fw = new FileWriter("b.txt");
 //这样做可以完成, 但是麻烦。 将读取的字节数据转成字符串, 再由字符流操作。
4、需要额外功能吗?
 需要转换,将字节流转成字符流,因为明确的源是Reader,这样操作文本数据更快捷。
 InputStreamReader isr = new InputStreamReader(System.in);
 FileWriter fw = new FileWriter("b.txt");
 还需要功能吗?
 需要,高效。
 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
 BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));
1.5 File类
File类用来将文件或者文件夹封装成对象,方便对文件和文件夹的属性进行操作。File对象可以作为参数传递给流的构造函数。

File f1 = new File("d:\\demo\\a.txt");//将已存在的文件封装成对象。
File f1 = new File("d:\\demo");       //将已存在的文件夹封装成对象。

File对象的常见方法:
1.获取
 获取文件名称:f1.getName();
 获取文件路径:f1.getPath();f1.getAbsolutePath();getParent();
 获取文件大小:f1.length();
 获取最后一次修改时间: f1.lastModified();
2.创建和删除
 创建:boolean creatNewFile();若文件已存在则返回false,和输出流不一样,输出流是覆盖已有文件。
       boolean mkdir();创建文件夹
       boolean mkdirs();创建多级文件夹
 删除:boolean delet();文件删除失败返回false
       void deletOnExit:程序退出时删除文件
3.判断
 文件是否存在:f1.exists();
 是否是文件:f1.isFile();
 是否是文件夹:f1.isDirectory();
 是否是隐藏文件:f1.isHidden();
 路径是否是绝对路径:f1.isAbsolute();
4.重命名
 f1.renameTo(f2):
5.其他
 File[] files = File.listRoots():返回可用的根目录。
 File file = new File("d:\\");
file.getFreeSpace();//返回D盘剩余空间
file.getTotalSpace();//返回D盘总空间
file.getUsableSpace();//返回D盘可用空间
 String[] names = new File("c:\\").list();//返回C盘里面的所有文件和文件夹名称
 File[] files = new File("c:\\").listFiles();//返回C盘里所有的文件和文件夹对象

list()和listFiles()方法可传入指定的文件名,返回目录下指定的文件的数组。
例:
File[] files = new File("c:\\").listFiles(new FileByHidden());

class FileByHidden implements FilenameFiler{
	public boolean accept(File dir , String name){
		return dir.isHidden();
	}
}
1.6 递归
函数自身直接或者间接的调用自身,一个功能在被重复的使用,每次使用时,参与运算的结果和上一次有关,这时可以使用递归来解决问题。

ps:
1.递归一定要明确条件,否则容易栈溢出。
2.注意递归的次数
3.递归一般都和嵌套在循环内,每次循环都好比褪去一层皮。

需求:获取目录下的所有文件名称
代码:
import java.io.*;
class FileDemo 
{
	public static void main(String[] args) 
	{
		File f = new File("e:\\java资料\\java007");
		getFileName(f);
	}

	public static void getFileName(File f){
		if(f.isFile())
			System.out.println(f.getName());
			//if(f.getnName().ehdsWith(".java"))也可以判断是否为某一文件
		if(f.isDirectory()){
			System.out.println(f);
			File[] files = f.listFiles();
			for(File file : files){
				getFileName(file);
			}
		}
	}
}


需求:用递归求6的二进制值
代码:
class ToBinary 
{
	public static void main(String[] args) 
	{
		int num = 6;
		toBinary(num);
	}
	public static void toBinary(int i){
		if(i>0){
			toBinary(i/2);
			System.out.print(i%2);//这里的递归和输出顺序问题,让递归底层的想打印就把输出语句放在递归后面
		}
	}
}

运行结果:
110
1.7 Properties集合(为Hashtable子类)
特点:
1、给集合中的键值对都是字符串
2、集合中的数据可以和保存到流中,或者可以从流中获取。
3、通常该集合用于操作以键值对存在的配置文件。

重要方法:
 1)设置和获取
 设置或者修改:p.setProperty("zhangsan","30");//Map中是put
 获取键对应的值:String value = p.getProperty("zhangsan");//Map中是get(key)
 获取所有键; String[] names = p.stringPropertyNames();
 2)与流相结合:
 读取流的键值对:load(InputStream/Reader i/r);
 向流中写入数据:store(OutputStream/Writer o/w);
1.8 IO流其他类
打印流:PrintStream和PrintWriter
 一般用PrintWriter,他可以在建立对象时接收File、String(路径)、OutoutStream、Writer。并且加上参数true,可以每次读取后自动flush。
 他的println()方法为写数据后立马另起一行。

序列流:SequenceInputStream
 可把多个有关系的流合并为一个流操作。多用于合并文件。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值