——- android培训、java培训、期待与您交流! ———-
IO流概述
- IO即:Input与Output。
- IO流的作用:用于处理设备间数据的传输。Java中对数据的的操作是通过流的方式完成的。
- IO流的分类
- 按被操作的数据分:字符流、字节流
- 按流向分:输出流、输入流。
- IO流的常用基类(其子类以父类名为后缀。如:FileReader)
- 字节流:
- InputStream
- OutputStream
- 字符流:
- Reader
- Writer
- 字节流:
流对象的选取方法
- 先明确源和目的
- 源:InputStream 、Reader
- 目的:OutputStream 、Writer
- 再明确是否为纯文本
- 是:Reader、Writer
- 否:InputStream 、OutputStream
- 以上两部就可以确定需要使用的体系,确定了体系以后,就可以在该体系内寻找适合的流对象使用。
- 例:
把一个文本文件中的数据复制到另一个文本文件中。
- 先明确源和目的:
源: 文件一,所以对文件一的读取使用InputStream或Reader
目的:文件二,所以对文件二的写入使用OutputStream或Writer - 再明确是否为纯文本
文件一为纯文本,所以使用Reader。Reader体系中可以操作文本文件的是FileReader,所以使用FileReader。
文件二为纯文本,所以使用Writer。Writer体系中可以操作文本文件的是FileWriter,所以使用FileWriter。
- 先明确源和目的:
IO流常用设备
IO流说用到的设备一般分为以下几种。在对流对象的选取中,完成两个明确以后,就可以通过设备来确定具体使用的流对象。
- 源设备:内存,硬盘,键盘
- 目的设备:内存,硬盘,控制台
- 如:
- 硬盘:new FileReader( “C:\test\Test.txt”);
- 键盘:new InputStreamReader(System.in);
- 控制台:new OutputStreamWriter(System.out);
IO流中的一些常见流对象
父类中常用方法摘要
Writer
- abstract void close()
关闭此流,释放与之关联的所有资源。但要先刷新它才能把流中的信息写入目的中。 - abstract void flush()
刷新该流的缓冲,把流中的信息写入目的中。 - void write(char[] cbuf)
写入字符数组。 - abstract void write(char[] cbuf, int off, int len)
写入字符数组的某一部分。 - void write(int c)
写入单个字符。 - void write(String str)
写入字符串。 - void write(String str, int off, int len)
写入字符串的某一部分。
- abstract void close()
Reader
- abstract void close()
关闭该流并释放与之关联的所有资源。 - int read()
读取单个字符。 - int read(char[] cbuf)
将字符读入数组。 - abstract int read(char[] cbuf, int off, int len)
将字符读入数组的某一部分。
- abstract void close()
FileWriter
- 作用:用来写入字符文件
- 构造方法
- FileWriter(File file)
根据给定的 File 对象构造一个 FileWriter 对象。 - FileWriter(File file, boolean append)
根据给定的 File 对象构造一个 FileWriter 对象。 - FileWriter(String fileName)
根据给定的文件名构造一个 FileWriter 对象。 - FileWriter(String fileName, boolean append)
根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
- FileWriter(File file)
- 方法1与方法2、方法4与方法5的区别在于:方法2和方法4里append的值为true时,数据将会写入文件的末尾处,而不是写入文件开始。方法1和方法3将会把原有的数据覆盖。
- 常用方法摘要:从Writer继承而来的方法。
- 例:
FileWriter fw = new FileWriter("Test.txt");//创建一个FileWriter对象与Test.txt相关联。
fw.writ("abc"); //向流中写入“abc"三个字符
//注意:writ()方法并不是把数据写入文件中,而是写入流中。
fw.flush(); //把流中的数据写入文件中(即把abc三个字符写入文件中)
fw.close(); //关闭流
FileReader
- 作用:用来读取字符文件。
- 构造方法:
- FileReader(File file)
在给定从中读取数据的 File 的情况下创建一个新 FileReader。 - FileReader(String fileName)
在给定从中读取数据的文件名的情况下创建一个新 FileReader。
- FileReader(File file)
- 常用方法摘要:从Reader继承而来的方法。
- 例:
FileReader fr = new FileReader("Test.txt");//创建一个FileReader对象和Test.txt相关联
int ch = 0; //创建一个变量ch
ch = fr.read(); //读取文件中的一个字符,并把返回来的值赋予ch
//注意:read()方法返回的是int类型的值,而不是char类型,
//并且如果已到达流的末尾,则返回 -1
System.out.println((char)ch); //将ch强转为char类型,并打印出来
char[] cbuf = new char[1024]; //建立一个字符数组,用于作为缓冲区就收读取的数据。
//一般定义大小为1024(即1k)的倍数
int len = 0;
while((len=fr.read(cbuf))!=-1) //将读取到的数据写入cbuf中,此时返回的是读取的字符数。
//并且如果已到达流的末尾,则返回 -1
System.out.println(new String(cbuf,0,len));//打印cbuf中0到len中数据的内容(即读取到的数据)
fr.close(); //关闭流资源
FileInputStream
- 作用:用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。
- 构造方法:
- FileInputStream(File file)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。 - FileInputStream(String name)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
- FileInputStream(File file)
- 常用方法摘要:
- int available()
返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。
即此输入流的长度。 - void close()
关闭此文件输入流并释放与此流有关的所有系统资源。 - int read()
从此输入流中读取一个数据字节。 - int read(byte[] b)
从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 - int read(byte[] b, int off, int len)
从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
- int available()
FileOutputStream
- 作用:用于写入诸如图像数据之类的原始字节的流。要写入字符流,请考虑使用 FileWriter。
- 构造方法:
- FileOutputStream(File file)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 - FileOutputStream(File file, boolean append)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 。 - FileOutputStream(String name)
创建一个向具有指定名称的文件中写入数据的输出文件流。 - FileOutputStream(String name, boolean append)
创建一个向具有指定 name 的文件中写入数据的输出文件流。
- FileOutputStream(File file)
- 常用方法摘要:
- void close()
关闭此文件输出流并释放与此流有关的所有系统资源。 - void write(byte[] b)
将 b.length 个字节从指定 byte 数组写入此文件输出流中。 - void write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 - void write(int b)
将指定字节写入此文件输出流。
- void close()
例(拷贝图片):
FileInputStream fis = new FileInputStream("Picture1.jpg"); //建立字节输入流与图1关联。
FileOutputStream fos = new FileOutputStream("Picture2.jpg"); //建立字节输出流与图2关联(或创建)。
byte[] b = new byte[fis.available()]; //建立byte数组作为缓冲区,
//available()方法使得此缓冲区大小刚好与图片大小相等。
fis.read(b); //读取图片1数据存入缓冲区中。
fos.writ(b); //把缓冲区的数据写入图片2中。
fis.close(); //关闭输入流。
fos.close(); //关闭输出流。
IO流缓冲技术
- 装饰设计模式
- 定义:定义一个类,将已有的对象传入,基于原对象的功能,可提供加强的功能,定义的这个类就被成为装饰类,这种编程手法成为装饰设计模式。
- 作用:为原有的对象提供加强的功能。
- 例:
class PlayGame{
public void play(){
System.out.println("开始玩游戏");
}
}
class SuperPlay{ //此类被成为装饰类
private PlayGame pg;
SperPlay(PlayGeame pg){
this.pg = pg;
}
public void superPlay(){ //提供了加强的功能
System.out.println("开外挂");
pg.play();
}
}
class Play{
public static void main(String[] args){
PlayGame pg = new PlayGame();
SuperPlay sp = new SuperPlay(pg);//将原有对象传入
sp.superPlay();
}
}
- IO流本身部分方法的局限性以及效率不高,需要为其提供加强功能,所以就通过装饰设计模式的方法为其提供了缓冲技术,除了提高流的效率外,提供了一些实用的方法以加强流的功能。
- BufferedReader
- 为字符输入流提供了readLine()方法,可以读取一行数据。
- BufferedWriter
- 提供newLine()方法,换行,可以代替换行符,便于跨平台。
- BufferedInputStream
- BufferedOutputStream
- BufferedReader
转换流
- InputStreamReader
- 字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
- 例:键盘录入最常见的写法
读取键盘录入的read方法是字节流的方法,想要读取一行数据就要用到BufferedReader的readLine方法,所以就需要用到转换流。
BufferedReader bufr =
new BufferedReader(InputStreamReader(System.in));
System.setIn(new FileInputStream("abc.txt"));//改变标准输入设备(默认的是键盘)
- OutputStreamWriter
- 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。
- 例
BufferWriter bufw =
new BufferedWriter(new OutputStreamWriter(System.out));
bufw.writ(bufr.readLine());//把数据写入流中。
bufw.newLine();//换行,可跨平台使用。
bufw.flush(); //把数据刷新到标准输出设备上。
System.setOut(new PrintStream("abc.txt"));//改变标准输出设备(默认的是控制台)。
File
- 文件和目录路径名的抽象表示形式。可用于把文件或目录封装成File对象,方便使用。
- 字段摘要
- static String separator
与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
- static String separator
- 构造方法摘要
- File(File parent, String child)
根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。 - File(String pathname)
通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。 - File(String parent, String child)
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。 - 例
- File(File parent, String child)
File f1 = new File("file.txt");
File f2 = new File("C:\\Test","file.txt");
//用File.separator代替分隔符,方便跨平台使用。
File f3 = new File("C:" + File.separator + "Test" + File.separator + "file.txt");
方法摘要
- 创建:
- boolean createNewFile()
当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。 - boolean mkdir()
创建此抽象路径名指定的目录。 - boolean mkdirs()
创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。
- boolean createNewFile()
- 删除
- boolean delete()
删除此抽象路径名表示的文件或目录。 - void deleteOnExit()
在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。
- boolean delete()
判断
- boolean canExecute()
测试应用程序是否可以执行此抽象路径名表示的文件。 - boolean canRead()
测试应用程序是否可以读取此抽象路径名表示的文件。 - boolean canWrite()
测试应用程序是否可以修改此抽象路径名表示的文件。 - boolean isAbsolute()
测试此抽象路径名是否为绝对路径名。 - boolean isDirectory()
测试此抽象路径名表示的文件是否是一个目录。 - boolean isFile()
测试此抽象路径名表示的文件是否是一个标准文件。 - boolean isHidden()
测试此抽象路径名指定的文件是否是一个隐藏文件。 - boolean exists()
测试此抽象路径名表示的文件或目录是否存在。 - boolean equals(Object obj)
测试此抽象路径名与给定对象是否相等
- boolean canExecute()
获取信息
- File getAbsoluteFile()
返回此抽象路径名的绝对路径名形式。 - String getAbsolutePath()
返回此抽象路径名的绝对路径名字符串。 - String getName()
返回由此抽象路径名表示的文件或目录的名称。 - String getParent()
返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。 - File getParentFile()
返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。 - String getPath()
将此抽象路径名转换为一个路径名字符串。 - long length()
返回由此抽象路径名表示的文件的长度。
- File getAbsoluteFile()
- 获取文件列表
- String[] list()
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。 - String[] list(FilenameFilter filter)
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。 - File[] listFiles()
返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。 - File[] listFiles(FileFilter filter)
返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。 - File[] listFiles(FilenameFilter filter)
返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。 - static File[] listRoots()
列出可用的文件系统根。 - 过滤器:FilenameFilter(接口) 示例
- String[] list()
- 创建:
String[] arr = f.list(new FilenameFilter(){
//复写accept方法,定义过滤条件。
public boolean accept(File dir,String name){
return name.endWith{".java");
}
});
递归
- 定义:函数出现自身调用自身的情况,称之为递归。
- 例(列出目录中所有的内容):
public void showDir(File dir){
System.out.println(dir);
File[] files = dir.listFiles();
for(File file : files){
if(file.isDirectory())
showDir(file);
else
System.out.println(file);
}
}
Properties
- 作用:表示了一个持久的属性集。可用于键值对形式的配置文件。
- 特点:
- Properties属于hashtable的子类,拥有map集合的特点,且属性列表中每个键及其对应值都是一个字符串。
- 是集合中与IO技术相结合的集合容器。可保存在流中或从流中加载。
- 在接在数据时,需要配置文件具有固定的格式:键=值。
- 构造方法摘要:
- Properties()
创建一个无默认值的空属性列表。 - Properties(Properties defaults)
创建一个带有指定默认值的空属性列表。
- Properties()
- 方法摘要
- String getProperty(String key)
用指定的键在此属性列表中搜索属性。 - void list(PrintStream out)
将属性列表输出到指定的输出流。 - void list(PrintWriter out)
将属性列表输出到指定的输出流。 - void load(InputStream inStream)
从输入流中读取属性列表(键和元素对)。 - void load(Reader reader)
按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 - Object setProperty(String key, String value)
调用 Hashtable 的方法 put。 - void store(OutputStream out, String comments)
以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。 - void* store(Writer writer, String comments)
以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。 - Set< String > stringPropertyNames()
返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。
- String getProperty(String key)
- 例:
/**
*例如在系统中有一个属性配置文件info.txt。读取其中信息并对错误的属性进行修改。
*info.txt
* zhangsan=30
* lisi=99
*lisi的年龄应该为39岁,所以需要修改。
*/
class PropTest{
public static void main(String[] args) throws IOException{
FileInputStream fis = new FileInputStream("info.txt");
FileOutputStream fos = new FileOutputStream("info.txt");
Properties prop = new Properties();//创建一个Properties集合。
prop.load(fis); //加载info.txt中的信息。
prop.setProperty("lisi","39"); //修改其中lisi的内容
prop.store(fos,"..."); //将修改后的信息写入info.txt文件中。"..."为备注信息。
prop.list(System.out); //将属性列表输出到指定的输出流中:控制台。
fis.close();
fos.close();
}
}
打印流
- 打印流的作用:为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
- 字节打印流:PrintStream
构造函数可以接收的参数类型:
- file对象:PrintStream(File file)
- 字符串路径:PrintStream(String fileName)
- 字节输出流:
- PrintStream(OutputStream out)
- PrintStream(OutputStream out, boolean autoFlush)
- 字符打印流:PrintWriter
构造函数可以接收的参数类型:
- file对象:PrintWriter(File file)
- 字符串路径:PrintWriter(String fileName)
- 字节输出流:
- PrintWriter(OutputStream out)
- PrintWriter(OutputStream out, boolean autoFlush)
- 字符输出流:
- PrintWriter(Writer out)
- PrintWriter(Writer out, boolean autoFlush)
- 打印流参数为输出流时,如果不带参数 autoFlush ,则打印时不带自动刷新功能。如带参数autoFlush,且其值为true时,则打印时带自动刷新功能。
- 例
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out,true);//创建带刷新功能的PrintWriter
String line = null;
while((line=bufr.readLine())!=null){
out.println(line.toUpperCase()); //调用Println方法,输出结果。
{
bufr.close();
out.close();
文件的切割与合并
- SequenceInputStream
- 作用:表示其他输入流的逻辑串联,可用于合并文件。
- 构造方法:
- SequenceInputStream(InputStream s1, InputStream s2)
通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。
的符合规范的风格化法规及 - SequenceInputStream(Enumeration< ? extends InputStream> e)
通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。
- SequenceInputStream(InputStream s1, InputStream s2)
- 例
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("1.txt"));
v.add(new FileInputStream("2.txt"));
v.add(new FileInputStream("3.txt"));
Enumeration<FileInputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("4.txt");
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
sis.close();
fos.close();
- 文件切割
- 例
FileInputStream fis = new FileInputStream("022.jpg");
FileOutputStream fos = null;
byte[] buf = new byte[1024*1024];//定义buf的大小为1M,即为文件分割后所得碎片文件的大小
int len = 0;
int count = 1;
while((len=fis.read(buf))!=-1){
fos = new FileOutputStream("0" + count++ +".part");
fos.write(buf,0,len);
fos.close();
}
fis.close();
IO流异常的处理方法
异常的处理方法:
例
FileReader fr = null;//定义流对象的引用时定义在try结构的外面。
//把会发生异常的部分发到try结构里。
try{
fr = new FileReader("IO_Test.txt");
int i;
while((i = fr.read())!=-1)
new sop((char)i);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
if(fr != null)
fr.close(); //关闭流放在finally结构里面,
//因为此动作也会发生异常,所以要单独处理。
}catch(IOException e){
System.out.println(e.toString());
}
}
字符编码
- 字符编码的产生:由于计算机只能识别1和0两个数据,所以就用1和0所组成的不同二进制数来对应不同的字符,再把这些对应的关系列成一张表,由此就产生了字符编码。
常见的字符编码
ASCII编码:用来表示英文,它使用1个字节表示,其中第一位规定为0,其他7位存储数据,一共可以表示128个字符。
ISO8859-1:用于表示更多的欧洲文字,用8个位存储数据,一共可以表示256个字符
GBK/GB2312/GB18030:表示汉字。GBK/GB2312表示简体中文,GB18030表示繁体中文。
Unicode编码:包含世界上所有的字符,是一个字符集。
UTF-8:是Unicode字符的实现方式之一,它使用1-4个字符表示一个符号,根据不同的符号而变化字节长度。