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

---------------------- android培训java培训、期待与您交流!

 

IO

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

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

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

流按操作数据分为两种:字节流与字符流

流按流向分为:输入流,输出流。

 

IO流常用基类

字节流的抽象基类:InputStream,OutputSteam

字符流的抽象基类:Reader,Writer

 

FileWriter 写文件的IO字符流 

用法如下:

FileWriter fw = new FileWriter("demo.txt"); 创建FileWriter对象

fw = new FileWriter("demo.txt",true); 传递一个true参数,代表不覆盖已有文件,并在已有文件的末尾出进行数据续写

fw.write("abcde");  调用write方法,将字符串写入到流中,如果文件存在将覆盖原有文件

fw.flush(); 刷新流对象中的缓冲中的数据,将数据刷新到目的地中。

fw.close(); 关闭流资源,关闭之前会刷新一次内部的缓冲中的数据

(close和flush区别:flush刷新后,流可以继续使用;close刷新后,流关闭。)

 

这些方法都会抛出IOException异常

捕获异常的方法如下:

 

FileWriter fw = null;
try
{
	fw = new FileWriter("demo.txt");
	fw.writer("abcdef");
}
catch (IOException e)
{
	System.out.println(e.toString());
}
finally
{
	try
	{

		if(fw!=null)
			fw.close();
	}
	catch (IOException e)
	{
		System.out.println(e.toString());
	}
}

FileReader 读文件的IO字符流  如下:

第一种方式:read();读取单个字符一次读一个字符,自动往下读,如果读到末尾返回-1

FileReader fr = new FileReader("demo.txt");创建一个文件读取流对象,和指定名称的文件相关联,要保证该文件是已经存在的,如果不存在,会发生FileNotFoundException异常

int ch = 0;

while((ch=fr.read())!=-1)  //调用读取流对象的read方法,

{

       System.out.print((char)ch);

}

fr.close();  关闭流资源

第二种方式:通过字符数组读取 read(char[]); 返回的是读到字符的个数

FileReader fr = new FileReader("demo.txt");

char[] buf = new char[1024];  定义个字符数组,用于存储读到的字符

int num = 0;

