黑马程序员——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);}}}


 定义功能,获取一个应用程序运行的次数,如果超过5次,给出使用次数一到请注册的提示。并不要再运行程序
 
  思路:
  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培训、期待与您交流! -------

0 0