File类
- 用来将文件或者文件夹封装成对象
- 方便对文件与文件夹的属性信息进行操作
- File对象可以作为参数传递给流的构造函数
- 了解File类的常用方法
创建文件对象
//创建一个文件对象的几种方法
import java.io.*;
public class FileDemo {
public static void main(String[] args)
{
//通过绝对路径创建对象
File f1 = new File("E:\\others\\java\\day20file\\abc\\a.txt");
sop("f1 = "+f1);
//通过相对路径创建对象
File f2 = new File("b.txt");
sop("f2 = "+f2);
//指定父目录,和子文件名称
File f3 = new File("E:\\others\\java\\day20file\\123","c.txt");
sop("f3 = "+f3);
//目录通过引用的方法
File d = new File("E:\\others\\java\\day20file\\haha");
File f4 = new File(d,"d.txt");
sop("f4 = "+f4);
//目录可以引用,但是文件不可以引用
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:
这里边的\分割符只适用于Windows系统,不是跨平台的,
File.separator,与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
使用起来是这样的。
File f = new File("E:"+File.separator+"others"+File.separator+"java"+File.separator+"day20file"+File.separator+"abc.txt");
File常见类的方法:
- 创建
- boolean createNewFile();在指定的位置创建文件,如果该文件已经存在,则不创建,返回false,和输出流不一样,输出流对象一建立创建文件,而且文件已经存在,会覆盖
- boolean mkdir();创建文件夹
- boolean mkdirs();创建多级文件夹
- 删除
- boolean delete();删除失败,返回false
- void deleteOnExit();在程序退出时删除指定文件
- 判断
- boolean exists();文件是否存在。
- isFile();判断文件对象是否是文件(该文件必须先 存在才返回真)
- isDirectory();判断文件对象是否是路径(文件夹)(该路径必须先存在才返回真)
- isHidden();判断文件是否隐藏
- isAbsolute();判断路径是否为绝对路径(该路径可以不用存在)
- 获取信息
简单的方法操作演示。
//file类中的基本方法
import java.io.*;
public class FileDemo2 {
//为了演示看起来简洁,先将异常抛出去
public static void main(String[] args) throws IOException
{
File f = new File("a.txt");//这是创建了一个对象,实际上什么都没有
File f0 = new File("b.txt");
//将该对象创建出来 实际的文件
sop("a.txt文件是否创建成功?"+f.createNewFile());
sop("b.txt文件是否创建成功?"+f0.createNewFile());
//删除文件
//f0.deleteOnExit()//这是在虚拟机退出的时候删除文件
sop("文件b.txt删除成功了吗?"+f0.delete());//这是在代码执行的时候删除文件
//创建一个路径
File f1 = new File("abcd");
sop("abcd文件夹是否创建成功"+f1.mkdir());
//创建多级目录
File f2 = new File("abc"+File.separator+"qq"+File.separator+"haha"+File.separator+"www");
sop("“礼物是否准备好?”"+f2.mkdirs());
//判断文件是否存在?
sop("a.txt文件是否存在呢?"+f.exists());
sop("abcd文件夹是否存在呢?"+f1.exists());
sop("abc文件夹是否存在呢?"+f2.exists());
//判断文件对象是文件还是文件夹
sop("f是文件吗?"+f.isFile());
sop("f1是文件吗?"+f1.isFile());
sop("f2是文件吗?"+f2.isFile());
sop("f1是文件夹吗?"+f1.isDirectory());
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:
File对象中的获取信息的方法
getName();获取对象名称
getPath();获取相对路径
getAbsolutePath();获取绝对路径
getParent();获取对象的父目录
long lastModified();获取文件最后一次被修改的时间
long length();获取文件的长度
//File类方法中的获取方法类
import java.io.*;
public class FileDemo3 {
public static void main(String[] args)
{
File f1 = new File("abc\\a.txt");
File f2 = new File("b.txt");
//不创建实际文件也可以进行获取
sop(f1.getPath());//获取相对路径
sop(f1.getAbsolutePath());//获取绝对路径
sop(f2.getPath());
sop(f1.getParent());//获取父目录
sop(f2.getParent());
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:
这里需要注意的是:
getParent方法,返回的是绝对路径中的父目录,如果获取的是相对路径,返回null
如果相对路径中有上一层目录,那么该目录就是返回结果。
替换文件名的方法演示:
//替换文件名称的方法演示
import java.io.*;
public class FileDemo4 {
public static void main(String[] args) throws IOException
{
File f1 = new File("E:\\others\\java\\day20file\\a.txt");
File f2 = new File("E:\\others\\java\\day20file\\b.txt");
f1.createNewFile();//将f1对象创建成存在的文件
//将f1文件名替换成f2上的名称
sop("renameTo:"+f1.renameTo(f2));
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果为:
第一次运行,打印结果为真,第二次运行,打印结果为假
文件名由a.txt变为b.txt
File类中的其他方法演示:
static listRoots();//列出可用的文件系统根,也就是盘符
//File类中其他方法的演示
import java.io.*;
public class FileDemo4 {
public static void main(String[] args) throws IOException
{
File[] files = File.listRoots();
for(File f :files )
{
sop(f);
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:
list方法:返回一个字符串数组,这些字符串指定此路径名表示的目录中的文件和目录。
演示:
//列出指定目录中所有的文件
import java.io.*;
public class FileDemo4 {
public static void main(String[] args) throws IOException
{
//指定一个目录名,这个目录必须存在
File f = new File("e:\\others\\java");
//根据list方法获取到目录中的所有文件和文件夹的名称
String[] lists = f.list();
for(String name:lists)
{
sop(name);
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:
能不能获取我想要的文件呢?比如说获取后缀名为.class的文件呢?
list方法的重载方法,可以做到,
在list方法的参数中传一个FilenameFilter(接口)过滤器;然后复写里面的accept方法,
原理是:list方法可以获取到该目录下所有的文件,accept方法读取到所有的文件名之后,进行条件的判断,是不是以.class结尾的,如果是,则返回真,如果不是则返回假
//用过滤器选出想要的文件,并打印出来
import java.io.*;
public class FileDemo4 {
public static void main(String[] args) throws IOException
{
//指定一个目录名,这个目录必须存在
File f = new File("e:\\others\\java\\day20file");
//根据list方法获取到目录中的所有文件和文件夹的名称
String[] lists = f.list(new FilenameFilter()//因为FilenameFilter是一个接口,所以这里用内部类的方法传参数
{
//复写里边的方法accept,参数为一个file对象(目录)一个String类型的文件名
public boolean accept(File dir,String name)
{
return name.endsWith(".class");//只要list方法读取到的文件的名称的后缀名为.class,就返回真
}
});
for(String name:lists)//然后把集合中的内容打印出来
{
sop(name);
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:
这个list方法可以获取到的文件名,也就是字符串类型的,
listFiles方法可以获取到文件对象File,可以进行更多的操作。
//用过滤器选出想要的文件对象,并打印出来获取到的文件名和长度
import java.io.*;
public class FileDemo4 {
public static void main(String[] args) throws IOException
{
File dir = new File("e:\\others\\java\\day20file");
//使用listFiles方法获取到所有的文件对象
File[] files = dir.listFiles();
for(File file:files)
{
sop(file.getName()+"....."+file.length());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:
发现,指定目录下的文件夹的长度是获取不到长度的,
那么需求来了,,想要获取到指定目录中目录中的文件,也就是目录下还有目录,需要将里边的所有文件打印出来。
因为在目录中还有目录,只要使用同一个列出目录功能的函数完成即可
在列出过程中出现还是目录的话,还可以再次调用本功能
也就是函数自身调用自身
这种表现形式,或者变成手法,称为递归。
用代码来演示递归:
//列出目录中的所有文件,以及目录中子目录中的所有文件
import java.io.*;
public class AllFileList {
public static void main(String[] args)
{
File dir = new File("e:\\others\\java\\day20file");
getDir(dir);//获取目录中文件的方法
}
public static void getDir(File dir)
{
sop(dir);//先打印一次目录名
File[] files = dir.listFiles();//获取所有的文件对象
for(File f:files)
{
if(f.isDirectory())//判断如果获取到的文件对象是目录,就再调用一次自己的方法
getDir(f); //这种在自己的方法中再一次调用自己的方法的模式叫做递归
sop(f.getName());//如果不是目录就直接打印出来对象的名字
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果:
使用递归时要注意
1,要有限定条件,否则就陷入了死循环
2,要注意递归的次数,尽量避免内存溢出。
演示几个递归的例子:
public class DiGuiTest {
public static void main(String[] args)
{
toBin(6);//110;
sop(getSum(10));//55
}
//获取一个十进制数的二进制数
public static void toBin(int num)
{
//判断如果num值大于0.就调用一次自己的方法,然后再打印数据
if (num>0)
{
toBin(num/2);
sop(num%2);
}
}
//获取一个数从1加到他的总和
public static int getSum(int n)
{
if(n==1)
return 1;
else
return n+getSum(n-1);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
再回来说之前打印目录中的文件的例子,打印的很难看,没有层次感,想在每一个目录下边加两个空格,于是就要获取到每个目录的层次:
//列出目录中的所有文件,以及目录中子目录中的所有文件
import java.io.*;
public class AllFileList {
public static void main(String[] args)
{
File dir = new File("e:\\others\\java\\day20file");
getDir(dir,0);//获取目录中文件的方法
}
public static void getDir(File dir,int level)//该方法可以有层次的获取目录中的文件
/*
具体思路是,
每调用一次该方法,level的值自增一次
打印文件内容的时候,在前边吧层次分割符加上,也就是加上getLevel方法就好了
*/
{
sop(getLevel(level)+dir.getPath());
level++;
File[] files = dir.listFiles();
for(File f:files)
{
if(f.isDirectory())
getDir(f,level);
sop(getLevel(level)+f.getName());
}
}
public static String getLevel(int level)//该方法可以给每一个层次前边添加空格,作为层次分割符号
/*
具体思路是,在一个缓冲区中先加入一个|--符号,
传进来的数字是多少,就在该符号前边添加多少个空格
最后将字符串中的数据全部返回去
*/
{
StringBuilder sb = new StringBuilder();
sb.append("|--");
for(int x = 0;x<level;x++)
{
sb.insert(0," ");
}
return sb.toString();
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果为:
需求:删除一个带内容的目录
删除原理
在Windows中,删除目录是从里面往外面删除的,
既然是从里往外删除,就用到了递归。
//删除目录中的文件,连同目录也删了
import java.io.*;
public class DeleteDemo {
public static void main(String[] args)
{
File dir = new File ("e:\\others\\java\\day20file\\abcd");
deleteDir(dir);
}
public static void deleteDir(File dir)
{
File[] files = dir.listFiles();
for(File f : files)
{
if(f.isDirectory())
deleteDir(f);//如果碰到目录文件,再次调用自己的方法
else
f.delete();
}
//里边的东西都删完了,该删最外面的目录了
dir.delete();
}
}
练习:将一个指定目录下的java文件的绝对路径,存储到一个文本文件中
建立一个java文件列表文件
思路:
1,对指定的目录进行递归
2,获取递归过程所有的java文件的路径
3,将这些路径存储到集合中
//将目录中所有的java文件的绝对路径存储到一个txt文件中
import java.io.*;
import java.util.*;
public class JavaFileList {
public static void main(String[] args)
{
File dir = new File("e:\\others\\java");//指定一个目录,要把这里边的所有java文件读出来,
List<File> list = new ArrayList<File> ();//按照思路,先把读到的所有的文件对象存到集合中
File file = new File(dir,"javafilelist.txt");//所有的数据要写入的文件定义好
getDir(dir,list);//该方法将dir目录中的所有符合条件的文件对象装进集合中
listToText(list,file);//该方法将集合中的对象的绝对路径值写入到文件中
}
public static void getDir(File dir,List<File> list)
{
File[] files = dir.listFiles();
for(File f : files)
{
if(f.isDirectory())
getDir(f,list);
else
{
if(f.getName().endsWith(".java"))//如果符合条件,将对象装入到集合中
list.add(f);
}
}
}
public static void listToText(List<File> list,File file)//该方法将集合中的java文件对象的绝对路径写入到文件中
{
BufferedWriter bufw = null;
try
{
bufw = new BufferedWriter(new FileWriter(file));
for(File f1:list)
{
String path = f1.getAbsolutePath();
bufw.write(path);
bufw.newLine();
bufw.flush();
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if(bufw!=null)
try
{
bufw.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
运行结果:
Properties简述
Properties是hashtable的子类
也就是说它具备map集合的特点,而且它里边存储的键值都是字符串(不用定义泛型)
是集合中和IO技术相结合的集合容器
该对象的特点:可以用于键值对形式的配置文件
在加载数据时,通常有固定格式:键=值
比如:EditPlus中可以设置自己的字体颜色,当我设置以后把软件关掉,重新开启之后,字体颜色还是改过之后的,说明,我们改的属性在软件的配置文件中,软件每次一运行,都会执行他的配置文件。
Properties的简单操作:
//实现Properties的存取
import java.io.*;
import java.util.*;
public class PropertiesDemo {
public static void main(String[] args)
{
Properties prop = new Properties();//创建一个新的Properties对象
set(prop);//在里边设置键值对
modificatoin(prop);//修改里边的键值对
get(prop);//获取键值对
}
public static void set(Properties prop)//该方法用来设置里边的键值对
{
//使用setProperty();
prop.setProperty("zhangsan","39");
prop.setProperty("lisi","50");
System.out.println(prop);
}
public static void modificatoin(Properties prop)//修改属性键值对的内容
{
//还是用setProperty()方法
prop.setProperty("lisi","88");
}
public static void get(Properties prop)//获取属性键值对中的信息
{
Set<String> names = prop.stringPropertyNames();//获取到键的名称,并存进set集合中
for(String name:names)
{
System.out.println("name = "+name+".........."+"value = "+prop.get(name));
}
}
}
运行结果:
那么如何将流中的数据存储到集合中,
就是将info.txt中的数据加载进prop中?
//将流中的数据加载进集合
import java.io.*;
import java.util.*;
/*
思路是:
将一个文件和读取流相关联
将读取到的整行的数据,用=分割开,作为键和值
将分隔开的字符作为键和值存储金prop中
*/
//这里为了演示看起来方便,先将异常抛出,不予处理
public class FileToProp {
public static void main(String[] args) throws IOException
{
method_2();
}
public static void method_1() throws IOException
{
//该方法是按照整体思路走的,可是实现将流中的数据存储进prop中。
BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
Properties prop = new Properties();
String line = null;
while((line = bufr.readLine())!=null)
{
//读取到的数据用=分割开
String[] strs = line.split("=");
//将=两边的数据分别加载进集合
prop.setProperty(strs[0],strs[1]);
}
System.out.println(prop);
}
public static void method_2() throws IOException
{
//在Properties类中提供了将流中的数据加载进集合的方法load
BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
Properties prop = new Properties();
prop.load(bufr);
System.out.println(prop);
}
}
运行结果:
代码中可以发现,使用Properties中的方法方便很多,
想到,如果我将数据加载进内存的时候,可不可以对数据进行修改呢?
//将流中的数据加载进集合
import java.io.*;
import java.util.*;
/*
思路是:
将一个文件和读取流相关联
将读取到的整行的数据,用=分割开,作为键和值
将分隔开的字符作为键和值存储金prop中
*/
//这里为了演示看起来方便,先将异常抛出,不予处理
public class FileToProp {
public static void main(String[] args) throws IOException
{
method_2();
}
public static void method_1() throws IOException
{
//该方法是按照整体思路走的,可是实现将流中的数据存储进prop中。
BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
Properties prop = new Properties();
String line = null;
while((line = bufr.readLine())!=null)
{
//读取到的数据用=分割开
String[] strs = line.split("=");
//将=两边的数据分别加载进集合
prop.setProperty(strs[0],strs[1]);
}
System.out.println(prop);
}
public static void method_2() throws IOException
{
//在Properties类中提供了将流中的数据加载进集合的方法load
BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
Properties prop = new Properties();
//将流中的数据加载进内存
prop.load(bufr);
//在这里对数据进行修改:
prop.setProperty("lisi","3");
//将集合中的元素输出到指定的输出流
prop.list(System.out);
}
}
运行结果发现,打印在控制台上的数据,是修改之后的数据,但是原文件中的数据还是以前的,也就是说修改后的数据没有保存在配置文件中。
prop.store方法,store(Writer writer, String comments)
将属列表中的数据,写入到输出流中,comments是注释,写不写都行的
对代码进行修改:
//将流中的数据加载进集合
import java.io.*;
import java.util.*;
//这里为了演示看起来方便,先将异常抛出,不予处理
public class FileToProp {
public static void main(String[] args) throws IOException
{
method_2();
}
public static void method_2() throws IOException
{
//在Properties类中提供了将流中的数据加载进集合的方法load
FileInputStream fis = new FileInputStream("info.txt");
Properties prop = new Properties();
//将流中的数据加载进内存
prop.load(fis);
//在这里对数据进行修改:
prop.setProperty("lisi","39");
//将集合中的元素输出到指定的输出流
prop.list(System.out);
//创建一个输出流,和文件关联
FileOutputStream fos = new FileOutputStream("info.txt");
//这里注意,因为这里文件读取流和文件写入流关联的是同一个文件,
//不可以在相邻的两行中连续创建文件的读取流和写入流。
//将列表中的文件再写入到文件中
prop.store(fos,"jaja");
fis.close();
fos.close();
}
}
运行结果为:
练习:建立一个配置文件,里边存储软件的运行次数,如果次数到了,那么给出注册提示。
思路:很容易想到的是计数器
可是该计数器定义在程序中,随着程序的运行而在内存中存在并进行自增
可是随着该应用程序的退出,该计数器也在内存中消失了
下一次再启动程序,又从0开始计数。
这不是我们想要的,
程序即使结束,该计数器的值也存在
下次程序启动会先加载该计数器的值,并加1后重新存储起来
键值对数据是map集合
数据是以文件形式存数的,使用IO技术
那么map+IO-->properties
//使用配置文件控制程序执行的次数
import java.io.*;
import java.util.*;
public class Runcount {
public static void main(String[] args) throws IOException
{
File file = new File("count.ini");
if(!file.exists())
file.createNewFile();
FileInputStream fis = new FileInputStream(file);
Properties prop = new Properties();
//每运行一次,先读取配置文件中的额信息
prop.load(fis);
//找键为time的值,第一次找是找不到的,返回null,count++后存进列表中
//如果找到了,把count的值取出来自增后存进列表中
String value = prop.getProperty("time");
int count = 0;
if(value!=null)
{
count = Integer.parseInt(value);
if(count>=4)
System.out.println("您好,您的试用次数已到,请您注册");
}
count++;
prop.setProperty("time",count+"");//Properties中的元素都是字符串,所以count+""表示将count转换为字符串
//最后将雷彪中的信息写进文件中。
FileOutputStream fos = new FileOutputStream(file);
prop.store(fos,"");
fis.close();
fos.close();
}
}
运行结果为:
打印流
该流提供了打印方法可以将各种数据类型的数据都原样打印
字节打印流
PrintStream
构造函数可以接收的参数类型
1,file对象 File
2,字符串路径 String
3,字节输出流 OutputStream
字符打印流
PrintWriter
构造函数可以接收的参数类型
1,file对象 File
2,字符串路径 String
3,字节输出流 OutputStream
4,字符输出流 Writer
简单的演示一下,普通的获取键盘录入的数据,然后打印在控制台上
//打印流的方法演示
//我想读取键盘录入,将键盘上敲的字符直接打印在控制台上
import java.io.*;
public class PrintStreamDemo{
public static void main(String[] args) throws IOException
{
//开启两个流对象,PrintWriter对象比Writer对象强大,
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out);
String line = null;
while ((line = bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line.toUpperCase());//自带换行的方法
out.flush();//写完要记得刷新,如果不刷新的话,他会将读取到的数据写入到缓冲区中
}
bufr.close();
out.close();
}
}
运行结果:
PrintWriter的强大之处还在于,可以自己刷新
在构造方法时可以看到:
只有println方法输出的时候,才会用自己刷新的。只要在构造方法的时候,流参数后边加一个true
//打印流的方法演示
//我想读取键盘录入,将键盘上敲的字符直接打印在控制台上
import java.io.*;
public class PrintStreamDemo{
public static void main(String[] args) throws IOException
{
//开启两个流对象,PrintWriter对象比Writer对象强大,
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());//自带换行的方法
//上边有了true,方法println会会自动刷新,这里可以不用写刷新方法
}
bufr.close();
out.close();
}
}
一样可以运行的,
那么我想将键盘录入的数据装进一个文件里呢?
只要将文件对象封装成流对象就可以实现读写时候的自动刷新了。
//打印流的方法演示
//我想读取键盘录入,将键盘上敲的字符直接打印在一个文本文件中
import java.io.*;
public class PrintStreamDemo{
public static void main(String[] args) throws IOException
{
//只要在这里创建一个文件对象
File file = new File("a.txt");
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//在这里将文件包装成流对象,再传入true值,就可以实现流的自动刷新。
PrintWriter out = new PrintWriter(new FileWriter(file),true);
String line = null;
while ((line = bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line.toUpperCase());
}
bufr.close();
out.close();
}
}
运行结果:
SequenceInputStream合并流对象
SequenceInputStream可以将多个流对象合并成一个大的流对象。
形成一个流对象的串联模式。
比如:将三个文件中的数据要打印到同一个文件中,需要建立三个流对象,如果一个一个的往里边存的话,就麻烦了,所以这里可以将三个流对象合并成一个大的流对象。
构造方法可以看出来,有两个流对象可以直接将流对象传进去,
如果流对象多的话,直接用Enumeration集合中,(Enumeration集合是Vector接口中的子类)
示例如下:
//合并流演示
//将1.txt和2.txt和3.txt中的文字连续写入到4.txt中
import java.io.*;
import java.util.*;
public class SequenceDemo {
public static void main(String[] args) throws IOException
{
//先创建集合,将文件封装成流对象存入集合中
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("1.txt"));//文件中都是数字1
v.add(new FileInputStream("2.txt"));//文件中都是数字2
v.add(new FileInputStream("3.txt"));//文件中都是数字3
//将集合中的元素用枚举遍历出来,交给一个对象en
Enumeration<FileInputStream> en = v.elements();
//万事具备,创建大流
SequenceInputStream sis = new SequenceInputStream(en);
//创建目标文件的流对象
FileOutputStream fos= new FileOutputStream(new File("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();
}
}
运行结果为:
文件切割
将文件切割成相等的几部分,
思路:
创建一个读取流对象,和要切割的文件相关联,
在创建一个写入流的空引用,
开始读取文件,创建一个固定大小的容器,读到容器大小的数据就新创建一个写入流对象,写完立马就把流关掉,
具体代码演示:
//切割文件
import java.io.*;
import java.util.*;
public class SplitFile {
public static void main(String[] args)
{
File file = new File("1.mp3");
FileInputStream fis = null;
FileOutputStream fos = null;
try
{
//读取流关联文件
fis = new FileInputStream(file);
//固定缓冲区的长度为1兆
byte[] buf = new byte[1024*1024];
int len = 0;
int count = 1;
while ((len = fis.read(buf))!=-1)
{
try
{
//只要读到了一兆的数据,马上创建一个写入流对象,将数据写进去,写完立马关资源
fos = new FileOutputStream("e:\\others\\java\\day20file\\splitfile\\"+((count++)+".part"));
fos.write(buf,0,len);
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if(fos!=null)
fos.close();
}
//当再次读够一兆数据的时候,新开一个写入流对象,写入数据
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if(fis!=null)
fis.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
运行结果:
那么能切割就可以把碎片文件拼在一起:用的是SequenceINputStream的方法
//切割文件
import java.io.*;
import java.util.*;
public class SplitFile {
public static void main(String[] args)
{
spiltFile();
pinJie();
}
//该方法可以将碎片文件拼接在一起
public static void pinJie()
{
//Vector效率低,所以这里用ArrayList集合存数据
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for (int x = 1;x<6 ;x++ )
{
try
{
al.add(new FileInputStream("splitfile\\"+x+".part"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
//而SequenceInputStream需要的参数是Enumeration的,这里就要将ArrayList中的数据用枚举的方式取出来
final Iterator<FileInputStream> it = al.iterator();
//因为Enumeration是一个接口,里边只有两个方法,所以可以给他创建子类对象,只要覆盖两个方法就可以了
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
{
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};
//开始用SequenceInputStream获取大流,写数据
SequenceInputStream sis = null;
FileOutputStream fos = null;
try
{
sis = new SequenceInputStream(en);
fos = new FileOutputStream(new File("splitfile\\2.mp3"));
byte[] buf = new byte[1024];
int len = 0;
while((len = sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if(sis!=null)
try
{
sis.close();
}
catch (IOException e)
{
e.printStackTrace();
}
if(fos!=null)
{
try
{
fos.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
//该方法可以将文件切割开
public static void spiltFile()
{
File file = new File("1.mp3");
FileInputStream fis = null;
FileOutputStream fos = null;
try
{
//读取流关联文件
fis = new FileInputStream(file);
//固定缓冲区的长度为1兆
byte[] buf = new byte[1024*1024];
int len = 0;
int count = 1;
while ((len = fis.read(buf))!=-1)
{
try
{
//只要读到了一兆的数据,马上创建一个写入流对象,将数据写进去,写完立马关资源
fos = new FileOutputStream("e:\\others\\java\\day20file\\splitfile\\"+((count++)+".part"));
fos.write(buf,0,len);
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if(fos!=null)
fos.close();
}
//当再次读够一兆数据的时候,新开一个写入流对象,写入数据
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if(fis!=null)
fis.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
运行结果: