您的位置:首页 > 职场人生

黑马程序员——java基础知识之IO流(三)

2015-05-14 20:23 169 查看
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

(一)、File类

1、什么是File类?

File类:文件和目录路径名的抽象表现形式

2、file类的主要方法:

部分方法演示:

例子程序:

sop("path:"+f.getPath());
sop("abspath:"+f.getAbsolutePath());
sop("parent:"+f.getParent());//该方法返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。
//如果相对路径中有上一层目录那么该目录就是返回结果。

//记住在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在。
//通过exists判断。
sop("dir:"+f.isDirectory());
sop("file:"+f.isFile());
//文件是否是绝对路径
sop(f.isAbsolute());
}

public static void method_2()
{
File f = new File("file.txt");

//sop("exists:"+f.exists());

//sop("execute:"+f.canExecute());

//创建文件夹
File dir = new File("abc\\kkk\\a\\a\\dd\\ee\\qq\\aaa");
boolean mkdirs();//创建多级文件夹
sop("mkdir:"+dir.mkdirs());
}

public static void method_1()throws IOException
{
File f = new File("file.txt");
//      sop("create:"+f.createNewFile());
//sop("delete:"+f.delete());

}


总结:File类主要方法说明:

①创建

booleancreateNewFile();

//在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样,输出流对象一建立就创建文件。而且文件已经存在,会覆盖。

boolean mkdir();//创建文件夹,只能创建一级文件夹

例:

File dir=new File(“abc”);

dir.mkdir();//创建abc这个文件夹

boolean mkdirs();//创建多级文件夹

②删除

boolean delete();

//删除文件或目录。文件存在,返回true;文件不存在或者正在被执行,返回false。

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

③判断

boolean canExecute();//是否是可执行文件

boolean exists();//文件是否存在

boolean isFile();//是否是文件

boolean isDirectory();//是否是文件夹

boolean isHidden();//是否是隐藏文件

boolean isAbsolute();//文件是否是绝对路径

记住:在判断文件对象是否是文件或者目录时,必须要判断该文件对象封装的内容是否存在。通过exists判断。

④获取信息

String getName();//获取文件名

String getPath();

//获取文件的相对路径(即创建的对象传入的参数是什么就获取到什么)

String getParent();

//获取文件父目录。返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。如果相对路径中有上一层目录,那么该目录就是返回结果。

String getAbsolutePath();//获取文件的绝对路径

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

long length();//返回文件长度

3、File类创建对象主要方法:

方式一:

File f =new File(“a.txt”);

将a.txt封装成File对象。可以将已有的和未出现的文件或者文件夹封装成对象。

方式二:

File f2=newFile(“c:\abc”,”b.txt”);

将文件所在目录路径和文件一起传入,指定文件路径。

方式三:

File d=new File(“c:\abc”);

File f3=new File(d,”c.txt”);

将文件目录路径封装成对象。再创建文件对象。降低了文件于父目录的关联性。

增加小知识点:

File.separator表示目录分隔符,可以跨平台使用。

相当于路径中的“\”(双斜杠\在windows中表示表示转义后的分隔符,但是在linux系统中就不是)。

程序演示:

//创建File对象
public static void consMethod()
{
//将a.txt封装成file对象。可以将已有的和为出现的文件或者文件夹封装成对象。
File f1 = new File("a.txt");

// 将文件所在目录路径和文件一起传入,指定文件路径。
File f2 = new File("c:\\abc","b.txt");

//将文件目录路径封装成对象。再创建文件对象。降低了文件于父目录的关联性。
File d = new File("c:\\abc");
File f3 = new File(d,"c.txt");

sop("f1:"+f1);
sop("f2:"+f2);
sop("f3:"+f3);
//File.separator表示目录分隔符,可以跨平台使用。
File f4 = new File("c:"+File.separator+"abc"+File.separator+"zzz"+File.separator+"a.txt");
}

public static void sop(Object obj)
{
System.out.println(obj);
}
}


增加知识点:File类中一个列出文件和过滤文件的方法:

static File[] listRoots();//列出可用的文件系统根目录,即系统盘符

String[] list();

//列出当前目录下所有文件,包括隐藏。调用list方法的file对象必须是封装了一个目录。该目录还必须存在。

String[]list(FilenameFilter filter);

//返回一个字符串数组,获取目录中满足指定过滤器的文件或目录。

File[] listFiles();//返回一个抽象路径名数组,获取当前文件夹下的所有文件和文件夹

File[] ListFiles(FilenameFilterfilter);//返回抽象路径名数组,获取目录中满足指定过滤器的文件或目录。

演示: String[] list()的方法和 File.listRoots()方法

public static void listDemo()
{
File f = new File("c:\\abc.txt");

String[] names = f.list();//调用list方法的file对象必须是封装了一个目录。该目录还必须存在。
for(String name : names)
{
System.out.println(name);
}
}
public static void listRootsDemo()
{
//列出可用的文件系统根目录,即系统盘符
File[] files = File.listRoots();

for(File f : files)
{
System.out.println(f);
}
}
}


演示 File[] listFiles()和 File[] ListFiles(FilenameFilterfilter)的方法

public static void main(String[] args)
{//返回一个抽象路径名数组,获取当前文件夹下的所有文件和文件夹
File dir = new File("c:\\");
File[] files = dir.listFiles();

for(File f : files)
{           System.out.println(f.getName()+"::"+f.length());
}
}

public static void listDemo_2()
{
File dir = new File("d:\\java1223\\day18");
//返回一个字符串数组,获取目录中满足指定过滤器的文件或目录。
String[] arr = dir.list(new FilenameFilter()
{
public boolean accept(File dir,String name)
{

return name.endsWith(".bmp");
}
});


4、递归

①什么是递归

当函数内每一次循环还可以调用本功能来实现,也就是函数自身调用自身。这种表现形式,或者编程手法,称为递归。

②递归要注意的条件

1,限定条件。

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

③用例子一说明:

/*列出指定目录下文件或者文件夹,包含子目录中的内容。
也就是列出指定目录下所有内容。
思路分析:
因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。
在列出过程中出现的还是目录的话,还可以再次调用本功能。
也就是函数自身调用自身。
这种表现形式,或者编程手法,称为递归。
*/
import java.io.*;
class  RecursionDemo
{
public static void main(String[] args)
{
//关联指定路径
File dir=new File("e:\\Java Study\\Practice");
//列出关联路径中所有的.java文件
allFileList(dir,0);
}

//列出指定目录下的所以内容
public static void allFileList(File dir,int level)
{
//有层次的输出
System.out.println(getLevel(level)+dir);
level++;
File[] fileArr=dir.listFiles();//获取本目录下的所以文件和目录的抽象路径

//遍历
for (File file : fileArr)
{
if(file.isDirectory())
{
//如果目录下还是目录,则继续调用本函数
allFileList(file,level);
}
else
System.out.println(getLevel(level)+file);//显示(列出)文件
}
}

//带层次的列表
public static String getLevel(int level)
{
StringBuilder sb=new StringBuilder();
sb.append("|--");
//每多一级目录,就多输出指定字符
for (int x=level;x>0 ; x--)
{
//sb.append("|--");
sb.insert(0,"|  ");
}
return sb.toString();
}
}


④用例子程序二说明

删除一个带内容的目录。

删除原理:

在windows中,删除目录从里面往外面删除的。

既然是从里往外删除。就需要用到递归。

class RemoveDir
{
public static void main(String[] args)
{
//指定目录
File dir=new File("e:\\1");
//删除目录
removeDir(dir);

}

//删除传入目录
public static void removeDir(File dir)
{  //列出目录下的所以文件和文件夹
File[] files=dir.listFiles();
//遍历
for (File file : files )
{
//如果还是目录且非隐藏
if(!file.isHidden()&&file.isDirectory())
//继续删除目录里的内容
removeDir(file);
else
//删除文件
System.out.println(file.toString()+":-file-:"+file.delete());
}
//删除目录
System.out.println(dir+":::dir:::"+dir.delete());//
}
}


⑤用例子三说明递归

练习

将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。

建立一个java文件列表文件。

思路:

1,对指定的目录进行递归。

2,获取递归过程所以的java文件的路径。

3,将这些路径存储到集合中。

4,将集合中的数据写入到一个文件中。

import java.util.*;
import java.io.*;

class  JavaFileList
{
public static void main(String[] args)
{
//指定目录
File dir=new File("e:/Java Study/Practice");

//定义一个List集合,用于存储.java文件的File对象
List<File> list =new ArrayList<File>();

//调用获取文件路径方法
fileToList(dir,list);

//指定写入文件
File file=new File(dir,"javafilelist.txt");
//调用写入文件方法
writeToFile(list,file);

}
//获取指定文件夹内的所有java文件的绝对路径,并存入集合中
public static void fileToList(File dir,List<File> list)
{  //列出dir路径下的所以文件和目录,
File[] files=dir.listFiles();
//遍历
for (File file : files)
{
//如果是目录,则继续获取
if(file.isDirectory())
{  //把父目录路径也存入
list.add(file.getAbsoluteFile());
fileToList(file,list);
}
//将是.java文件的绝对路径存入
else if(file.getName().endsWith(".java"))
list.add(file);
}
}

//将集合中元素写入到一个文本文件中
public static void writeToFile(List<File> list,File file)
{

BufferedWriter bw=null;

try
{   //使用字符流缓冲区对象关联写入的文件
bw=new BufferedWriter(new FileWriter(file));
for (File file0 : list )
{
bw.write(file0.getAbsolutePath());//写入
bw.newLine();//换行
bw.flush();//刷新
}
}
catch (IOException e)
{
throw new RuntimeException("写入文件失败");
}
finally
{
try
{
if(bw!=null)
bw.close();//关流
}
catch (IOException e)
{
throw new RuntimeException("流资源关闭失败");
}
}
}
}


(二)、Properties类

1、什么是Properties类?

Properties是Hashtable的子类,它具备Map集合的特点。而且它里面还有存储的键值对,都是字符串,无泛型定义。是集合中和IO技术想结合的集合容器。

2、Properties类主要特点:

①可用于键值对形式的配置文件

②在加载时,需要数据有固定的格式,常用的是:键=值

3、Properties类的主要方法:

①、设置

Object setProperty(String key,String value);

//设置键和值,调用Hashtable的方法put

②获取

String getProperty(String key);

//指定key搜索value

Set stringPropertyName();

//返回属性列表的键集,存入Set集合

③加载流和存入流

void load(InputStream ism);

//从输入字节流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。

void load(Readerreader);

//从输入字符流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。

voidlist(PrintStream out);//将属性列表输出到指定的输出流

void store(OutputStreamout,String comments);

//对应load(InputStream )将属性列表(键值对)写入输出流。comments属性列表的描述。

void store(Writerwriter, String comments);

//对应load(Reader)将属性列表(键值对)写入输出流。comments属性列表的描述。

例子程序:

练习:限制程序运行次数。当运行次数到达5次时,给出,请您注册的提示。并不再让该程序执行。

/*
思路:
用于记录应用程序运行次数。
如果使用次数已到,那么给出注册提示。

很容易想到的是:计数器。
可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。
可是随着该应用程序的退出,该计数器也在内存中消失了。

下一次在启动该程序,又重新开始从0计数。
这样不是我们想要的。

程序即使结束,该计数器的值也存在。
下次程序启动在会先加载该计数器的值并加1后在重新存储起来。

所以要建立一个配置文件。用于记录该软件的使用次数。

该配置文件使用键值对的形式。
这样便于阅读数据,并操作数据。

键值对数据是map集合。
数据是以文件形式存储,使用io技术。
那么map+io -->properties.

配置文件可以实现应用程序数据的共享。
*/
package cn.dhjIo;

import java.io.*;
import java.util.*;

public class Text04 {
public static void main(String[] args) throws IOException{
//创建集合对象
Properties prop = new Properties();
//将文件对象进行封装
File file = new File("count.ini");
//判断文件是否存在
if(!file.exists()){
file.createNewFile();
}
//将文件与读取流相关联
FileInputStream in = new FileInputStream(file);
//将流中的文件数据以键值对的形式放入集合中
prop.load(in);
//定义计数器
int count=0;
String value = prop.getProperty("time");
if(value!=null){
count = Integer.parseInt(value);
if(count>=5){
System.out.println("使用的次数已到,请充钱");
return;
}
}
count++;
//将数据以键值对的形式存放在集合中
prop.setProperty("time", count+"");
//定义输入流
FileOutputStream out = new FileOutputStream(file);
//将集合中的键值对信息通过流写到硬盘中
prop.store(out, "");
//关闭流资源
in.close();
out.close();
}
}


(三)、打印流

打印流:

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

字节打印流:

PrintStream

构造函数可以接收的参数类型:

1,file对象。File

2,字符串路径。String

3,字节输出流。OutputStream

字符打印流:

PrintWriter

构造函数可以接收的参数类型:

1,file对象。File

2,字符串路径。String

3,字节输出流。OutputStream

4,字符输出流,Writer。

例子程序:

class  PrintStreamDemo
{
public static void main(String[] args) throws IOException
{//定义输入流
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
//定义打印流,调可以自动刷新的构造方法
PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);

String line = null;

while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line.toUpperCase());
//out.flush();
}
out.close();
bufr.close();
}
}


(四)、序列流

1、重要知识点

①SequenceInputStream对多个流进行合并。也被称为合并流。

②常用构造函数

SequenceInputStream(Enumeration

import java.util.*;
import java.io.*;

class  SequenceInputStreamDemo
{
public static void main(String[] args)throws IOException
{  //创建vector集合,并添加相关流对象
Vector<InputStream> ve=new Vector<InputStream>();
ve.add(new FileInputStream("1.txt"));
ve.add(new FileInputStream("2.txt"));
ve.add(new FileInputStream("3.txt"));
//创建枚举对象
Enumeration<InputStream> en=ve.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);
}

//关流
fos.close();
sis.close();
}
}


综合应用程序:

将一个mp3文件按1M大小切割成几部分 ,然后再将这些封开的几个部分合成一个文件

1、使用文件字节流关联mp3文件

2、定义一个容器存储1M大小的数据,当存储满时,写入一个新文件中

import java.util.*;
import java.io.*;

class  SplitFile
{
public static void main(String[] args) throws IOException
{
//指定要切割的文件
File file=new File("C:\\Users\\asus\\Desktop\\速度与激情.mp3");
//将指定文件进行切割
splitFile(file);

//指定要合并到的文件
File file1=new File("E:\\Java Study\\Practice\\day20\\splitFile\\速度与激情.mp3");
//将部分文件进行合并指定文件中
merge(file1);

}
//接收一个文件,将其按1M大小进行切割
public static void splitFile(File file)throws IOException
{
//关联要切割的文件
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));

BufferedOutputStream bos=null;

//定义1M大小存储容器
byte[] buf=new byte[1024*1024];
int len=0,x=0;
while ((len=bis.read(buf))!=-1)
{
//每满1M就写入一个新文件中
bos=new BufferedOutputStream(new FileOutputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+(++x)+".part"));
bos.write(buf,0,len);
bos.close();//没写完一个文件要记得关流
}
//关流
bis.close();
}
//将部分文件合并为一个可执行文件
public static void merge(File file)throws IOException
{
//定义一个集合存储这些部分文件关联路径数据
ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();

for (int x=1;x<=6 ; x++)
{
al.add(new FileInputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+x+".part"));
}

//因为Enumeration是Vector特有的迭代方法,所以这里创建一个Enumeration类型的匿名内部类
final  ListIterator<FileInputStream> it=al.listIterator();
Enumeration<FileInputStream> en=new Enumeration<FileInputStream>()
{
public boolean hasMoreElements()
{
return it.hasNext();
}

public FileInputStream nextElement()
{
return it.next();
}
};

//关联枚举对象
SequenceInputStream sis=new SequenceInputStream(en);

//将合并的文件数据写入指定文件中
FileOutputStream fos=new FileOutputStream(file);

//定义临时存储数据的数组
byte[] buf=new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);//写数据
}
//关流
fos.close();
sis.close();
}
}


(五)、对象的序列化

1、什么是对象的序列化?

对象的序列化就是把对象的信息存储到硬盘上,而且能够从硬盘上把对象的信息读取出来,而且可以使用读取出来的对象

2、例子程序

import java.io.*;

class ObjectStreamDemo
{
public static void main(String[] args) throws Exception
{
//writeObj();
readObj();
}
public static void readObj()throws Exception
{//定义对象的读入的流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));

Person p = (Person)ois.readObject();

System.out.println(p);
ois.close();
}

public static void writeObj()throws IOException
{//定义对象的写出流对象
ObjectOutputStream oos =
new ObjectOutputStream(new FileOutputStream("obj.txt"));
//写到硬盘上指定的文件夹
oos.writeObject(new Person("lisi0",399,"kr"));
//关闭流对象
oos.close();
}
}


(六)、管道流

管道流不用通过缓冲区,将IO流的读写直接连起来。它是通过多线程实现的。

例子程序实现原理:

import java.io.*;
//利用两个线程,一个是读的线程,一个是写的线程
class Read implements Runnable
{
private PipedInputStream in;
Read(PipedInputStream in)
{
this.in = in;
}
public void run()
{
try
{
byte[] buf = new byte[1024];

System.out.println("读取前。。没有数据阻塞");
int len = in.read(buf);
System.out.println("读到数据。。阻塞结束");

String s= new String(buf,0,len);

System.out.println(s);

in.close();

}
catch (IOException e)
{
throw new RuntimeException("管道读取流失败");
}
}
}

class Write implements Runnable
{
private PipedOutputStream out;
Write(PipedOutputStream out)
{
this.out = out;
}
public void run()
{
try
{
System.out.println("开始写入数据,等待6秒后。");
Thread.sleep(6000);
out.write("piped lai la".getBytes());
out.close();
}
catch (Exception e)
{
throw new RuntimeException("管道输出流失败");
}
}
}

class  PipedStreamDemo
{
public static void main(String[] args) throws IOException
{

PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out);

Read r = new Read(in);
Write w = new Write(out);
new Thread(r).start();
new Thread(w).start();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: