第一讲 File类
一、概述
1、File类:文件和目录路径名的抽象表示形式。
2、特点:
1)用来将文件或者文件夹封装成对象
2)方便对文件与文件夹的属性信息进行操作 。
3)File对象可以作为参数传递给流的构造函数。
4)
File
类的实例是不可变的;也就是说,一旦创建,
File
对象表示的抽象路径名将永不改变。
二、File对象创建
方法一:
File file = new File("a.txt");
将a.txt封装成file对象。可以将已有的和为出现的文件或者文件夹封装成对象。
方法二:
File file = new File("c:\\abc","b.txt");
将文件所在目录和文件一起传入,指定文件路径。
方法三:
File d = new File("c:\\abc");
File file
= new File(d,"c.txt");
将文件目录封装成对象,再创建文件对象。
三、File中常见的方法
1、创建
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。
2、删除
boolean delete():删除失败返回false。如果文件正在被使用,删除不了返回false。
void deleteOnExit();在程序退出时删除指定文件。
3、判断
boolean exists() :文件是否存在.
isFile():是否是一个标准文件
isDirectory();是否是目录
isHidden();是否被隐藏
isAbsolute(); 是否是绝对路径
4、获取信息
getName():获取文件名
getPath():获取路径
getParent():获取父级目录
getAbsolutePath() 获取绝对路径
long lastModified() 返回文件最后一次被修改的时间
long length() 文件的长度
5、列出文件及过滤
File[] listFiles():返回一个抽象路径名数组
String[] list():返回字符串数组,表示目录中的文件和目录
File[] listFiles(FilenameFilter filter):返回抽象路径名数组,列出满足指定过滤器的文件和目录。
FilenameFilter:文件名过滤器,是一个接口,包含一个方法accept(),boolean accept(File dir,String name),对不符合条件的文件名过滤。
static File[] listRoots:列出可用的文件系统根。
String [] list(FilenameFilter filter):返回一个字符串数组,表示的目录中满足指定过滤器的文件和目录。
File[] listFiles(FileFilter filter):返回抽象路径名数组,目录中满足指定过滤器的文件和目录。
示例:
/*
需求:
通过String[] list(FilenameFilter filter)方法获取一个目录中所有的.java文件,其他文件都被过滤掉。
思路:
用匿名内部类传入一个filter对象
复写FilenameFilter接口的accept(File dir,String name)方法,并判断是否是.java文件
遍历数据,得到所有.java文件
*/
import java.io.*;
class FilterDemo
{
public static void main(String[] args)
{
listDemo();
}
//获取一个指定目录中的所有.java文件的方法
public static void listDemo()
{
File dir = new File("d:\\java01\\day19");
//创建FilenameFilter匿名内部类,创建filter对象
String[] arr = dir.list(new FilenameFilter()
{
public boolean accept(File dir,String name)
{
return name.endsWith(".java");判断文件名是否是.java结尾并返回
}
});
System.out.println("len:"+arr.length);
//遍历数组
for(String name : arr)
{
System.out.println(name);
}
}
四、递归
1、定义
函数每一次循环都可以调用本身功能来实现,即函数自身调用自身,这种表现形式,或者编程手法,称为递归。
2、递归注意:
a、限定条件。用来结束循环调用,否则会成死循环。
b、递归的次数。避免内存溢出。因为每次调用自身时都用先执行下一次调用自身的方法,不断在栈内存中开辟控件,越来越多,导致内存溢出。
示例一
/*需求:
列出指定目录下文件或者文件夹,包含子目录中的内容。也就是列出指定目录下所有内容。
思路:
因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。
在列出过程中出现的还是目录的话,还可以再次调用本功能。
所以用递归来实现。
*/
import java.io.*;
class RecursionDemo
{
public static void main(String[] args)
{ //关联指定路径
File dir = new File("d:\\test");
//列出关联路径中的所有.java文件
showDir(dir,0);
}
public static String getLevel(int level)
{
StringBuilder sb = new StringBuilder();
sb.append("|--");
//每一级目录用指定字符连接
for(int x=0; x
示例二
/*
删除一个带内容的目录。
删除原理:
在window中,删除目录从里面往外删除的。
既然是从里往外删除。就需要用到递归。
*/
import java.io.*;
class RemoveDir
{
public static void main(String[] args)
{
//指定目录
File dir = new File("d:\\testdir"); //删除目录
removeDir(dir);
}
public static void removeDir(File dir)
{
File[] files = dir.listFiles();//列出目录下所有文件和目录
for(int x=0; x
示例三
/*
练习
将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。
建立一个java文件列表文件。
思路:
1,对指定的目录进行递归。
2,获取递归过程所以的java文件的路径。
3,将这些路径存储到集合中。
4,将集合中的数据写入到一个文件中。
*/
import java.io.*;
import java.util.*;
class JavaFileList
{
public static void main(String[] args) throws IOException
{
//指定目录
File dir = new File("d:\\java01");
//定义一个list集合,存储.java文件的file对象
List list = new ArrayList();
//调用获取文件路径的方法
fileToList(dir,list);
//指定写入文件
File file = new File(dir,"javalist.txt");
//调用写入文件方法
writeToFile(list,file.toString());
}
//获取指定文件夹中的所有.java文件的绝对路径,存入集合中
public static void fileToList(File dir,List list)
{
File[] files = dir.listFiles();
for(File file : files)
{ //如果是目录继续获取
if(file.isDirectory())
fileToList(file,list);
else
{ //将.java文件的路径存入
if(file.getName().endsWith(".java"))
list.add(file);
}
}
}
//将集合中的元素写入到一个文件中
public static void writeToFile(List list,String javaListFile)throws IOException
{
BufferedWriter bufw = null;
try
{ //字符流缓冲区关联写入的文件
bufw = new BufferedWriter(new FileWriter(javaListFile));
for(File f : list)
{
String path = f.getAbsolutePath();
bufw.write(path);//写入
bufw.newLine();//换行
bufw.flush();//刷新
}
}
catch (IOException e)
{
throw new RuntimeException("写入文件失败");
}
finally
{ //关闭资源
try
{
if(bufw!=null)
bufw.close();
}
catch (IOException e)
{
throw new RuntimeException("关闭失败");
}
}
}
}
第二讲 Properties类
一、概述
1、Properties是hashtable的子类。也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。
2、特点
1)可以用于键值对形式的配置文件。
2)在加载数据时,需要数据有固定格式:键=值。
二、Properties的方法
1、设置
Object setProperty(String key,String value);设置键和值,调用Hashtable的put方法。
2、获取
String getProperty(String key);用指定的key搜索value
3、操作流的方法
void load(InputStream is);从输入流中读取属性列表。
void load(Reader reader);按简单的面向行的格式从输入字符流中读取属性列表。
void list(PrintStream out);将属性列表输出到指定的输出流。
void list(PrintWriter out);将属性列表输出到指定的输出流。
void store(OutputStream out,String comments);对应load(InputStream) 方法,将属性列表(键和元素对)写入输出流。comments是属性列表的描述。
void store(Writer writer,String comments);对应load(Reader)方法,将属性列表(键和元素对)写入输出字符。
示例
/*如何将流中的数据存储到集合中。
想要将info.txt中键值数据存到集合中进行操作。
思路:
1,用一个流和info.txt文件关联。
2,读取一行数据,将该行数据用"="进行切割。
3,等号左边作为键,右边作为值。存入到Properties集合中即可。
*/
//将文件数据存储进Properties集合的方法
public static void method() throws IOException
{ //使用字符读取缓冲流关联文件
BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
String line = null;
//定义Properties集合
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);
}
//设置和获取元素。
public static void setAndGet()
{
Properties prop = new Properties();
prop.setProperty("zhangsan","30");
prop.setProperty("lisi","39");
String value = prop.getProperty("lisi");
prop.setProperty("lisi",89+"");
Set names = prop.stringPropertyNames();
for(String s : names)
{
System.out.println(s+":"+prop.getProperty(s));
}
}
练习
/*
限制程序运行次数。当运行次数到达5次时,给出,请您注册的提示。并不再让该程序执行。
思路:
很容易想到的是:计数器。
可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。
可是随着该应用程序的退出,该计数器也在内存中消失了。
下一次在启动该程序,又重新开始从0计数。
这样不是我们想要的。
程序即使结束,该计数器的值也存在。
下次程序启动在会先加载该计数器的值并加1后在重新存储起来。
所以要建立一个配置文件。用于记录该软件的使用次数。
该配置文件使用键值对的形式。
这样便于阅读数据,并操作数据。
键值对数据是map集合。
数据是以文件形式存储,使用io技术。
那么map+io -->properties.
配置文件可以实现应用程序数据的共享。
*/
mport java.io.*;
import java.util.*;
class RunCount
{
public static void main(String[] args) throws IOException
{
Properties prop = new Properties();//创建集合对象
File file = new File("count.ini");//将文件封装
if(!file.exists())
file.createNewFile();
FileInputStream fis = new FileInputStream(file);//关联文件
prop.load(fis);//将流中的文件数据加载到集合中
int count = 0;//定义计数器
String value = prop.getProperty("time");//获取字数
if(value!=null)
{
count = Integer.parseInt(value);
if(count>=5)//如果使用次数超过5次,则禁止再使用
{
System.out.println("您好,使用次数已到,请充值后再使用!");
return ;
}
}
count++;//每使用一次自增
prop.setProperty("time",count+"");
FileOutputStream fos = new FileOutputStream(file);
prop.store(fos,"");
fos.close();//关流
fis.close();//返回程序使用的次数
}
}
第三讲 打印流
一、概述
1,、打印流包括:字节打印流(PrintStream)、字符打印流(PrintWriter)。
2、该流提供了打印方法,可以将各种数据类型的数据都原样打印。
二、字节打印流
构造函数可以接收的参数类型:
1、
file对象。File
2、
字符串路径。String
3、
字节输出流。OutputStream
三、字符打印流
构造函数可以接收的参数类型:
1、
file对象。File
2、
字符串路径。String
3、
字节输出流。OutputStream
4、
字符输出流,Writer
示例:
import java.io.*;
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对多个流进行合并。也称为合并流
2、构造函数
SequenceInputStream(InputStrean s1,InputStream s2); 通过记住这两个参数来初始化新创建的SequenceInputStream
(将按顺序读取这两个参数,先读取 s1
,然后读取 s2
),以提供从此SequenceInputStream
读取的字节。
二、合并多个流步骤
1、创建集合,并将流对象添加进集合。
2、创建Enumeration对象,将集合元素加入。
3、创建SequenceInputStream对象,合并流对象。
4、创建写入流对象,FileOutputStream对象,关联文件。
5、利用SequenceInputStream对象和FileOutputStream对象对数据进行反复读写操作。
示例
/*需求
将三个文本文件中的数据合并到一个文件中
思路:
创建一个Vector集合,将三个文本文件字节流添加到集合中
创建Enumeration对象,创建SequenceInoutStream对象关联Enumeration对象
输出流关联新文本文件
反复读写*/
import java.io.*;
import java.util.*;
class SequenceDemo
{
public static void main(String[] args) throws IOException
{
Vector v = new Vector();//创建Vector对象,并添加流对象
v.add(new FileInputStream("d:\\1.txt"));
v.add(new FileInputStream("d:\\2.txt"));
v.add(new FileInputStream("d:\\3.txt"));
Enumeration en = v.elements();//创建枚举对象
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("d:\\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();
}
}
练习
/*切割文件
需求:讲一个jpg文件按1M大小切割成几部分
思路:
使用文件字节流关联jpg文件
定义一个容器存储1M大小的数据,存满后,写入新文件
*/
import java.io.*;
import java.util.*;
class SplitFile
{
public static void main(String[] args) throws IOException
{
merge();
}
//将部分文件合并为一个可使用的文件
public static void merge()throws IOException
{ //定义一个集合存储被切割的这些部分文件数据
ArrayList list = new ArrayList();
for(int x=1; x<=3; x++)
{
al.add(new FileInputStream("d:\\splitfiles\\"+x+".part"));
}
final Iterator it = al.iterator();
//为了提高效率,创建Enumeration匿名内部类
Enumeration en = new Enumeration()
{
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};
//关联枚举对象
SequenceInputStream sis = new SequenceInputStream(en);
//将合并的文件数据写入指定文件
FileOutputStream fos = new FileOutputStream("d:\\splitfiles\\科比.jpg");
//定义临时存储数据的数组
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
//关流
fos.close();
sis.close();
}
public static void splitFile()throws IOException
{ //关联要切割的文件
FileInputStream fis = new FileInputStream("d:\\科比.jpg");
FileOutputStream fos = null;
//定义1M大小的容器
byte[] buf = new byte[1024*1024];
int len = 0;
int count = 1;
while((len=fis.read(buf))!=-1)
{ //读取满1M就写入一个文件
fos = new FileOutputStream("d:\\splitfiles\\"+(count++)+".part");
fos.write(buf,0,len);
fos.close();//写完一部分数据后关流
}
//关流
fis.close();
}
}
第五讲 其他类
一、RandomAccessFile类
1、RandomAccessFile随机访问文件,自身具备读写的方法。
2、该类不是算是IO体系中子类。而是直接继承自Object。但是它是IO包中成员。因为它具备读和写功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。
可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。其实完成读写的原理就是内部封装了字节输入流和输出流。通过构造函数可以看出,该类只能
操作文件。而且操作文件还有模式:只读r,,读写rw等。
如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。
如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖。
3、通过skipBytes(int x),seek(int x)来达到随机访问。
示例
class RandomAccessFileDemo
{
public static void main(String[] args) throws IOException
{
//writeFile_2();
readFile();
}
public static void readFile()throws IOException
{ //创建RandomAccessFile对象
RandomAccessFile raf = new RandomAccessFile("ran.txt","r");
//调整对象中指针。
//raf.seek(8*1);
//跳过指定的字节数
raf.skipBytes(8);
byte[] buf = new byte[4];
raf.read(buf);
String name = new String(buf);
int age = raf.readInt();
System.out.println("name="+name);
System.out.println("age="+age);
raf.close();
}
public static void writeFile_2()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.seek(8*0);
raf.write("赵六".getBytes());
raf.writeInt(103);
raf.close();
}
public static void writeFile()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.write("李四".getBytes());
raf.writeInt(97);
raf.write("王五".getBytes());
raf.writeInt(99);
raf.close();
}
}
二、管道流
1、PipedInputStream和PipedOutputStream
2、输入输出可以直接进行连接,通过结合线程使用。
3、方法connect(PipedOutputStream src) 使此管道输入流连接到管道输出流
src
。
示例
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();
}
}
三、DataInputStream和DataOutputStream
1、可以用于操作基本数据类型的数据的流对象。
2.、常用方法:
String readUTF();读入一个已使用UTF-8修改版格式编码的字符串。
void writeUTF(String s);将表示长度信息的两个字节写入输出流,后跟字符串
s
中每个字符的 UTF-8修改版表示形式。
int skipBytes();在输入流中跳过数据的
n
个字节,并丢弃跳过的字节。
以及对基本数据类型读入输入流和写入输出流
示例
import java.io.*;
class DataStreamDemo
{
public static void main(String[] args) throws IOException
{
//writeData();
//readData();
//writeUTFDemo();
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");
//
// osw.write("你好");
// osw.close();
// readUTFDemo();
}
public static void readUTFDemo()throws IOException
{
DataInputStream dis = new DataInputStream(new FileInputStream("utf.txt"));
//用UTF-8修改版格式编码读取字符串
String s = dis.readUTF();
System.out.println(s);
dis.close();
}
public static void writeUTFDemo()throws IOException
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("utfdate.txt"));
//用UTF-8修改版格式编码写入字符串
dos.writeUTF("你好");
dos.close();
}
public static void readData()throws IOException
{ //创建数据输入流对象
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
int num = dis.readInt();
boolean b = dis.readBoolean();
double d = dis.readDouble();
System.out.println("num="+num);
System.out.println("b="+b);
System.out.println("d="+d);
dis.close();
}
public static void writeData()throws IOException
{ //创建数据输出流对象
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(234);//将int数据写入输出流
dos.writeBoolean(true);//将boolean类型数据写入输出流
dos.writeDouble(9887.543);将double类型数据写入输出流
dos.close();
}
}
四、ByteArrayInputStream和ByteArrayOutputStream
1、用于操作字节数组的流对象
ByteArrayInputStream :在构造的时候,需要接收数据源。而且数据源是一个字节数组。
ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。这就是数据目的地。
2、因为这两个流对象都操作的是数组,并没有使用系统资源。所以,不用进行close关闭。
3、
在流操作规律讲解时:
源设备:
键盘 System.in,硬盘 FileStream,内存 ArrayStream。
目的设备:
控制台 System.out,硬盘FileStream,内存 ArrayStream。
示例:
/*用流的读写思想来操作数组。*/
import java.io.*;
class ByteArrayStream
{
public static void main(String[] args)
{
//数据源。
ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFD".getBytes());
//数据目的
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int by = 0;
while((by=bis.read())!=-1)
{
bos.write(by);
}
System.out.println(bos.size());
System.out.println(bos.toString());
// bos.writeTo(new FileOutputStream("a.txt"));
}
}