------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
IO流
流概念:
流是一组有顺序、有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
特点:
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的对象都在IO包中
分类:
1、按操作数据划分
字节流与字符流
2、按流向分类
输入流,输出流
字节流两个基类:
InputStream OutputStream
字符流两个基类:
Reader Writer
字符流
字符流的由来:
因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查指定的码表。
字节流和字符流的区别:
读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
FileWriter文件写入
定义文件路径时,可以用“/”或者“\\”。
在创建FileWriter对象时,该对象一被初始化就必须要明确被操作的文件。而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。其实该步就是在明确数据要存放的目的地。
FileWriter fw = new FileWriter("demo.txt");
fw.write("abcde");//调用write方法,将字符串写入到流中。
fw.flush();//刷新流对象中的缓冲中的数据,将数据刷到目的地中。
fw.close();//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据,将数据刷到目的地
close和flush区别:
flush刷新后,流可以继续使用
close刷新后,会将流关闭。
注意:传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。
FileWriter fw = new FileWriter("demo.txt",true);
fw.write("nihao\r\nxiexie");// \r\n:在Windows系统中代表换行
FileReader文件读取
在创建读取流对象时,和指定名称的文件相关联。要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
FileReader fr = new FileReader("demo.txt");
文件读取两种方式:
字符流缓冲区第一种:
调用读取流对象的read方法。read():一次读一个字符。而且会自动往下读。
int ch = 0;
while((ch=fr.read())!=-1)
{
System.out.println((char)ch);
}
第二种:
通过字符数组进行读取
定义一个字符数组,用于存储读到字符。该read(char[])返回的是读到字符个数。
char[] buf = new char[1024];
int num = 0;
while((num=fr.read(buf))!=-1)
{
System.out.println(new String(buf,0,num));
}
缓冲区的出现提高了对数据的读写效率。
缓冲区对应的类
BufferedWriter BufferedReader
缓冲区的出现是为了提高流的操作效率。所以在创建缓冲区之前,必须要先有流对象。该缓冲区中提供了一个跨平台的换行符。newLine();
操作步骤:
1、创建一个字符写入流对象
FileWriter fw = new FileWriter("buf.txt");
2、将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
BufferedWriter bufw = new BufferedWriter(fw);
简写为:
BufferedWriter bufw = new BufferedWriter(new FileWriter("buf.txt"));
字符读取流缓冲区:
该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。当返回null时,表示读到文件末尾。
readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。
需求:通过缓冲区复制一个.java文件。
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; class CopyTextByBuf { public static void main(String[] args) { BufferedReader bufr = null; BufferedWriter bufw = null; try { bufr = new BufferedReader(new FileReader("1.java")); bufw = new BufferedWriter(new FileWriter("2.txt")); 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("写入关闭失败"); } } } }
字节流
字节流和字符流的基本操作是相同的,但字节流还可以操作其他媒体文件。
由于媒体文件数据中都是以字节存储的,所以,字节流对象可直接对媒体文件的数据写入到文件中,而可以不用再进行刷流动作。因为字节流操作的是字节,即数据的最小单位,不需要像字符流一样要进行转换为字节。所以可直接将字节数据写入到指定文件中。
字节流:
InputStream 输入流(读) FileInputStream(读)
OutputStream 输出流(写) FileOutputStream(写)
FileInputStream(读)
第一种:读取单个字节
FileInputStream fis = new FileInputStream("fos.txt");
int ch = 0;
while((ch=fis.read())!=-1)
{
System.out.println((char)ch);
}
第二种:通过字节数组读取
FileInputStream fis = new FileInputStream("fos.txt");
byte[] buf = newbyte[1024];
int len = 0;
while((len=fis.read(buf))!=-1)
{
System.out.println(newString(buf,0,len));
}
特有方法:available()获取文件中字节的个数.
当文件比较小的时候可以用,可以不用循环直接打印;文件过大慎用
int num = fis.available();
byte[] buf = new byte[num];//定义一个刚刚好的缓冲区,不用在循环了
fis.read(buf);
需求:复制一个图片
思路:
1、用字节读取流对象和图片关联
2、用字节写入流对象创建一个图片文件。用于存储获取到的图片数据
3、通过循环读写,完成数据的存储
4、关闭资源
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; class CopyPic { public static void main(String[] args) { FileOutputStream fos = null; FileInputStream fis = null; try { fos = new FileOutputStream("2.bmp"); fis = new FileInputStream("1.bmp"); byte[] buf =new byte[1024]; int len = 0; while((len=fis.read(buf))!=-1) { fos.write(buf,0,len); } } catch (IOException e) { throw new RuntimeException("复制文件失败"); } finally { try { if(fis!=null) fis.close(); } catch(IOException e) { throw new RuntimeException("读取关闭失败"); } try { if(fos!=null) fos.close(); } catch(IOException e) { throw new RuntimeException("写入关闭失败"); } } } }
需求:通过缓冲区演示mp3的复制
由于在缓冲区内部定义了字节数组,因此不用定义数组
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 copyMp3 { public static void main(String[] args) throws IOException { BufferedInputStream bufis = new BufferedInputStream( new FileInputStream("c:\\0.mp3")); BufferedOutputStream bufos = new BufferedOutputStream( new FileOutputStream("c:\\1.mp3")); int by = 0; while ((by = bufis.read()) != -1) { bufos.write(by); } bufos.close(); bufis.close(); } }
转换流
InputStreamReader:字节转换成字符
OutputStreamWriter:字符转成字节
需求:通过键盘录入数据。当录入一行数据后,就将该行数据进行打印。如果录入的数据是over,那么停止录入。
System.out:对应的是标准输出设备,控制台
System.in:对应的标准输入设备:键盘
import java.io.IOException; import java.io.InputStream; class ReadIn { public static void main(String[] args) throws IOException { InputStream in = System.in; StringBuilder sb = new StringBuilder(); while (true) { int ch = in.read(); if (ch == '\r') continue; if (ch == '\n')// 输入字符串,当遇到回车符开始打印 { String s = sb.toString();// 把缓冲区变成字符串 if ("over".equals(s)) break;// 当输入over时结束循环 System.out.println(s.toUpperCase());// 字符串变成大写打印 sb.delete(0, sb.length());// 每次打印完清空缓冲区 } else sb.append((char) ch);// 把键盘录入的字符装入缓冲区 } } }
上述键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理,也就是readLine方法。能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?readLine方法是字符流BufferedReader类中的方法。而键盘录入的read方法是字节流InputStream的方法。那么能不能将字节流转成字符流再使用字符流缓冲区的readLine方法呢?InputStreamReader可以完成将字节流转成字符流。
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; class TransStreamDemo { public static void main(String[] args) throws IOException { // 获取键盘录入对象 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); // 获取键盘输出对象 BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while ((line = bufr.readLine()) != null) { if ("over".equals(line)) break; bufw.write(line.toUpperCase()); bufw.newLine(); bufw.flush(); } bufr.close(); } }
流操作的基本规律
通过三个明确来完成
1、明确源和目的
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer
2、操作的数据是否是纯文本
是:字符流
不是:字节流
3、当体系明确后,在明确要使用哪个具体的对象
通过设备来进行区分:
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台
举例说明:
1、将一个文本文件中数据存储到另一个文件中,复制文件
分析:
源:纯文本,Reader
设备:硬盘上一个文件, FileReader
是否需要提高效率:是! BufferedReader.
BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
目的:纯文本,Writer
设备:硬盘一个文件,FileWriter
是否需要提高效率:是!BufferedWriter
BufferedWriter bufw = newBufferedWriter( newFileWriter("b.txt"));
2、将键盘录入的数据保存到一个文件中
分析:
源:纯文本,Reader
设备:键盘,对应的对象是System.in,将System.in转换成Reader,用了Reader体系中转换流:InputStreamReader
是否需要提高效率:是!BufferedReader
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
目的:纯文本 ,Writer
设备:硬盘一个文件, FileWriter
是否需要提高效率:是!BufferedWriter
BufferedWriter bufw = new BufferedWriter(new FileWriter("1.txt"));
3、把录入的数据按照指定的编码表(utf-8),将数据存到文件中
分析:
目的:纯文本 ,Writer
设备:硬盘一个文件,FileWriter
但FileWriter默认编码表是GBK。而题目要求存储时,加入指定编码表utf-8,而指定的编码表只有转换流可以指定,所以要使用的对象是OutputStreamWriter,而该转换流对象要接收一个字节输出流,而且还可以操作的文件的字节输出流,因此用FileOutputStream
是否需要提高效率:是!BufferedWriter
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8"));
注意:涉及到字符编码转换时,需要用到转换流
File类
文件和目录路径名的抽象表现形式
特点:
1、用来将文件或文件夹封装成对象
2、方便于对文件与文件夹的属性信息进行操作
3、File类的实例是不可变的;也就是说,一旦创建,File对象表示的抽象路径名将永不改变
4、File对象可以作为参数传递给流的构造函数
File创建对象的三种方式:
方式一:
File f =new File("a.txt");
将a.txt封装成File对象,可以将已有的和未出现的文件或者文件夹封装成对象
方式二:
File f2=new File("c:\\abc","b.txt");
将文件所在目录路径和文件一起传入,指定文件路径
方式三:
File d=new File("c:\\abc");
File f3=new File(d,"c.txt");
将文件目录路径封装成对象,再创建文件对象,降低了文件于父目录的关联性
sop(f);//封装的目录是什么就打印什么
File类常见方法:
1、创建
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样,输出流对象一建立创建文件,而且文件已经存在会覆盖
boolean mkdir():创建文件夹
boolean mkdirs():创建多级文件夹
2、删除
boolean delete():删除失败返回false,如果文件正在被使用,则删除不了返falsel
void deleteOnExit();在程序退出时删除指定文件
3、判断
boolean exists() :文件是否存在.
isFile():是否是文件
isDirectory();是否是目录
isHidden();是否隐藏
isAbsolute();是否是绝对路径
4、获取信息
getName():获取名字
getPath():获取路径
getParent():获取绝对路径中的父目录
getAbsolutePath()获取绝对路径
long length()获取长度
注意:在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在,通过exists判断
需求:列出当前目录下所有文件及文件夹
public static void listDemo()
{
File f = new File("c:\\");
//调用list方法的file对象必须是封装了一个目录,该目录还必须存在
String[] names =f.list();
for(String name :names)
{
System.out.println(name);
}
}
需求:列出磁盘中有效的盘符
public static void listRootsDemo()
{
File[] files =File.listRoots();
for(File f :files)
{
System.out.println(f);
}
}
需求:文件名过滤
String[] arr =dir.list(new FilenameFilter()
{
public boolean accept(File dir,String name)
{
returnname.endsWith(".bmp");
}
});
Properties类
Properties是hashtable的子类,它具备map集合的特点,里面存储的键值对都是字符串,是集合中和IO技术相结合的集合容器
特点:
可以用于键值对形式的配置文件
在加载数据时,需要数据有固定格式:键=值
需求:将流中的数据存储到集合中
1、用一个流和info.txt文件关联
2、读取一行数据,将该行数据用"="进行切割
3、等号左边作为键,右边作为值,存入到Properties集合中即可
public static void method() throws IOException {
BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
String line = null;
Properties prop = new Properties();
while ((line = bufr.readLine()) != null) {
String[] arr = line.split("=");
prop.setProperty(arr[0], arr[1]);
}
bufr.close();
System.out.println(prop);
}
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------