IO流
一、File类
File类:用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作。File对象可以作为参数传递给流的构造函数。
例:创建File对象。
import java.io.*;
class Demo
{
public static void main(String []args){
consMethod();
}
public static void consMethod(){
//创建File对象
File f1 = new File("c:\\abc","a.txt");
File f2 = new File("c:\\abc\\a.txt");
File d = new File("c:\\abc");
File f3 = new File(d,"a.txt");
}
}
separator:跨平台分隔符。static String separator
与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
例:
import java.io.*;
class Demo
{
public static void main(String []args){
consMethod();
}
public static void consMethod(){
//创建File对象
File f1 = new File("c:"+File.separator+"abc","a.txt");
File f2 = new File("c:"+File.separator+"abc"+File.separator+"a.txt");
File d = new File("c:"+File.separator+"abc");
File f3 = new File(d,"a.txt");
}
}
File类的常见方法:
1.创建
boolean createNewFile()
当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样,输出流一建立就创建文件,而且文件已存在会覆盖。
boolean mkdir()
创建此抽象路径名指定的目录。
boolean mkdirs()
创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。
mkdir():创建目录,只能创建一级目录。
mkdirs():创建多级目录。
例:
import java.io.*;
class Demo
{
public static void main(String []args) throws Exception{
File f = new File("file.txt");
//f.mkdir();
f.createNewFile();
}
}
注:mkdir(),mkdirs()是创建目录,createNewFile()是创建文件。2.删除
boolean delete()
删除此抽象路径名表示的文件或目录。
void deleteOnExit()
在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。
delete():删除失败返回false。
deleteOnExit():在退出时删除指定文件。
例:
import java.io.*;
class Demo
{
public static void main(String []args) throws Exception{
File f = new File("file.txt");
System.out.println("create:"+f.createNewFile());
Thread.sleep(3000);
f.deleteOnExit();
throw new RuntimeException();
}
}
效果:程序运行时,创建了“file.txt”文件,3秒后出现抛出异常,但是设置了deleteOnExit()后,文件能正常删除。
deleteOnExit()特点:程序即使发生了异常,也能正常删除文件,避免了垃圾文件的产生。
3.判断
boolean canExecute()
测试应用程序是否可以执行此抽象路径名表示的文件。
canExecute():判断是否可执行。
boolean isAbsolute()
测试此抽象路径名是否为绝对路径名。
boolean isDirectory()
测试此抽象路径名表示的文件是否是一个目录。
boolean isFile()
测试此抽象路径名表示的文件是否是一个标准文件。
boolean isHidden()
测试此抽象路径名指定的文件是否是一个隐藏文件。
isAbsolute():是否是绝对路径(即使文件不存在)。
isDirectory():是否是目录。
isFile():是否是文件。
isHidden():是否是隐藏文件。
例:
import java.io.*;
class Demo
{
public static void main(String []args){
File f = new File("file.txt");
System.out.println("dir:"+f.isDirectory());
System.out.println("file:"+f.isFile());
}
}
注:记住在判断文件对象是否是文件或目录时,必须要先判断该文件对象封装的内容是否存在。
boolean exists()
测试此抽象路径名表示的文件或目录是否存在。
exists():文件是否存在。
例:
import java.io.*;
class Demo
{
public static void main(String []args){
File f = new File("file.txt");
System.out.println("exists:"+f.exists());
System.out.println("dir:"+f.isDirectory());
System.out.println("file:"+f.isFile());
}
}
4.获取信息
getName()
返回由此抽象路径名表示的文件或目录的名称。
String getParent()
返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。
File getParentFile()
返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。
String getPath()
将此抽象路径名转换为一个路径名字符串。
String getAbsolutePath()
返回此抽象路径名的绝对路径名字符串。
long lastModified()
返回此抽象路径名表示的文件最后一次被修改的时间。
long length()
返回由此抽象路径名表示的文件的长度。
getAbsoluteFile()和getAbsolutePath()的区别:前者把返回的绝对路径封装成了File对象。
例:
import java.io.*;
class Demo
{
public static void main(String []args) throws Exception{
File f = new File("a.txt");
System.out.println(f.getPath());
System.out.println(f.getAbsolutePath());
System.out.println(f.getParent());
}
}
getParent():没有明确的父目录会返回null,该方法返回的是绝对路径中的父目录。如果获取的是相对路径返回null。如果相对路径中有上一层目录,那么该目录就是返回结果。
renameTo(): 重命名。
boolean renameTo(File dest)
重新命名此抽象路径名表示的文件。
例:import java.io.*;
class Demo
{
public static void main(String []args) throws Exception{
File f1 = new File("Test.txt");
File f2 = new File("haha.java");
System.out.println(f1.renameTo(f2));
}
}
listRoots():列出盘符。
static File[] listRoots()
列出可用的文件系统根。
例:
import java.io.*;
class Demo
{
public static void main(String []args) throws Exception{
File[] file = File.listRoots();
for(File filename : file){
System.out.println(filename.toString());
}
}
}
listFiles():获取目录下的文件组成的数组。
File[] listFiles()
返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
例:
import java.io.*;
class Demo
{
public static void main(String []args) throws Exception{
File file = new File("C:\\Users\\Administrator\\Desktop\\wizweb");
File[] filelist = file.listFiles();
for(File filename : filelist){
System.out.println(filename.toString());
}
}
}
注:调用list方法的file对象必须封装了一个目录,该目录还必须存在。内容包含隐藏文件。
练习:过滤文件
查阅Api文档,既然是操作文件的,那么就查找File类
String[] list(FilenameFilter filter)
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。
点开FilenameFilter
boolean accept(File dir, String name)
测试指定文件是否应该包含在某一文件列表中。
复写accept方法,可以通过内部类形式简化代码。
import java.io.*;
class Demo
{
public static void main(String []args) throws Exception{
File file = new File("C:\\Users\\Administrator\\Desktop");
//过滤,将满足条件的文件存到字符串数组。
String[] dirlist = file.list(new FilenameFilter(){
public boolean accept(File dir,String name){
if(name.endsWith(".java"))
return true;
return false;
}
});
//遍历数组,打印符合条件的文件名
for(String filename : dirlist){
System.out.println(filename);
}
}
}
练习:列出指定目录下的所有内容。
思路:因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。在列出过程中出现的还是目录的话,可以再次调用本功能。也就是函数自身调用自身,这种表现形式或者编程手法称为递归。
递归要注意:
1.限定条件。
2.要注意递归次数,尽量避免内存溢出。
import java.io.*;
class Demo
{
public static void main(String []args) throws Exception{
File file = new File("C:\\Users\\Administrator\\Desktop\\wizweb");
showFile(file);
}
//递归函数
public static void showFile(File file){
File[] files = file.listFiles();
for(File thisfile : files){
//判断是否是目录,如果是调用自己传入目录
if(thisfile.isDirectory())
showFile(thisfile);
//否则打印文件名
else
System.out.println(thisfile.toString());
}
}
}
练习:使打印具有层级感。
import java.io.*;
class Demo
{
public static void main(String []args) throws Exception{
File file = new File("C:\\Users\\Administrator\\Desktop\\Test");
showFile(file,0);
}
public static void showFile(File file,int count){
System.out.println(showline(count)+file.toString());
count++;
File[] files = file.listFiles();
for(File thisfile : files){
if(thisfile.isDirectory())
showFile(thisfile,count);
else
System.out.println(showline(count)+thisfile.toString());
}
count--;
}
public static String showline(int x){
StringBuilder sb = new StringBuilder();
for(int i=0;i<x;i++){
sb.append("----");
}
return sb.toString();
}
}
练习:删除一个带内容的目录。
删除原理:在windows中,删除目录是从里往外删除的。
import java.io.*;
class Demo
{
public static void main(String []args) throws IOException{
File file = new File("C:\\Users\\Administrator\\Desktop\\Test");
deleteFile(file);
}
public static void deleteFile(File file) throws IOException{
File[] files = file.listFiles();
//遍历数组,如果是目录,则递归,否则直接删除
for(File thisfile : files){
if(thisfile.isDirectory())
deleteFile(thisfile);
System.out.println(thisfile.getName()+":"+thisfile.delete());
}
//将文件夹删除
System.out.println(file.getName()+":"+file.delete());
}
}
练习:将一个指定目录下的Java文件的绝对路径,存储到一个文件中,建立一个Java文件列表文件。
思路:
1.对指定的目录进行递归
2.获取在递归过程中所有的java文件的路径。
3.将这些路径存储到集合中。
4.将集合中的数据写入到文件中。
import java.io.*;
import java.util.*;
class Demo
{
public static void main(String []args) throws IOException{
File file = new File("C:\\Users\\Administrator\\Desktop\\Test");
List<File> list = new ArrayList<File>();
list = file2List(file,list);
write2file(list);
}
public static List<File> file2List(File file,List<File> list) throws IOException{
File[] files = file.listFiles();
for(File thisfile : files){
if(thisfile.isDirectory())
list = file2List(thisfile,list);
else{
if(thisfile.getName().endsWith(".java"))
list.add(thisfile);
}
}
return list;
}
public static void write2file(List<File> list) throws IOException{
BufferedWriter bw = new BufferedWriter(new FileWriter("java.txt"));
for(File file : list){
bw.write(file.getAbsolutePath());
bw.newLine();
bw.flush();
}
bw.close();
}
}
Properties:是Hashtable的子类,也就是说它具备了Map集合的特点,而且它里面存储的键值对都是字符串,是集合中和IO技术相结合的集合容器。
Properties特点:可以用于键值对形式的配置文件。
加载的数据的格式:键 = 值。
load():读取属性列表(键和元素对)。
void load(InputStream inStream)
从输入流中读取属性列表(键和元素对)。
void load(Reader reader)
按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
setProperty():添加。
Object setProperty(String key, String value)
调用 Hashtable 的方法 put。
getProperty()
:获取。
String getProperty(String key)
用指定的键在此属性列表中搜索属性。
String getProperty(String key, String defaultValue)
用指定的键在属性列表中搜索属性。
list():输出。void list(PrintStream out)
将属性列表输出到指定的输出流。
void list(PrintWriter out)
将属性列表输出到指定的输出流。
stringPropertyNames():获取键集。
Set<String> stringPropertyNames()
返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。
练习:设置和获取元素。import java.io.*;
import java.util.*;
class Demo
{
public static void main(String []args){
Properties prop = new Properties();
prop.setProperty("zhangsan", "30");
prop.setProperty("lisi", "39");
System.out.println(prop);
}
}
优化:
import java.io.*;
import java.util.*;
class Demo
{
public static void main(String []args){
Properties prop = new Properties();
prop.setProperty("zhangsan", "30");
prop.setProperty("lisi", "39");
prop.setProperty("lisi", "89");
Set<String> set = prop.stringPropertyNames();
for(String s : set){
System.out.println(s+":"+prop.getProperty(s));
}
}
}
练习:读取配置文件。
思路:想要将info.txt中的键值数据存到集合中进行操作。
1.用一个流和info.txt文件关联。
2.读取一行数据,将该行数据用“=”进行切割。
3.符号左边作为键,右边作为值。存入到Properties集合中即可。
import java.io.*;
import java.util.*;
class Demo
{
public static void main(String []args) throws IOException{
Properties prop = new Properties();
BufferedReader br = new BufferedReader(new FileReader("info.txt"));
String line = null;
while((line = br.readLine())!=null){
String[] str = line.split("=");
prop.put(str[0],str[1]);
}
br.close();
prop.list(System.out);
}
}
利用Properties自身的方法:
import java.io.*;
import java.util.*;
class Demo
{
public static void main(String []args) throws IOException{
Properties prop = new Properties();
//将流中的数据加载进集合
prop.load(new FileInputStream("info.txt"));
//将集合元素输出到控制台
prop.list(System.out);
}
}
store():将此
Properties
表中的属性列表(键和元素对)写入输出流。
void store(OutputStream out, String comments)
以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。
例:
import java.io.*;
import java.util.*;
class Demo
{
public static void main(String []args) throws IOException{
Properties prop = new Properties();
//将流中的数据加载进集合
prop.load(new FileInputStream("info.txt"));
//将集合元素输出到控制台
prop.list(System.out);
prop.setProperty("sunba","40");
//将集合写入到输出流
prop.store(new FileOutputStream("info.txt"),"haha");
}
}
练习:用于记录应用程序运行次数,如果使用次数已到,那么给出注册提示。
思路:很容易想到的是计数器。可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。可是随着该应用程序的退出,该计数器也在内存中消失了。下一次再启动该程序,又重新开始从0计数。这不是我们想要的。程序即使结束,该计数器的值也存在。下次程序启动先加载计数器的值并加1后再重新存储起来。所以要建立一个配置文件。用于记录该软件的使用次数。
该配置文件使用键值对的形式。这样便于阅读数据并操作数据。键值对数据是Map集合。数据是以文件形式存储。使用IO技术。那么Map+IO——>Properties。
配置文件可以实现应用程序数据的共享。
我的方法:
import java.io.*;
import java.util.*;
class Demo
{
public static void main(String []args) throws Exception{
File file = new File("count.txt");
Properties pro = new Properties();
if(!file.exists()){
file.createNewFile();
method(pro,1,"run"+1,file);
}
else{
pro.load(new FileInputStream(file));
int count = Integer.parseInt(pro.getProperty("count"));
if(count>=5)
throw new RuntimeException("您好,使用次数已到,拿钱");
method(pro,count+1,"run"+(count+1),file);
}
}
public static void method(Properties pro,int count,String comments,File file) throws IOException{
pro.setProperty("count",count+"");
pro.store(new FileOutputStream(file),comments);
}
}
视频的方法:
import java.io.*;
import java.util.*;
class Demo
{
public static void main(String []args) throws Exception{
Properties pro = new Properties();
File file = new File("count.ini");
if(!file.exists())
file.createNewFile();
FileInputStream fis = new FileInputStream("count.ini");
pro.load(fis);
int count = 0;
String value = pro.getProperty("time");
if(value!=null)
count = Integer.parseInt(value);
if(count>5)
System.out.println("您好,使用次数已到,拿钱");
count++;
pro.setProperty("time",count+"");
FileOutputStream fos = new FileOutputStream(file);
pro.store(fos," ");
fos.close();
fis.close();
}
}
二、IO包中的其他类
打印流:PrintWriter与PtintStream,可以直接操作输入流和文件。
序列流:SequenceInputStream,对多个流进行合并。
操作对象:ObjectInputStream与ObjectOutputStream,被操作的对象需要实现Serializable(标记接口)。
PtintStream:为其他输出流添加了功能,使他们能够方便的打印各种数据值表示形式。操作的都是字节。
println():可以对基本数据类型直接操作。能保证数据原样性打印出去。
write(int b):写的是低8位。
PrintStream字节打印流构造函数可以接收的参数类型:
1.File对象。
2.字符串路径。
3.字节输出流OutputStream。
PrintWriter字符输出流构造函数可以接收的参数类型:
1.File对象。
2.字符串路径。
3.字节输出流OutputStream。
4.字符输出流Writer。
练习:键盘录入数据操作。
PrintWriter(OutputStream out, boolean autoFlush)
通过现有的 OutputStream 创建新的 PrintWriter。
注:只有println、printf或 format 方法才支持自动刷新。import java.io.*;
class Demo
{
public static void main(String []args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(System.out,true);
String line = null;
while((line = br.readLine())!=null){
if("over".equals(line))
break;
pw.println(line.toUpperCase());
}
br.close();
pw.close();
}
}
SequenceInputStream:序列流,无对应输出流,表示其他输入流的逻辑串联。
解析:图示
练习:将1.txt,2.txt,3.txt的内容整合到4.txt中。
1.txt——>11111111111111111111...
2.txt——>22222222222222222222...
3.txt——>33333333333333333333...
import java.io.*;
import java.util.*;
class Demo
{
public static void main(String []args) throws Exception{
ArrayList<InputStream> al = new ArrayList<InputStream>();
al.add(new FileInputStream("1.txt"));
al.add(new FileInputStream("2.txt"));
al.add(new FileInputStream("3.txt"));
final Iterator<InputStream> it = al.iterator();
Enumeration<InputStream> en = new Enumeration<InputStream>(){
public boolean hasMoreElements(){
return it.hasNext();
}
public InputStream nextElement(){
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(en);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("4.txt"));
int ch = 0;
while((ch = sis.read())!=-1){
bos.write(ch);
}
sis.close();
bos.close();
}
}
练习:切割文件。
import java.io.*;
import java.util.*;
class Demo
{
public static void main(String []args) throws Exception{
splitFile();
}
public static void splitFile() throws IOException{
File file = new File("Test.jpg");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos = null;
int count = 1;
byte[] by = new byte[1024*1024];
int len = 0;
while((len = bis.read(by))!=-1){
bos = new BufferedOutputStream(new FileOutputStream("Test_"+(count++)+".part"));
bos.write(by,0,len);
bos.close();
}
bis.close();
}
}
练习:合并文件。
import java.io.*;
import java.util.*;
class Demo
{
public static void main(String []args) throws Exception{
//splitFile();
merge();
}
public static void splitFile() throws IOException{
File file = new File("Test.jpg");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos = null;
int count = 1;
byte[] by = new byte[1024*1024];
int len = 0;
while((len = bis.read(by))!=-1){
bos = new BufferedOutputStream(new FileOutputStream("Test_"+(count++)+".part"));
bos.write(by,0,len);
bos.close();
}
bis.close();
}
public static void merge() throws IOException{
ArrayList<InputStream> al = new ArrayList<InputStream>();
for(int x=1;x<=3;x++){
al.add(new FileInputStream("Test_"+x+".part"));
}
final Iterator<InputStream> it = al.iterator();
Enumeration<InputStream> en = new Enumeration<InputStream>(){
public boolean hasMoreElements(){
return it.hasNext();
}
public InputStream nextElement(){
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(en);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Test_copy.jpg"));
int len = 0;
byte[] by = new byte[1024*1024];
while((len = sis.read(by))!=-1){
bos.write(by,0,len);
}
sis.close();
bos.close();
}
}