Java IO(三)

时间:2023-03-08 21:51:05

File

File类的常见方法:

  1、创建。

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

    boolean mkdir():创建文件夹。

    boolean mkdirs():创建多级文件夹。

  2、删除。

    boolean delete():删除失败返回false。

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

  3、判断。

    boolean exists():文件是否存在。

    isDirectory()

    isFile()

    isHidden():是否是一个隐藏文件。

    isAbsolute():文件不存在也可以判断。

  4、获取信息。

    getName():获取文件或目录的名称。

    getPath():返回的就是File类构造函数里面的字符串,不管什么绝对或相对路径,你给我什么,我就返回什么。

    getParent():该方法返回的是绝对路径中的父目录,如果获取的是相对路径,返回null。如果相对路径中有上一层目录,那么该目录就是返回结果。

    getAbsolutePath():该方法法返回的是绝对路径。

    long lastModified()

    long length()

示例代码如下:

import java.io.File;
import java.io.IOException; public class FileDemo0 { public static void main(String[] args) throws IOException {
//consMethod();
//method_1();
//method_2();
//method_3();
//method_4();
method_5();
} public static void method_5() {
File f1 = new File("d:\\java\\LoginDemo.java");
File f2 = new File("d:\\java\\aaa.java"); sop("rename:" + f2.renameTo(f1));
} public static void method_4() {
File f = new File("abc\\file.txt"); sop("path:" + f.getPath());//返回的就是File类构造函数里面的字符串,里面是什么就返回什么
sop("abspath:" + f.getAbsolutePath());
sop("parent:" + f.getParent());//该方法返回的是绝对路径中的父目录,如果获取的是相对路径,返回null
//如果相对路径中有上一层目录,那么该目录就是返回结果。
} public static void method_3() throws IOException {
File f = new File("E:\\MyJava\\workspace\\IO_Project\\file2.txt"); //f.createNewFile();
//f.mkdir(); /*
* 记住在判断文件对象是否是文件或者目录时,必须要先判断该文件对象封装的内容是否存在,
* 通过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\\asd\\qewq\\as\\er"); sop("mkdir : " + dir.mkdirs()); } public static void method_1() throws IOException {
File f = new File("file.txt");
f.deleteOnExit();
//code();
//sop("create : " + f.createNewFile());
sop("delete :" + f.delete());
} /*
* 创建File对象
*/
public static void consMethod() {
/*
* 将a.txt封装成file对象,可以将已有和未出现的文件或文件夹封装成对象
*/
File f1 = new File("a.txt"); File f2 = new File("d:\\java\\io123", "b.txt"); File d = new File("d:\\java\\io123");
File f3 = new File(d, "c.txt"); sop("f1 : " + f1);
sop("f2 : " + f2);
sop("f3 : " + f3); File f4 = new File("d:" + File.separator + "java" + File.separator + "io123" + File.separator + "d.txt");
} public static void sop(Object obj) {
System.out.println(obj);
} }

  5、列出可用的文件系统根,也就是本机上的盘符。

    listRoots()

  6、字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。如果目录为空,那么数组也将为空如果此抽象路径名不表示一个目录,或者发生 I/O 错误,则返回null

    list()

  7、返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。

    listFiles()

代码如下:

import java.io.File;
import java.io.FilenameFilter; public class FileDemo1 { public static void main(String[] args) {
//listRootsDemo();
//listDemo(); File dir = new File("c:\\");
File[] files = dir.listFiles();
for(File f : files) {
System.out.println(f.getName() + "::" + f.length());
} } /*
* 专门找指定目录下指定后缀名(例如:.java/.jpg/.mp3/.log)的文件
*/
public static void listDemo_2() {
File dir = new File("d:\\java\\io"); String[] arr = dir.list(new FilenameFilter() { @Override
public boolean accept(File dir, String name) {
//System.out.println("dir:" + dir + "...name:" + name);
/*
if(name.endsWith(".log"))
return true;
else
return false;
*/
return name.endsWith(".log");
}
}); System.out.println("len:" + arr.length);
for(String name : arr) {
System.out.println(name);
}
} 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.length());
}
} }

递归

例,列出指定目录下文件或者文件夹,包含子目录中的内容。也就是列出指定目录下的所有内容。

分析:

因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。在列出过程中出现的还是目录的话,还可以再次调用本功能。也就是函数自身调用自身。这种表现形式或者编程手法,称为递归。

递归要注意:

  1. 限定条件。
  2. 要注意递归的次数,尽量避免内存溢出。

代码如下:

import java.io.File;

public class FileDemo2 {