while((num=fr.read(buf)!=-1)

{

       System.out.print(new String(buf,0,num));

}

fr.close();

 

字符流的缓冲区 缓冲区的出现提高了对数据的读写效率

对应类:BufferedWriter,BufferedReader

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

BufferedWriter应用如下

FileWriter fw = new FileWriter("buf.txt");//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可

BufferedWriter bufw = new BufferedWriter(fw);

bufw.write("abcde");

bufw.newLine();//跨平台换行方法

bufw.flush();//只要用到缓冲区,就要记得刷新

bufw.close();//其实关闭缓冲区,就是在关闭缓冲区的流对象

BufferedReader应用如下:

FileReader fr = new FileReader("demo.txt");//创建一个读取流对象和文件相关联

BufferedReader bufr= new BufferedReader(fr);将字符读取流对象传递给缓冲对象的构造函数。

String line = null;

while((line=bufr.readLine())!=null) // readLine();一次读一行,返回null表示读到文件末尾

{

       System.out.println(line);

}

bufr.close();   

 

装饰设计模式

当想要对已有对象进行功能增强时,可以定义类,将已有对象传入,基于已有对象的功能,并提供加强功能,那么自定义的该类称为装饰类。

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

装饰和继承的区别:

装饰模式比继承更灵活,避免了继承体系的臃肿,而且降低了类与类之间的关系

装饰类因为增强已有对象,具备的功能和已有功能是相同的,只不过提供了更强的功能,所以装饰类和被装饰类都属于一个体系中的。

 

BufferedReader

       |--LineNumberReader 跟踪行号缓冲字符输入流

 

字节流:InputStream  OutputStream

 FileOutputStream和FileWriter用法基本相似,唯一一点FileOutputStream不用刷新,只能接受字节单位

FileInputStream和FileReader用法相似,多了一个方法available();获取文件的长度

  

字节流的缓冲区 BufferedOutputStream BufferedInputStream

 

读取键盘录入

System.out:对应的标准的输出设备,控制台

System.in:对应的标准输入设备,键盘

通过键盘录入一行数据并打印大写,发现其实就是读一行数据的原理也就是readLine方法,能不能通过ReadLine方法来完成键盘录入一行数据的读取呢?

readLine方法是字符流BufferedReader类中的方法,而键盘录入的ReadLine方法是字节流InputStream的方法,可以通过InputStreamReader将字节流转换成字符流

 

读入转换流

InputStreamReader  字节流通向字符流的桥梁

 写入转换流

OutputStreamWriter  字符流通向字节流的桥梁

 键盘录入最常见写法

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

控制台显示

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

转换流什么时候使用?

是字符和字节之间的桥梁,涉及到字符编码转换时,用到转换流

 

流对象选择的基本规律:

1,  明确源和目的

源:输入流   InputStream  Reader

目地:输出流  OutputStream  Writer

2,  操作的数据是否是纯文本

是:字符流   不是:字节流

3,  当体系明确后,再明确要使用哪个具体的对象

通过设备来进行区分:

源设备:内存、硬盘、键盘

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

4,是否需要提高效率

 

改变标准输入输出设备

改变输入:System.setIn(InputStream in);

改变输出:System.setOut(PrintStream out);

 

异常的日志信息(专业工具:log4j) 

Date d = new Date();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String s = sdf.format(d);

PrintStream ps = new PrintStream("exception.log");

ps.println(s);

System.setOut(ps);

e.printStackTrace(System.out);

 

系统信息

Properties prop = System.getProperties();

//prop.list(System.out);

prop.list(new PrintStream(“sysinfo.txt”));

 

 File类

用来将文件或者文件夹封装成对象

方便对文件与文件夹的属性信息进行操作

File对象可以作为参数传递给流的构造函数

 

打印File对象显示的是路径(取决于你定义的是相对路径还是绝对路径)

String separator  File中跨平台的目录分隔符

 

File类的常见方法

1,  创建

boolean creatNewFile():在指定位置创建文件,如果该文件存在,则不创建,返回false

                             和输出流不一样,输出流对象一建立创建文件,而且文件存在就覆盖

boolean mkdir();创建目录,只能创建一级目录

boolean mkdirs();创建多级目录

2,  删除

boolean delete(); 删除失败返回false

void deleteOnExit();在程序退出时删除指定文件

3,  判断

boolean canExecute();是否能执行

boolean exists():文件是否存在

boolean isFile():是否是文件(在判断前,必须先判断文件对象封装的内容是否存在。)

boolean isDirectory():是否是目录

boolean isHidden():是否隐藏

boolean isAbsolute():是否是绝对路径

4,  获取信息

String getName();

String getPath();获取路径

String getParent();该方法返回绝对路径中的父目录。如果是相对路径,返回null。如果相对路径中有上一层目录,那么该目录就是上一层目录

String getAbsolutePath();获取绝对路径

file getAbsoluteFile();

long lastModified();返回文件最后一次被修改的时间

long length();返回文件的大小

 5,其它

boolean renameTo(); 文件重命名

File[] listRoots(); 列出机器中有效盘符

String[] list(); 列出指定目录下的的所有文件,包含隐藏文件。调用list方法file对象必须是目录,而且该目录必须存在。

String[] list(FilenameFilter filter) 列出指定目录下的特定文件  应用如下:

File dir = new File("c:\\");
String[] arr = dir.list(new FilenameFilter()
{
	public boolean accept(File dir,String name)
	{
		return name.endsWith(".bmp");
	}
});
for(String name : arr)
{
	System.out.println(name);
}     

File[] listFiles() 列出指定目录下的所有文件,并可以对其文件进行操作。 应用如下:

File dir = new File("c:\\");
File[] files = dir.listFiles();
for(File f : files)
{
	System.out.println(f.getName()+"::"+f.length());
}

递归注意条件:

1,限定条件

2,要注意递归的次数,尽量避免内存的溢出

 

Properties是hashTable的子类

也就是说它具备map集合的特点,它里面存储的键值对都是字符串

是集合中的IO技术想结合的集合容器

该对象的特点:可以用于键值对形式的配置

那么在加载数据时,需要数据有固定格式,通常是键=值

常用方法:

getProperty(String key); 获取元素

setProperty(String key, String value); 设置元素

load(InputStream inStream)  加载流中数据到集合中

store(OutputStream out,String comments) 加载流中中的数据并且修改到一个输出流中

list(PrintWriter out)  显示出属性列表

 专业解析xml文件工具(dom4j)

 

打印流:PrintWriter,PrintStream

该流提供了打印方法,可以将各种数据类型的数据进行原样打印

字节打印流:PrintStream

构造函数可以接受的参数类型

1,  file对象 File

2,  字符串路径 String

3,  字节输出流。OutputStream

字符打印流:PrintWriter

构造函数可以接受的参数类型

1,  file对象 File

2,  字符串路径 String

3,  字节输出流。OutputStream

4,  字符输出流,Writer

 

序列流:SequenceInputStream 其他输入流的逻辑串联

  

操作对象:ObjectInputStream与ObjectOutputStream

                     被操作的对象需要实现Serializable(标记接口:没有方法);

                     实现对象持久化存储

                     静态的成员不能序列化;非静态的成员加入transient不能实现序列化

 

管道流:PipedInputStream与PipedOutputStream

              输入输出可以直接进行连接,通过结合线程使用

              连接的方法可以通过构造函数也可以通过connect()

 

RandomAccessFile

随机访问文件,自身具备读写的方法,通过skipBytes(int x),seek(int x)来达到随机访问。

 该类不是IO体系中的子类,直接继承Object。它是IO包中的成员,因为它具备读和写功能

内部封装了数组,通过指针对数组的元素进行操作

可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置

 

其实完成读写的原理就是内部封装了字节输入流和输出流

 

通过构造函数可以看出该类只能操作文件,而且操作文件还有模式:r,rw等

 如果模式为只读r,不会创建文件,会去读取一个已存在文件,如果该文件不存在,则会出现异常;如果模式是rw,如果要操作的文件不存在,会自动创建,如果存在则不会覆盖。

 

操作基本数据对象:DataInputStream与DataOutputStream

       writeUTF();和readUTF();必须配合使用

 

操作字节数组:ByteArrayInputStream与ByteArrayOutStream

ByteArrayInputStream:在构造的时候需要接受数据源,而且数据源是一个字节数组。

ByteArrayOutStream:在构造的时候,不用定义数据目的,因为在该对象中已经内部封装了可变长度的字节数组。这就是数据目的地。

因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭

 

流操作规律
源设备:键盘(System.in)、硬盘(FileStream)、内存(ArrayStream)

目的设备:控制台(System.out)、硬盘(FileStream)、内存(ArrayStream)

 

操作字符数组:CharArrayReader与CharArrayWriter

操作字符串:StringReader与StringWriter

 

 字符编码

字符流的出现为了方便操作字符

更重要的加入了编码转换

通过子类转换流来实现:InputStreamReader OutputStreamWriter

常见的编码表:

ASCII:美国标准信息交换码用一个字节的7位可以表示

ISO8859-1:拉丁码表。欧洲码表。用一个字节的8位表示

GB2312:中国的中文编码表

GBK:中国的中文编码表升级,融合了更多的中文字符号

Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言就是

UTF-8:更多用三个字节来表示一个字符

 

编码:字符串编程字节数组。

String----》byte[]  str.getBytes(charsetName); 默认是GBK

解码:字节数组编程字符串。

Byte[]----》String  new String(byte[],charsetName);

 

 

-------------------------------------------- android培训java培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net/heima

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值