黑马程序员——IO
来源:互联网 发布:比特币 软件 编辑:程序博客网 时间:2024/05/16 00:29
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、流的简介
输入流和输出流相对于内存设备而言。
将外设中的数据读取到内存中:输入
将内存的数据写入到外设中:输出
字符流的由来:
其实就是:字节流读取文字字节数据后,不直接操作而是先查指定的编码表。获取对应的文字。
再对这个文字进行操作。简单说:字节流+编码表。
字节流的两个顶层父类:
1,InpuutStream 2,OutputStream
字符流的两个顶层父类:
1.Reader 2,Writer
就从熟悉的文字开始字符流
需求:将一些文字存储到硬盘的一个文件中。
记住:如果操作文件数据,建议优先考虑字符流
为期将数据从内存写到硬盘上,要考虑使用字符流中的输出流Writer
二、字符流
字符流——创建对象
(1)创建流对象,建立数据存放文件
FileWriter fw = new FileWriter(“Test.txt”);
(2)调用流对象的写入方法,将数据写入流
fw.write(“text”);
(3)关闭流资源,并将流中的数据清空到文件中。
fw.close();
字符流——读取文件
(1)建立一个流对象,将已存在的一个文件加载进 流。
•FileReader fr = new FileReader(“Test.txt”);
(2)创建一个临时存放数据的数组。
•char[] ch = new char[1024];
(3)调用流对象的读取方法将流中的数据读入到数组 中。
•fr.read(ch);
注意:
定义文件路径时,可以用“/”或者“\\”。
在创建一个文件时,如果目录下有同名文 件将被覆盖。
在读取文件时,必须保证该文件已存在, 否则出异常。
利用FileWriter写入数据演示:
import java.io.FileWriter;import java.io.IOException;public class FileWriterDemo {private static final String LINE_SEPARATRO=System.getProperty("line.separator");public static void main(String[] args) throws IOException {// 创建一个可以往文件中写入字符数据的输出流对象/* * 既然是往一个文件中写入文字书记,那么在创建对象时,就必须明确该文件(用于存储数据的目的地)。 * * 如果文件不存在,则会自动创建。 如果文件存在,则会被覆盖。 * * 如果构造函数中加入true,可实现对文件进行续写 */FileWriter fw = new FileWriter("demo.txt",true);/* * 调用Writer对象中的white(String)方法,写入数据。 * * 其实数据写入到临时存储缓冲区中。 * * */fw.write("abcde"+LINE_SEPARATRO+"aaffag");fw.write("xixi");/* * 进行刷新,将数据直接写入到目的地中。 */// fw.flush();/* * 关闭流,切断资源。在关闭前会调用flush刷新缓冲中的数据到目的地*/fw.close();//fw.write("saf"); java.io.IOException}}
IO异常的简单处理:
import java.io.FileWriter;import java.io.IOException;public class IOExceptionDemo {private static final String LINE_SEPARATRO = System.getProperty("line.separator");public static void main(String[] args) throws IOException {FileWriter fw = null;try {fw = new FileWriter("demo.txt"); fw.write("abcde" + LINE_SEPARATRO + "aaffag");} catch (IOException e) {// TODO: handle exceptionSystem.out.println(e.toString());} finally {if (fw != null)try {fw.close();} catch (IOException e) {throw new RuntimeException("关闭失败");}}}}
使用ReadFile读取文件演示:
import java.io.FileReader;import java.io.IOException;//需求:读取一个文本文件。将读取到的字符打印到控制台。public class FileReaderDemo2 {public static void main(String[] args) throws IOException {/* * 1,创建读取字符数据的流对象。 * * 在创建读取流对象时,必须要明确被读取的文件。一定要确定该文件是存在的。 * 用一个读取流关联一个已存在的文件。 * */FileReader fr = new FileReader("demo.txt");/* * 使用read(char[])读取文本文件数据。 * * 先创建字符数组。 */char[]buf=new char[3];int len=0;while((len=fr.read(buf))!=-1){System.out.println(new String(buf,0,len));}/*int num=fr.read(buf);//将读到的字符存储到数组中。System.out.println(new String(buf));int num1=fr.read(buf);System.out.println(new String(buf));*/fr.close();}}
利用FileWriter和FileReader进行文件的复制方法演示:
import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyTextTest_2 {private static final int BUFF_SIZE = 1024;public static void main(String[] args) {FileReader fr = null;FileWriter fw = null;try {fr = new FileReader("IO流_2.txt");fw = new FileWriter("copytest_2.txt");char[] buf = new char[BUFF_SIZE];// 定义一个变量记录读渠道的字符数(其实就是往数组里装的字符个数)int len = 0;while ((len = fr.read(buf)) != -1) {fw.write(buf, 0, len);}} catch (Exception e) {// TODO: handle exception//System.out.println("读写失败");throw new RuntimeException();} finally {if (fw != null) {try {fr.close();} catch (IOException e) {e.printStackTrace();}}if (fr != null) {try {fw.close();} catch (IOException e) {e.printStackTrace();}}}}}
三、字符流的缓冲区
缓冲区的出现提高了对数据的读写效率。
对应类
•BufferedWriter
•BufferedReader
缓冲区要结合流才可以使用。
在流的基础上对流的功能进行了增强。
利用BufferedWriter 写入数据演示:
import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;public class BufferedWriterDemo {private static final String LINE_SEPARATOR = System.getProperty("line.separator");public static void main(String[] args) throws IOException {FileWriter fw=new FileWriter("buf.txt");//为了提高写入的效率。使用了字符流的缓冲区。//创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联。BufferedWriter bufw=new BufferedWriter(fw);//使用缓冲区的写入方法,将数据县写入到缓冲区中//bufw.write("abcdef"+LINE_SEPARATOR+"nsfff");/*bufw.write("xxxxx");bufw.newLine();bufw.write("wwafa");*/for (int x = 0; x <=4; x++) {bufw.write("abcdef"+x);bufw.newLine();bufw.flush();}//使用缓冲区的刷新方法将数据刷到目的地中bufw.flush();//关闭缓冲区。其实关闭的是缓冲的流对象bufw.close();}}
使用缓冲区读取数据的方法演示:
import java.io.BufferedReader;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;public class BufferedReaderDemo {public static void main(String[] args) throws IOException {FileReader fr = new FileReader("buf.txt");BufferedReader bufr=new BufferedReader(fr);String line=null;while((line=bufr.readLine())!=null){System.out.println(line);}bufr.close();}/** * @throws FileNotFoundException * @throws IOException */private static void demo() throws FileNotFoundException, IOException {FileReader fr = new FileReader("buf.txt");char[] buf = new char[1024];int len = 0;while ((len = fr.read(buf)) != -1) {System.out.println(new String(buf, 0, len));System.out.println(len);}fr.close();}}
利用缓冲区进行文件的复制方法演示:
import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyTextByBuffTest {public static void main(String[] args) throws IOException {FileReader fr = new FileReader("buf.txt");BufferedReader bufr = new BufferedReader(fr);FileWriter fw = new FileWriter("Copy.txt");BufferedWriter bufw = new BufferedWriter(fw);String len = null;while ((len = bufr.readLine()) != null) {bufw.write(len);bufw.newLine();bufw.flush();}bufr.close();bufw.close();}}
自定义的读取缓冲区,其实就是模拟一个BufferedReader
分析:
缓冲区中无非就是封装了一个数组,
并对外提供了更多的方法对数组进行访问
其实这些方法最终操作的都是数组的角标
缓冲的原理:
其实就是从源中获取一批数据装进缓冲区中
再从缓冲区中不断地取出一个一个数据
当此次取完后,再从源中继续取一批数据进缓冲区
当源中的数据取光时,用-1作为结束标记。
方法演示:
public class MyBufferReader {private FileReader r;// 定义一个数组作为缓冲区private char[] buf = new char[1024];// 定义一个指针用于操作这个数组中的元素。当操作到最后一个元素时,指针应该归零private int pos = 0;// 定义一个计数器用于记录缓冲区中的数据个数,当数据减到0,就从源中继续获取数据到缓冲区中private int count = 0;MyBufferReader(FileReader r) {this.r = r;}/** * * */public int myRead() throws IOException {if (count == 0) {count = r.read(buf);pos = 0;}if (count < 0) {return -1;}int ch = buf[pos++];count--;return ch;/* * // 1,从源中获取一匹数据到缓冲区中。需要先做判断,只有计数器为0时,才需要从源中获取数据 if (count == 0) { * count = r.read(buf); * if (count < 0) * return -1; * * // 每次获取数据到缓冲区后,角标归零。 * char ch = buf[pos]; * pos++; * count--; * return ch; } * else if (count > 0) { * char ch = buf[pos]; * pos++; * count--; * return ch; * } return count; */}public String myReadLine() throws IOException {StringBuilder sb = new StringBuilder();int ch = 0;while ((ch = myRead()) != -1) {if (ch == '\r')continue;if (ch == '\n')return sb.toString();// 将从缓冲区独到的字符,存储到缓存行数据的缓冲区中sb.append((char) ch);}if(sb.length()!=0)return sb.toString();return null;}public void myClose() throws IOException{r.close(); }}
装饰设计模式:
对一组对象的功能进行增强时,就可以使用该模式进行问题的解决。
装饰和几次都能实现一样的特点:进行功能的扩展增强
有什么区别呢?
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体
|--BufferWriter:用于提高效率
想要对操作的动作进行效率的提高。
按照面向对象,可以通过继承对具体的进行功能的扩展。
效率提高需要加入缓冲技术。
Writer
|--TextWriter:用于操作文本
|--BuufferTextWriter:加入了缓冲技术的操作文本的对象
|--MediaWriter:用于操作媒体
|--BufferMediaWriter
但是这样做好像并不理想。
如果这个体系进行功能扩展,又多了流对象
那么这个流要提高效率,是不是也要产生子类呢?是,这是就会发现只为提高功能进行的继承
导致继承体系越来越臃肿。不够灵活
重新思考这个问题?
既然加入的都是同一种技术——缓冲。
前一种是让缓冲和具体的对象相结合。
可不可以将缓冲进行单独的封装,那个对象需要缓冲就将哪个对象和缓冲关联。
装饰比继承灵活。
特点:装饰类和被装饰类都必须所属同一个接口或者父类。
四、字节流
基本操作与字符流类相同
但它不仅可以操作字符,还可以操作其他 媒体文件
字节流的读取和写入方法演示:
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class ByteStreamDemo {public static void main(String[] args) throws IOException {demp_read();}public static void demp_read() throws IOException {//1,创建一个读取流对象,和指定的文件关联。FileInputStream fis =new FileInputStream("bytedemo.txt");byte[]buf=new byte[fis.available()];fis.read(buf);System.out.println(new String(buf));//System.out.println(fis.available());//建议使用这种读取数据的方式/*byte[]buf=new byte[1024];int len=0;while((len=fis.read(buf))!=-1){System.out.println(new String(buf,0,len));}*//*int ch=0;while((ch=fis.read())!=-1){System.out.println((char)ch);}*///一次读取一个字节//int ch=fis.read();//System.out.println(ch);fis.close();}public static void demp_write() throws IOException {//创建字节输出流对象,用于操作文件。FileOutputStream fos=new FileOutputStream("bytedemo.txt");//写数据。直接写入到了目的地中fos.write("aafaga".getBytes());fos.close();//关闭资源动作要完成}}
复制mp3的四种方法演示:
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class CopyMp3Text {public static void main(String[] args) throws IOException {copy_4();}// 千万不要用 效率没有!public static void copy_4() throws IOException {FileInputStream fis = new FileInputStream("C:\\Users\\Public\\Music\\Sample Music\\kalimba.mp3");FileOutputStream fos = new FileOutputStream("asdf.mp3");int ch = 0;while ((ch = fis.read()) != -1) {fos.write(ch);}fis.close();fos.close();}// 不建议public static void copy_3() throws IOException {FileInputStream fis = new FileInputStream("C:\\Users\\Public\\Music\\Sample Music\\kalimba.mp3");FileOutputStream fos = new FileOutputStream("asdf.mp3");byte[] buf = new byte[fis.available()];fis.read(buf);fos.write(buf);fos.close();fis.close();}private static void copy_2() throws IOException {FileInputStream fis = new FileInputStream("C:\\Users\\Public\\Music\\Sample Music\\kalimba.mp3");FileOutputStream fos = new FileOutputStream("asdf.mp3");BufferedOutputStream bos = new BufferedOutputStream(fos);BufferedInputStream bis = new BufferedInputStream(fis);// byte[] sub = new byte[1024];int ch = 0;while ((ch = bis.read()) != -1) {bos.write(ch);}bis.close();bos.close();}public static void copy_1() throws IOException {FileInputStream fis = new FileInputStream("C:\\Users\\Public\\Music\\Sample Music\\kalimba.mp3");FileOutputStream fip = new FileOutputStream("asdf.mp3");byte[] sub = new byte[1024];int len = 0;while ((len = fis.read(sub)) != -1) {fip.write(sub, 0, len);}fis.close();fip.close();}}
键盘录入的方法演示:
import java.io.IOException;import java.io.InputStream;/* * 读取一个键盘录入的数据,并打印在控制台上 * * 键盘本身就是一个标准的输入设备 * 对于java而言,对于这种输入设备都有相应的对象 * */public class ReadKey {public static void main(String[] args) throws IOException {// readKey();// System.out.println((int)'\r');// System.out.println((int)'\n');readKey2();}public static void readKey2() throws IOException {/* * 获取用户键盘录入的数据 并将数据变成大写显示在控制台上 如果用户输入的是over,结束键盘录入 * * 思路: 1,因为键盘录入只读取一个字节,要判断是否是over,需要先将读到的字节拼成字符串 * 2,那就需要一个容器。StringBuilder * 3,在用户回车之前将录入的数据变成字符串即可 */// 1,创建容器。StringBuilder sb = new StringBuilder();// 获取键盘读取流InputStream in = System.in;// 3,定义变量记录读取到的字节,并循环获取int ch = 0;while ((ch = in.read()) != -1) {// 在存储前要判定是否是换行标记,因为换行标记不存储。if (ch == '\r')continue;if (ch == '\n') {String temp = sb.toString();if ("over".equals(temp))break;System.out.println(temp.toUpperCase());sb.delete(0, sb.length());}// 将读渠道的字节存储到StringBuilder中。elsesb.append((char) ch);}/* * InputStream in=System.in; * * int ch=0; while((ch=in.read())!=-1){ System.out.println(ch); } */}public static void readKey() throws IOException {InputStream in = System.in;int ch = in.read();// 阻塞式方法System.out.println(ch);int ch1 = in.read();// 阻塞式方法System.out.println(ch1);int ch2 = in.read();// 阻塞式方法System.out.println(ch2);}}
InputStreamReader,OutputStreamWriter
转换流的由来
•字符流与字节流之间的桥梁
•方便了字符流与字节流之间的操作
转换流的应用
•字节流中的数据都是字符时,转成字符流操作更高效。
转换流的基本演示:
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;public class TransStreamDemo {public static void main(String[] args) throws IOException {// 字节流InputStream in = System.in;// 将字节转成字符的桥梁。转换流。InputStreamReader isr = new InputStreamReader(in);// 字符流BufferedReader bufr = new BufferedReader(isr);String line = null;while ((line = bufr.readLine()) != null) {if (line.equals("over"))break;System.out.println(line.toUpperCase());}}}
InputStreamReader:字节到字符的桥梁。解码。
OutputStreamWriter:字符到字节的桥梁。编码。
流的操作规律;
之所以要弄清这个规律,是因为流对象太多,开发时不知道使用哪个对象合适。
想要知道开发时用到哪些对象。只要通过四个明确即可。
1,明确源和目的(汇)
源:InputStream Reader
目的:OutputStream Writer
2,明确数据是否是纯文本数据
源:是纯文本:Reader
否:InputStream
目的:是纯文本Writer
否:OutputStream
到这里。就可以明确需求中要使用哪个体系。
3,明确具体的设备
源设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
目的设备:
硬盘:File
控制台:System.out
内存:数组
网络:Socket
4,是否需要其他额外功能
是否需要高效(缓冲区)
是就加上Buffer
需求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 buwr=new BufferedWriter( new File Writer("b.txt")
需求2: 读取键盘录入信息,并写到一个文件中
(1)明确源和目的
源: InputStream Reader
目的:OutputStream Writer
(2)是否是纯文本?
是!
源:Reader
目的:Writer
(3)明确设备
源:键盘 System.in
目的:硬盘 Fie
InputStream in=System.in;
FileWriter fw=new FileWriter("b.txt");
这样做可以完成,但是麻烦。将读取的字节数据转成字符串,再由字符流操作、
(4)需要额外功能吗?
需要:转换 将字节流转成字符流。因为明确的源是Reader,这样操作文本数据更便捷
所以要将已有的字节流转换成字符流。使用字节到字符。InputStreamReader
InputStreamReader isr=new InputStreamReader(System.in);
FileWriter fr=new FileWriter("b.txt");
还需要高效吗?
需要
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in);
BufferedWriter bufw=new BufferedWriter(new FileWriter("b.txt");
需求3:将一个文本文件数据显示在控制台上
(1)明确源和目的
源: InputStream Reader
目的:OutputStream Writer
(2)是否是纯文本?
是!
源:Reader
目的:Writer
(3)明确具体设备
源:硬盘File
目的:控制台 System.out
FileReader fr=new FileReader("a.txt);
OutputStream out=System.out;
(4)需要额外功能吗
需要:转换
FileReader fr=new FileReader("a.txt);
OutputStreamWriter osw=new OutputStreamWriter(System.out);
需要:高效
BufferedReader bufr=new BufferedReader(new FileReader("a.txt");
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out);
需求4:读取键盘录入的数据,显示在控制台上
(1)明确源和目的
源: InputStream Reader
目的:OutputStream Writer
(2)是否是纯文本?
是!
源:Reader
目的:Writer
(3)明确设备
源:键盘 System.in
目的:控制台 System.out
InputStream in=Syetem,in
OutputStream out=System.out
(4)明确额外功能
需要转换,因为都是字节流。但是操作的却是文本数据
所以使用字符流操作起来更为便捷
InputStreamReader isr=new InputStreamReader(System.in)
OutputStreamWriter osw=new OutputStreamWriter(System.out);
为了将其高效
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));
需求5:将一个中文字符串数据按照指定的编码表写入到一个文本文件中
· (1)目的 OutputStream,Writer
(2)是纯文本 Writer
(3)设备:硬盘Writer
FileWriter fw=new FileWriter("a.txt")
fw.write("你好")
注意:既然需求中已经明确了指定编码表的动作
那就不可以使用FileWriter,因为FileWriter内部是使用默认的本地码表
只能使用其父类。OutputStreamWriter。
OutputStreamWriter接收一个字节输出流对象,既然是操作文件,那么该对象应该是FileOutputStream
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("a.txt",charsetName);
需要高效
BuffereWriter bufr=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt"),charsetName)
什么时候使用转换流呢?
1,源或者目的对应的设备是字节流,但操作的是文本数据,可以使用转换流作为桥梁
2,一旦操作文本涉及到具体的指定的编码表示,必须使用转换流
四、File类
File类的创建方法演示:
import java.io.File;public class FileDemo {public static void main(String[] args) {constructorDemo();}public static void constructorDemo() {//可以将一个已存在的,或者不存在的文件或目录封装成File对象File f1= new File("c:\\a.txt");File f2=new File("c:\\","a.txt");File f=new File("c:\\");File f3=new File(f,"a.txt");//File f4=new File("c:"+System.getProperty("file.separator")+"abc\\a.txt");File f4=new File("c:"+File.separator+"abc"+File.separator+"a.txt");System.out.println(f4);}}
File类的基本方法演示:
import java.io.File;import java.io.IOException;import java.text.DateFormat;import java.util.Date;public class FileMethodDemo {public static void main(String[] args) throws IOException {/* * File对象的常见方法。 * * 1,获取 * 1.1获取文件名称 * 1.2获取文件路径 * 1.3获取文件大小 * 1.4获取文件修改时间 * * 2,创建和删除 * * 3,判断 * * 4,重命名 */// getDemo();// createAddDeleteDemo();//isDemo();//renameToDemo();listRootsDemo();}public static void listRootsDemo() {File file=new File("d:\\");System.out.println("getFreeSpace:"+file.getFreeSpace());System.out.println("getTotalSpace:"+file.getTotalSpace());System.out.println("getUsableSpace:"+file.getUsableSpace());/*File[]files=File.listRoots();for(File file:files){System.out.println(file);*///}}public static void renameToDemo() {File f1 =new File("123.txt");File f2 =new File("asd.txt");f1.renameTo(f2);}public static void isDemo() throws IOException {File f = new File("a.txt");//f.createNewFile();f.mkdir();//boolean b = f.exists();//System.out.println("b=" + b);//最好先判断是否存在System.out.println(f.isFile());System.out.println(f.isDirectory());}public static void createAddDeleteDemo() throws IOException {File dir = new File("abc\\gagas\\aga\\ha");dir.mkdirs();//创建多级目录// boolean b=dir.mkdir();//make directory// System.out.println(b);System.out.println(dir.delete());// 文件的创建和删除File file = new File("file.txt");/* * 和输出流不一样,如果文件不存在,则创建,如果文件不存在,则不创建 */// boolean b=file.createNewFile();// boolean b = file.delete();// System.out.println("b=" + b);}public static void getDemo() {File file = new File("gbk.txt");String name = file.getName();String abspath = file.getAbsolutePath();//绝对路径String path = file.getPath();//相对路径long len = file.length(); //文件大小long time = file.lastModified();//最后一次修改时间Date date = new Date(time);DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);String str_time = dateFormat.format(date);System.out.println("name:" + name);System.out.println("abspath:" + abspath);System.out.println("path:" + path);System.out.println("len:" + len);System.out.println("time:" + str_time);System.out.println("parent:" + file.getParent());}}
过滤器方法演示:
import java.io.File;import cn.itcast.io.p2.file.filter.FilterByHidden;import cn.itcast.io.p2.file.filter.FilterByJava;import cn.itcast.io.p2.file.filter.SuffixFilter;public class FileListDemo {public static void main(String[] args) {listDemo_3();}public static void listDemo_3() {File dir=new File("c:\\");File[]files=dir.listFiles(new SuffixFilter("xt"));for(File file:files){System.out.println(file);}}public static void listDemo_2() {File dir = new File("C:\\Users\\litianxiang\\workspace\\day22");String[] names = dir.list(new FilterByJava());for (String name : names) {System.out.println(name);}}public static void listDemo() {File file = new File("C:\\");/* * 获取当前目录下的文件毅力文件夹的名称,包括隐藏文件 调用list方法的File对象中中封装的必须是目录 * 否则会发生NullPointerException * 如果访问的是系统级目录也会发生空指针异常 * * 如果目录存在但是没有内容,会返回一个数组,但是长度为0 * */String[] names = file.list();for (String name : names) {System.out.println(name);}}}
import java.io.File;import java.io.FilenameFilter;public class SuffixFilter implements FilenameFilter {private String suffix;public SuffixFilter(String suffix) {super();this.suffix = suffix;}@Overridepublic boolean accept(File dir, String name) {return name.endsWith(suffix);}}
使用递归的方法对文件夹进行深度遍历:
import java.io.File;/* * 需求:对指定的目录进行所以内容的列出(包含子目录中的内容) * 也可以理解为深度遍历*/public class FileTest {public static void main(String[] args) {File dir = new File("C:\\Users\\litianxiang\\workspace\\day22");listAll(dir, 0);}public static void listAll(File dir, int level) {System.out.println(getSpace(level)+dir.getName());// 获取指定目录下的当前的所有文件夹或文件对象level++;File[] files = dir.listFiles();for (int x = 0; x < files.length; x++) {if (files[x].isDirectory()) {listAll(files[x], level);} elseSystem.out.println(getSpace(level)+files[x].getName());}}public static String getSpace(int level) {StringBuilder sb=new StringBuilder();sb.append("|--");for (int x = 0; x < level; x++) {sb.insert(0,"| ");}return sb.toString();}}
递归:
函数自身直接或者间接地调用到了自身。
一个功能在被重复使用,并且每次使用时,参与运算的结果和上一次的调用有关。
这时可以用递归来解决问题
使用递归法删除带目录的文件夹:
import java.io.File;/* * 删除一个带内容的目录 * * 原理:必须从最里面往外删 * 需要进行深度遍历*/public class RemoveDirTest {public static void main(String[] args) {File dir=new File("C:\\Users\\litianxiang\\workspace\\day23\\eae");//dir.delete();removeDir(dir);}public static void removeDir(File dir) {File[]files=dir.listFiles();for(File file :files){if(file.isDirectory()){removeDir(file);}else{System.out.println(file+":"+file.delete());}}System.out.println(dir+":"+dir.delete());} }
六、properties集合
Map
--Hashtable
|--properties
properties集合:
特点: 1,该集合中的键和值都是字符串类型
2,集合中的数据可以保存到流中,或从流获取
通常该集合用于操作以键值对形式存在的配置文件
利用Properties和流对配置信息的常见操作演示:
import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.util.Properties;import java.util.Set;public class PropertiesDemo {public static void main(String[] args) throws IOException {/* * Map * |--Hashtable * |--properties * * * properties集合: * 特点: 1,该集合中的键和值都是字符串类型 * 2,集合中的数据可以保存到流中,或从流获取 * * 通常该集合用于操作以键值对形式存在的配置文件 */// propertiesDemo();//methodDemo4();//myLoad();test();}//对已有的配置文件中的信息进行修改/* * 读取这个文件。 * 并将这个文件中的键值数据存储到集合中 * 再通过集合对数据进行修改 * 再通过流将修改后的数据存储到文本中*/public static void test() throws IOException{//读取这个文件File file =new File("info.txt");if(!file.exists()){file.createNewFile();}FileReader fr=new FileReader(file);//创建集合存贮配置信息Properties prop=new Properties();//将流中信息存储到集合中prop.load(fr);prop.setProperty("wangwu", "16");//prop.list(System.out);FileWriter fw=new FileWriter(file);prop.store(fw, "");fr.close();}// 模拟一下load方法public static void myLoad() throws IOException {Properties pro = new Properties();BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));String line = null;while ((line = bufr.readLine()) != null) {if(line.startsWith("#"))continue;String[] arr = line.split("=");//System.out.println(arr[0] + ":" + arr[1]);pro.setProperty(arr[0], arr[1]);}pro.list(System.out);bufr.close();}public static void methodDemo4() throws IOException {Properties prop = new Properties();// 几何中的数据来于一个文件// 注意:必须要保证该文件中的数据是键值对// 需要使用到读取流FileInputStream fis = new FileInputStream("info.txt");// 使用load方法。prop.load(fis);prop.list(System.out);}public static void methodDemo3() throws IOException {// 创建一个Properties集合。Properties prop = new Properties();// 存储元素prop.setProperty("zhangsan", "30");prop.setProperty("lisi", "31");prop.setProperty("wangwu", "36");prop.setProperty("zhaoliu", "20");// 想要将这些集合中的键值信息持久化存储到文件中// 需要关联输出流FileOutputStream fos = new FileOutputStream("info.txt");// 将集合中数据存储到文件中,使用strore方法prop.store(fos, "name+age");fos.close();}/** * 演示Prpperties集合和流对象相结合的特点 */public static void methodDemo2() {// 创建一个Properties集合。Properties prop = new Properties();// 存储元素// prop.setProperty("zhangsan", "30");// prop.setProperty("lisi", "31");// prop.setProperty("wangwu", "36");// prop.setProperty("zhaoliu", "20");prop.list(System.out);}/* * Properties集合的存和取 */public static void propertiesDemo() {// 创建一个Properties集合。Properties prop = new Properties();// 存储元素prop.setProperty("zhangsan", "30");prop.setProperty("lisi", "31");prop.setProperty("wangwu", "36");prop.setProperty("zhaoliu", "20");// 修改元素prop.setProperty("wangwu", "26");// 取出所有元素Set<String> names = prop.stringPropertyNames();for (String name : names) {String value = prop.getProperty(name);System.out.println(name + ":" + value);}}}
思路:
1,应该有计数器
每次程序启动都需要计数一次,并且是在原有的次数上进行计数
2,计数器就是一个变量 。突然冒出一想法,程序启动时进行计数,计数器必须存在于内存中进行计算
可是程序一结束,计数器消失了。那么再起启动该程序,计数器又重新被初始化了
而我们需要多次启动同一个应用程序,使用的是同一个计数器
这就需要计数器的生命周期变长,从内存存储到硬盘文件中
3,如何使用这个计数器呢?
首先,程序启动时,应该先读取这个用于记录计数器信息的配置文件。
获取上一次的计数器次数。并进行试用次数的判断。
其次,对该次数进行自增,并将自增后的次数重新存储到配置文件中
4,文件中的信息该如何进行存储并体现
直接存储数值可以,但是不明确该数据含义
这就有了名字和值的对应,所以可以使用键值对
可以映射关系map集合搞定,有需要读取硬盘上的数据
所以map+io=properties
演示:
import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.Properties;public class PropertiesTest {public static void main(String[] args) throws IOException {getAppCount();}public static void getAppCount() throws IOException {// 将配置文件封装成File对象File confile = new File("couny.properties");if (!confile.exists()) {confile.createNewFile();}FileInputStream fis = new FileInputStream(confile);Properties prop = new Properties();prop.load(fis);// 从集合中通过键获取次数String value = prop.getProperty("time");// 定义计数器 获取记录到的次数int count = 0;if (value != null) {count = Integer.parseInt(value);if(count>5){//System.out.println("使用次数已到,请注册!");//return;throw new RuntimeException("使用次数已到,请注册!");}}count++;// 将改变后的次数重新存储到集合中prop.setProperty("time", count + "");FileOutputStream fos = new FileOutputStream(confile);prop.store(fos, "");fis.close();fos.close();}}需求:
获取指定目录下,指定扩展名的文件(包含子目录中的)
这些文件的绝对路径写入到一个文本文件中
简单说,就是建立一个指定扩展名的文件的列表。
思路:
1,必须进行深度遍历。
2,要在遍历的过程中进行过滤,将符合条件的内容都存储到容器中
3,对容器中的内容进行遍历并将绝对路径写入到文件中。
import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.io.FilenameFilter;import java.io.IOException;import java.util.ArrayList;import java.util.List;public class Tset {public static void main(String[] args) {// getFiles();File dir=new File("C:\\Users\\litianxiang\\workspace\\day23");List<File>list=new ArrayList<File>();FilenameFilter filter=new FilenameFilter(){@Overridepublic boolean accept(File dir, String name) {return name.endsWith(".txt");}};getFiles(dir,filter,list);File destFile=new File("123.txt");write2File(list,destFile);}/** * 对指定目录的内容进行深度遍历,并按照指定过滤器进行过滤 将过滤后的内容存储到指定容器List中。 * */public static void getFiles(File dir, FilenameFilter filter, List<File> list) {File[] files = dir.listFiles();for (File file : files) {if (file.isDirectory()) {// 递归啦getFiles(file, filter, list);} else {// 对遍历到的文件进行过滤器的过滤,将符合条件的存储到集合中。if (filter.accept(dir, file.getName())) {list.add(file);}}}}public static void write2File(List<File> list, File destFile) {BufferedWriter buwf = null;try {buwf = new BufferedWriter(new FileWriter(destFile));for (File file:list){buwf.write(file.getAbsolutePath());buwf.newLine();buwf.flush();}} catch (IOException e) {throw new RuntimeException("写入失败");} finally {if (buwf != null) {try {buwf.close();} catch (IOException e) {throw new RuntimeException("关闭失败");}}}}}
七、IO中的其他流
PrintStream
1,提高了打印方法可以对多种数据类型值进行打印。并保持数据的表示形式。
2,它不抛IOExection
构造函数,接受三种类型的值
1,字符串路径
2,File对象
3,字节输出流
方法演示:
import java.io.IOException;import java.io.PrintStream;public class PrintStreamDemo {public static void main(String[] args) throws IOException { PrintStream out=new PrintStream("print.txt");out.write(97);//只写最低8位//out.print(97);//将97先变成字符串保持原有将数据打印到目的地out.close();}}
PrintWriter:字符打印流。
构造函数参数:
1,字符串路径
2,File对象
3,字节输出流
4,字符输出流
方法演示:
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;public class PrintWriterDemo {public static void main(String[] args) throws IOException {BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));PrintWriter out =new PrintWriter(System.out,true);String line=null;while((line=bufr.readLine())!=null){if("over".equals(line))break;out.println(line.toUpperCase());//out.flush();}out.close();bufr.close();}}
序列流
SequenceInputStream
对多个流进行合并。
文件合并的方法演示:
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.ArrayList;import java.util.Collections;import java.util.Enumeration;public class SequenceInputStreamDemo {public static void main(String[] args) throws IOException {/* * 需求:将1.txt 2.txt 3.txt文件中的数据合并到一个文件中 *//* * Vector<FileInputStream>v=new Vector<FileInputStream>(); v.add(new * FileInputStream("1.txt")); * v.add(new FileInputStream("2.txt")); * v.add(new FileInputStream("3.txt")); */ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();for (int x = 1; x <= 3; x++) {al.add(new FileInputStream(x + ".txt"));}Enumeration<FileInputStream>en=Collections.enumeration(al);/*Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() {final Iterator<FileInputStream> it = al.iterator();@Overridepublic boolean hasMoreElements() {return it.hasNext();}@Overridepublic FileInputStream nextElement() {return it.next();}};*/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();}}
利用配置文件和序列流对文件的切割合并的演示:
import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.Properties;/* * 文件切割器*/public class SplitFileDemo {private static final int SIZE = 1024 * 1024;public static void main(String[] args) throws IOException {File file = new File("D:\\qas.dwg");splitFile(file);}public static void splitFile(File file) throws IOException {// 用读取流关联源文件FileInputStream fis = new FileInputStream(file);// 定义一个1M的缓冲区byte[] buf = new byte[SIZE];// 创建目的FileOutputStream fos = null;int len = 0;int count = 1;/* * 切割文件时,必须记录猪被切割文件的名称,以及切割出来的碎片文件的个数,以方便于合并 * 这些信息为了进行描述,使用键值对的方式,用到了Properties对象*/Properties prop=new Properties();File dir = new File("d:\\partfiles");if (!dir.exists()) {dir.mkdirs();}while ((len = fis.read(buf)) != -1) {fos = new FileOutputStream(new File(dir, count++ + ".part"));fos.write(buf, 0, len);fos.close();}//将被切割的文件信息保存到prop集合中prop.setProperty("partcount", count+"");prop.setProperty("filename", file.getName()); fos=new FileOutputStream(new File(dir,count+".properties"));//将prop集合中的数据存储到文件中prop.store(fos, "save file info");fis.close();fos.close();}}
import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.ArrayList;import java.util.Collections;import java.util.Enumeration;import java.util.Properties;public class MergeFile {public static void main(String[] args) throws IOException {File dir = new File("D:\\partfiles");mergeFile(dir);}public static void mergeFile(File dir) throws IOException {/* * 获取指定目录下的配置文件对象*/File[] files = dir.listFiles(new SuffixFilter(".properties"));if (files.length != 1) {throw new RuntimeException(dir + ",该目录没有properties扩展名的文件或者不唯一");}// 记录配置文件对象。File confile = files[0];// 获取该文件的信息Properties prop = new Properties();FileInputStream fis = new FileInputStream(confile);prop.load(fis);String filename = prop.getProperty("filename");int count = Integer.parseInt(prop.getProperty("partcount"));// 获取该目录下的碎片文件File[] partFiles = dir.listFiles(new SuffixFilter(".part"));if (partFiles.length != count - 1) {throw new RuntimeException("碎片文件不符合要求,个数不对!应该是" + count + "个");}//将碎片文件和流对象关联并存储到集合中ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();for (int x = 0; x < partFiles.length; x++) {al.add(new FileInputStream(partFiles[x]));}//将多个流合并成一个序列流Enumeration<FileInputStream> en = Collections.enumeration(al);SequenceInputStream sis = new SequenceInputStream(en);FileOutputStream fos = new FileOutputStream(new File(dir, filename));byte[] buf = new byte[1024];int len = 0;while ((len = sis.read(buf)) != -1) {fos.write(buf, 0, len);}sis.close();fos.close();}}
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
- 黑马程序员—IO
- 黑马程序员——IO
- 黑马程序员——IO
- 黑马程序员——IO
- 黑马程序员——IO
- 黑马程序员——IO
- 黑马程序员—IO操作
- 黑马程序员—io流
- 黑马程序员—IO技术
- 黑马程序员—IO流
- 黑马程序员—IO流
- 黑马程序员 — IO流
- 黑马程序员—IO流
- 黑马程序员—IO流
- 黑马程序员—IO流
- 黑马程序员—API-Io
- 黑马程序员—IO流
- 黑马程序员—IO概述
- 原码, 反码, 补码 详解
- UVA 10082 WERTYU字符串处理
- 《正则表达式必知必会》读书笔记
- CentOS下安装Scala(事例为Scala2.11.7) 2015
- translate和left
- 黑马程序员——IO
- Ubuntu Server安装Memcached
- 第9周项目4-广义表算法库及应用(1)
- android framework添加对C++的支持
- A - 最难的一道题
- Android之BaseAdapter(笔记)
- STL 中 lower_bound 与 upper_bound 与 二分查找
- 静态方法和静态成员变量和多线程
- NMF非负矩阵分解