    public static void main(String[] args) {
File dir = new File("d:\\java");
showDir(dir, 0);
}
/*
* 分层级列出指定目录下的所有内容
*/
public static String getLevel(int level) {
StringBuilder sb = new StringBuilder();
sb.append("|--");
for(int x = 0; x < level; x++) {
//sb.append("|--");
sb.insert(0, "| ");
}
return sb.toString();
}
public static void showDir(File dir, int level) { System.out.println(getLevel(level) + dir.getName());
level++;
File[] files = dir.listFiles();
for(int x = 0; x < files.length; x++) {
if(files[x].isDirectory()) {
showDir(files[x], level);
} else {
System.out.println(getLevel(level) + files[x]);
} }
}
}

举例说之,十进制数转二进制数。代码如下:

public class FileDemo0 {

    public static void main(String[] args) {
toBin(6);
} public static void toBin(int num) {
if(num > 0) {
toBin(num / 2);
System.out.print(num % 2);
}
} }

图解:

Java IO(三)

再举例说之:求和。代码如下:

public class FileDemo0 {

    public static void main(String[] args) {
int sum = getSum(100);
System.out.println("sum = " + sum);
} public static int getSum(int n) {
if(n == 1)
return 1;
return n + getSum(n - 1);
} }

图解:

Java IO(三)

删除一个带内容的目录。

删除原理:在windows中,删除目录从里面往外删除的。既然是从里往外删除,就需要用到递归。

代码如下:

import java.io.File;

public class RemoveDir {

    public static void main(String[] args) {
File f = new File("d:\\java");
removeDir(f);
} public static void removeDir(File dir) {
File[] files = dir.listFiles(); for(int x = 0; x < files.length; x++) {
if(files[x].isDirectory()) {
removeDir(files[x]);
} else {
System.out.println(files[x].toString() + ":-file-:" + files[x].delete());
}
} System.out.println(dir + "::dir::"+ dir.delete());
} }

Properties

Properties是HashTable的子类,也就是说它具备map集合的特点,而且他里面存储的键值对都是字符串。是集合和IO技术相结合的集合容器。该对象的特点:可以用于键值对形式的配置文件。那么在加载数据时,需要数据有固定格式,通常是键=值。

示例代码:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Set; public class PropertiesDemo0 { public static void main(String[] args) throws IOException {
//setAndGet();
//method_1();
loadDemo();
} public static void loadDemo() throws IOException {
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("D:\\java\\io123\\info.txt");
//将流中的数据加载进集合
prop.load(fis); prop.setProperty("wangwu", "21"); FileOutputStream fos = new FileOutputStream("D:\\java\\io123\\info.txt"); prop.store(fos, "haha");
//System.out.println(prop);
prop.list(System.out);//将属性列表输出到指定的输出流。功能与System.out.println(prop);语句相似 fos.close();
fis.close();
} /*
* 演示,如何将流中的数据存储到集合中。(也即是Properties类中load(InputStream in)方法的原理)
* 想要将info.txt中的键值对数据存到集合中进行操作
*
* 1、用一个流和info.txt文件关联
* 2、读取一行数据,将该行数据用“=”进行切割
* 3、等号左边作为键,右边作为值。存入到Properties集合中即可。
*/
public static void method_1() throws IOException {
BufferedReader bufr = new BufferedReader(new FileReader("D:\\java\\io123\\info.txt"));
String line = null;
Properties prop = new Properties();
while((line = bufr.readLine()) != null) {
String[] arr = line.split("=");
prop.setProperty(arr[0], arr[1]);
//System.out.println(arr[0]+"...."+arr[1]);
}
bufr.close();
System.out.println(prop);
} /*
* 设置和获取元素
*/
public static void setAndGet() {
Properties pro = new Properties();
pro.setProperty("zhangsan", "30");
pro.setProperty("lisi", "39");
//System.out.println(pro);
String value = pro.getProperty("lisi");
//System.out.println(value); pro.setProperty("lisi", 89+""); Set<String> names = pro.stringPropertyNames();
for(String s : names) {
System.out.println(s+":"+pro.getProperty(s));
}
}
}

打印流

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

1、字节打印流(PrintStream)

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

  1. file对象。File
  2. 字符串路径。String
  3. 字节输出流。OutputStream

2、字符打印流(PrintWriter)

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

  1. file对象。File
  2. 字符串路径。String
  3. 字节输出流。OutputStream
  4. 字符输出流。Writer

示例代码:

import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter; public 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);//不需要写刷新代码out.flush();自动刷新。 String line = null; while((line = bufr.readLine()) != null) {
if("over".equals(line))
break;
out.println(line.toUpperCase());
//out.flush();
}
out.close();
bufr.close();
}
}

练习1:将一个指定目录下的java文件的绝对路径,存到一个文本文件中,建立一个java文件列表清单。

思路:

  1. 对指定的目录进行递归。
  2. 获取递归过程中所有的java文件的路径。
  3. 将这些路径存储到集合中。
  4. 将集合的数据写入到一个文件中。

代码:

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List; public class JavaFileList { public static void main(String[] args) throws IOException {
File dir = new File("d:\\java");
List<File> list = new ArrayList<File>();
fileToList(dir, list);
File file = new File(dir, "javalist.txt");
writeToFile(list, file.toString()); //System.out.println(list.size());
} public static void fileToList(File dir, List<File> list) {
File[] files = dir.listFiles();
for(File file : files) {
if(file.isDirectory())
fileToList(file, list);
else {
if(file.getName().endsWith(".java"))
list.add(file);
}
}
} public static void writeToFile(List<File> 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 e;
} finally {
try {
if(bufw != null)
bufw.close();
} catch (IOException e) {
throw e;
}
} } }

练习2:用于记录应用程序运行次数,如果使用次数已到,那么给出注册提示。

分析:

很容易想到的是:计数器。可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增,可是随着该应用程序的退出,该计数器也在内存中消失了。下一次在启动该程序,又重新开始从0计数。这样不是我们想要的。

程序即使结束,该计数器的值也存在。下次程序启动会先加载该计数器的值,并+1后重新存储起来。所以要建立一个配置文件,用于记录该软件的使用次数。该配置文件使用键值对的形式,这样便于阅读数据,并操作数据。键值对数据是map集合。数据是以文件形式存储,使用io技术。那么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 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) {
System.out.println("您好,使用次数已到,拿钱!");
return;
}
}
count++;
prop.setProperty("time", count+""); FileOutputStream fos = new FileOutputStream(file);
prop.store(fos, ""); fos.close();
fis.close(); }
}

当然配置文件还有另外一种格式保存,那就是XML,格式如下:

<persons>
<person id="001">
<name>zhangsan</name>
<age>30</age>
<address>bj</address>
</person>
<person id="002">
<name>zhangsan1</name>
<age>31</age>
<address>bj</address>
</person>
</persons>

一个用来解析XML格式的文件的工具:dom4j,即dom for(four的谐音) java   

合并流

SequenceInputStream表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

它有两个构造函数:

  1. SequenceInputStream(Enumeration<? extends InputStream> e),通过记住参数来初始化新创建的SequenceInputStream,该参数必须是生成运行时类型为InputStream对象的Enumeration型参数。
  2. SequenceInputStream(InputStream s1, InputStream s2),通过记住这两个参数来初始化新创建的SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取s2),以提供从此SequenceInputStream读取的字节。

示例代码:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector; public class SequenceDemo { public static void main(String[] args) throws IOException {
/*
* 将3个文件中的数据合并到1个文件中
*/
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("D:\\java\\io123\\1.txt"));
v.add(new FileInputStream("D:\\java\\io123\\2.txt"));
v.add(new FileInputStream("D:\\java\\io123\\3.txt"));
Enumeration<FileInputStream> en = v.elements(); SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("D:\\java\\io123\\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.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator; public class SplitFile { public static void main(String[] args) throws IOException {
//splitFile();
merge();
} /*
* 合并图片
*/
public static void merge() throws IOException {
//使用Vector的效率很低下,所以使用List集合
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>(); for(int x = 1; x < 6; x++) {
al.add(new FileInputStream("D:\\java\\io123\\split\\"+x+".part"));
}
/*
* 匿名内部类访问局部变量,所以要用final修饰
*/
final Iterator<FileInputStream> it = al.iterator();
/*
* 枚举,匿名内部类
* 虽然见过Enumeration,但是从来没这么写过,这是用ArrayList来实现一个Enumeration。
* 即使用Enumeration来访问ArrayList。
*/
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() { @Override
public boolean hasMoreElements() {
return it.hasNext();
} @Override
public FileInputStream nextElement() {
return
it.next();
} };
SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("D:\\java\\io123\\ye.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:\\java\\io123\\DSC_0206.JPG"); FileOutputStream fos = null;
byte[] buf = new byte[1024 * 1024];//1MB大小的字节数组 int len = 0;
int count = 1;
while((len = fis.read(buf)) != -1) {
fos = new FileOutputStream("D:\\java\\io123\\split\\"+(count++)+".part");
fos.write(buf, 0, len);
fos.close();
}
fis.close();
} }