------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
File类
File类用来将文件或者对象封装成对象,方便对文件与文件夹的属性信息进行操作。
file对象可以作为参数传递给流的构造函数。
ps:流只能操作数据,不能操作文件,只有File类能对文件进行操作。
示例:File类创建文件
package com.leaf.iotest;
import java.io.File;
public class FileDemo {
public static void main(String[] args) {
//可以将一个已存在的,或者不存在的文件或者目录封装成file对象
//方式1:
File f1 = new File("E:\\File\\x.txt");
//方式2:
File f2 = new File("E:\\File","y.txt");
//方式3:
File fh = new File("E:\\File");
File f3 = new File(fh,"z.txt");
//能在不同的系统中通用
File f4 = new File("E:"+File.separator+"File"+File.separator+"xyz.txt");
}
}
result:
你发现运行代码,却在对应的文件夹下没有发现文件?这是怎么回事?
分析:原来,File类new一个File不是创建一个文件,而是创建一个文件或者问价夹的路径,只有你使用createNewFile并返回true的时候才是文件创建成功。
下面我们先介绍一下文件File类的常用方法:
1. 获取
a) 获取文件名
b) 获取文件路径
c) 获取文件大小
d) 获取文件的修改时间
示例:
package com.leaf.iotest;
import java.io.File;
import java.text.DateFormat;
import java.util.Date;
public class FileMethodDemo{
public static void main(String[] args) {
File file1 = new File("1.txt");
File file2 = new File("E:\\File\\1.txt");
//获取文件名
String name = file2.getName();
//获取绝对路径
String absPath = file2.getAbsolutePath();
String path1 = file1.getPath();
String path2 = file2.getPath();
long len = file2.length();
long time = file2.lastModified();
//相对路径不同,父目录不同,如果此路径名没有指定的父目录,则返回null
String parent1 = file1.getParent();
String parent2 = file2.getParent();
Date date = new Date(time);
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
String str_time = df.format(date);
System.out.println("name:"+name);
System.out.println("absPath:"+absPath);
System.out.println("path1:"+path1);
System.out.println("path2:"+path2);
System.out.println("len:"+len);
System.out.println("str_time:"+str_time);
System.out.println("parent1:"+parent1);
System.out.println("parent2:"+parent2);
}
}
result:
文件的创建和删除:
示例:
package com.leaf.iotest;
import java.io.File;
import java.io.IOException;
public class FileCreAndDelDemo {
public static void main(String[] args) throws IOException {
File file = new File("file.txt");
// 和输出流不一样,如果文件不存在,则创建,如果文件存在,则不创建
boolean b1 = file.createNewFile();
System.out.println("b1 = " + b1);
// 使用delete方法删除文件夹的时候,如果文件夹中有文件,则会删除失败
boolean b2 = file.delete();
System.out.println("b2 = " + b2);
File dir = new File("abc\\ab");
// 使用mkdir可以创建多级目录
boolean b3 = dir.mkdir();// make directory
System.out.println("b3 = " + b3);
// 最里层目录被干掉,dir代表的是最里层的目录
boolean b4 = dir.delete();
}
}
result:
判断:
package com.leaf.iotest;
import java.io.File;
import java.io.IOException;
public class FileMethodDemo2 {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
File f = new File("a.txt");
//文件是否存在
boolean b = f.exists();
System.out.println("b:"+b);
if(!f.exists()){
f.createNewFile();
}
if(f.exists()){
//是文件?
System.out.println(f.isFile());
//是目录?
System.out.println(f.isDirectory());
f = new File("aa\\bb");
f.mkdir();
if(f.exists()){
System.out.println(f.isFile());
System.out.println(f.isDirectory());
}
}
}
}
result:
系统的根目录和容量获取
package com.leaf.iotest;
import java.io.File;
public class FileMethodDemo3 {
public static void main(String[] args) {
File[] files = File.listRoots();
for(File file:files){
System.out.println(file);
}
File file = new File("E:\\");
System.out.println("getFreeSpace:"+file.getFreeSpace());
System.out.println("getTotalSpace:"+file.getTotalSpace());
System.out.println("getUsableSpace:"+file.getUsableSpace());
}
}
result:
获取目录下的文件已经文件夹的名称
package com.leaf.iotest;
import java.io.File;
public class FileListDemo {
public static void main(String[] args) {
File file = new File("C:\\");
//获取目录下的文件已经文件夹名称(包括隐藏文件)
//调用List方法的File对象中封装的必须是目录,否则会发生NullPointerException
//如果访问的是系统级目录也会发生空指针异常
//如果目录存在但是没有内容,会返回一个长度为0的数组。
String[] names = file.list();
for(String name :names){
System.out.println(name);
}
}
}
result:
获取D盘下JavaClass文件下的”.java“文件
package com.leaf.iotest;
import java.io.File;
import java.io.FilenameFilter;
public class FileMethodDemo4 {
public static void main(String[] args) {
File dir = new File("D:\\JavaClass");
String[] names = dir.list(new FilterByJava());
for(String name :names){
System.out.println(name);
}
}
}
class FilterByJava implements FilenameFilter{
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".java");
}
}
result:
打印出c盘下的隐藏文件
package com.leaf.iotest;
import java.io.File;
import java.io.FilenameFilter;
public class FileListDemo1 {
public static void main(String[] args) {
File dir = new File("C:\\");
File[] files = dir.listFiles(new FilterByHidden());
for(File file:files){
System.out.println(file);
}
}
}
class FilterByHidden implements FilenameFilter{
@Override
public boolean accept(File dir, String name) {
return dir.isHidden();
}
}
result:
递归算法:
函数自身直接或者间接的调用到了自身,一个功能在被重复使用,并且每次使用时,参与运算的结果和上一次调用有关,这是可以使用递归来解决问题
ps
1. 递归一定要明确条件,否则容易栈溢出
2. 注意递归的次数
需求:对指定目录进行所有内容(包含子目录的内容),可以理解为深度遍历。
package com.leaf.iotest;
import java.io.File;
public class FileListDemo3 {
/**使用递归对文件目录及子目录的所有文件进行打印
* @param args
*/
public static void main(String[] args) {
File fileDir = new File("E:\\File");
listAll(fileDir,0);
}
public static void listAll(File dir , int level){
System.out.println(getSpace(level)+"dir:"+dir.getAbsolutePath());
level++;
File[] files = dir.listFiles();
for(int x = 0;x<files.length;x++){
if(files[x].isDirectory()){
listAll(files[x],level);
}
System.out.println(getSpace(level)+"files:"+files[x].getAbsolutePath());
}
}
private static String getSpace(int level) {
StringBuilder sb = new StringBuilder();
sb.append("|--");
for(int x = 0;x>level;x++){
sb.append("| ");
}
return sb.toString();
}
}
result:
递归的作用很多,简单示例:
package com.leaf.iotest;
public class DiGuiDemo {
/**利用递归求一个数的二进制
* @param args
*/
public static void main(String[] args) {
toBin(7);
}
public static void toBin(int num){
if(num >0){
toBin(num/2);
System.out.println(num%2);
}
}
}
result:
IO中其他流对象:
打印流:
printWriterhe PrintStream:可以直接操作输入流和文件。
PrintStream为其他输出流添加了功能,使他们能方便的打印出各种数据值表示形式
与其他输出流不同,PrintStream永远不会泡茶IOException
PrintStream打印的所有字符都使用平台默认的字符编码转换为字节
在需要写入字符而不是写入字节的情况下,应该使用PrintWriter
PrintStream:
1. 提供了打印方法可以对多种数据类型值进行打印,并保持数据的表示形式
2. 它不抛IOException
构造函数,接收三种类型的值:
1. 字符串路径
2. File对象
3. 字节输出流
示例:
package com.leaf.iotest;
import java.io.PrintStream;
public class PrintStreamDemo {
public static void main(String[] args) throws Exception {
PrintStream out = new PrintStream("E:\\File\\print.txt");
// write(int b)方法只写最低8位
out.write(97); // a
// print方法将97先变成字符串保持原样将数据打印到目的地
out.print(97); // 97
out.close();
}
}
result:
PrintWriter:字符打印流
构造函数参数:
1. 字符串路径
2. File对象
3. 字节输出流
4. 字符输出流
示例:
package com.leaf.iotest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class PrintWriterDemo {
public static void main(String[] args) throws IOException {
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();
}
}
}
result:
序列流:
SequenceInputStream:多个流进行合并。
需求,将1.tx、2.txt、3.txt文件中的数据合并到一个文件4.txt中。
package com.leaf.iotest;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;
public class SequenceInputStreamDemo {
public static void main(String[] args) throws Exception {
Vector<FileInputStream> v = new Vector<FileInputStream>();
String path = "E:\\File\\";
v.add(new FileInputStream(path+"1.txt"));
v.add(new FileInputStream(path+"2.txt"));
v.add(new FileInputStream(path+"3.txt"));
Enumeration<FileInputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream(path+"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();
}
}
result:
运行前:
“1.txt”
“2.txt”
“3.txt”
运行后:
上述代码中,我们可以使用ArrayList来代替Vector。有兴趣的朋友可以试验一下。
需求:设计一个文件切割器,将文件安固定大小切割成n个部分
package com.leaf.iotest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class SplitFileDemo {
private static final int SIZE = 1024 * 1024;
public static void main(String[] args) throws IOException {
File file = new File("E:\\File\\1.mp3");
splitFile(file);
}
public static void splitFile(File file) throws IOException {
// 用读取流关联源文件
FileInputStream fis = new FileInputStream(file);
// 定义一个1M的缓冲区
byte[] buf = new byte[SIZE];
// 创建目的
FileOutputStream fos = null;
int len = 0;
int count = 1;
// 切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数,以方便于合并。
// 这个信息为了进行描述,使用键值对的方式,用到了properties对象。
Properties prop = new Properties();
File dir = new File("E:\\File\\partFiles");
if (!dir.exists())
dir.mkdirs();
while ((len = fis.read(buf)) != -1) {
fos = new FileOutputStream(new File(dir, (count++) + ".part"));
fos.write(buf, 0, len);
fos.close();
}
// 将被切割文件的信息保存到prop集合中
prop.setProperty("partcount", count + "");
prop.setProperty("filename", file.getName());
fos = new FileOutputStream(new File(dir, count + ".properties"));
// 将prop集合中的数据存储到文件中
prop.store(fos, "save file info");
fis.close();
fos.close();
}
}
result:
运行前:
运行后:
合并刚刚切割的文件
示例:
package com.leaf.iotest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Properties;
public class MergeFile {
public static void main(String[] args) throws IOException {
File dir = new File("E:\\File\\partFiles");
mergeFile(dir);
}
public static void mergeFile(File dir) throws IOException {
// 获取指定目录下的配置文件对象
File[] files = dir.listFiles(new SuffixFilter(".properties"));
if (files.length != 1)
throw new RuntimeException(dir + ",该目录下没有properties扩展名的文件或者不唯一");
// 记录配置文件对象
File confile = files[0];
// 获取该文件中的信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream(confile);
prop.load(fis);
String filename = prop.getProperty("filename");
int count = Integer.parseInt(prop.getProperty("partcount"));
// 获取该目录下的所有碎片文件
File[] partFiles = dir.listFiles(new SuffixFilter(".part"));
if (partFiles.length != (count - 1)) {
throw new RuntimeException("碎片文件不符合要求,个数不对!应该是" + count + "个");
}
// 将碎片文件和流对象关联并存储到集合中
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for (int x = 1; x <= partFiles.length; x++) {
al.add(new FileInputStream(partFiles[x - 1]));
}
final Iterator<FileInputStream> it = al.iterator();
// 将多个流合并成一个序列流
Enumeration<FileInputStream> en = Collections.enumeration(al);
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream(new File(dir, filename));
byte[] buf = new byte[1024 * 1024];
int len = 0;
while ((len = sis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
sis.close();
}
}
class SuffixFilter implements FilenameFilter {
private String suffix;
public SuffixFilter(String suffix) {
super();
this.suffix = suffix;
}
public boolean accept(File dir, String name) {
return name.endsWith(suffix);
}
}
result:
操作对象:
ObjectInputStream与ObjectOutputStream
ps:
被操作的对象需要实现Serialzable,类通过实现java.io.Serializable接口以启动序列号功能,Serializable只是一个标记接口。
这里不做演示了。
RandomAccessFile:这是一个非常特殊的类
演示:
package com.leaf.iotest;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException {
writeFile();
}
// 使用RandomAccessFile对象写入一些人员信息,比如姓名和年龄
public static void writeFile() throws IOException {
// 如果文件不存在,则创建,如果文件存在,不创建
RandomAccessFile raf = new RandomAccessFile("E:\\File\\ranacc.txt", "rw");
raf.write("张三".getBytes());
// 使用write方法之写入最后一个字节
raf.write(97);
// 使用writeInt方法写入四个字节(int类型)
raf.writeInt(97);
raf.write("小强".getBytes());
raf.writeInt(99);
raf.close();
}
}
result:
示例:
package com.leaf.iotest;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo2 {
public static void main(String[] args) throws IOException {
readFile();
}
public static void readFile() throws IOException {
RandomAccessFile raf = new RandomAccessFile("E:\\File\\ranacc.txt", "r");
// 通过seek设置指针的位置
raf.seek(9); // 随机的读取,只要指定指针的位置即可
byte[] buf = new byte[4];
raf.read(buf);
String name = new String(buf);
System.out.println("name=" + name);
int age = raf.readInt();
System.out.println("age=" + age);
System.out.println("pos:" + raf.getFilePointer());
raf.close();
}
}
result:
注:因为我把eclipse的默认编码改成了UTF-8,所以会有上述的乱码问题。
管道流:
PipedInputStream和PipedOutputStream:输入输出可以直接进行连接,通过集合线程使用。
示例:
package com.leaf.iotest;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
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();
}
}
result:
操作基本数据类型:
DataInputStream与DataOutputStream
示例:
package com.leaf.iotest;
/*
DataInputStream与DataOutputStream
可以用于操作基本数据类型的数据的流对象。
*/
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("E:\\File\\utfdate.txt"));
String s = dis.readUTF();
System.out.println(s);
dis.close();
}
public static void writeUTFDemo()throws IOException
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("E:\\File\\utfdate.txt"));
dos.writeUTF("你好");
dos.close();
}
public static void readData()throws IOException
{
DataInputStream dis = new DataInputStream(new FileInputStream("E:\\File\\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("E:\\File\\data.txt"));
dos.writeInt(234);
dos.writeBoolean(true);
dos.writeDouble(9887.543);
dos.close();
}
}
result:
操作字节数组:
ByteArrayInputStream 与 ByteArrayOutputStream
示例:
package com.leaf.iotest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class ByteArrayDemo {
public static void main(String[] args) throws IOException {
ByteArrayInputStream bis = new ByteArrayInputStream("abcdef".getBytes());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int ch = 0;
while ((ch = bis.read()) != -1) {
bos.write(ch);
}
System.out.println(bos.toString());
}
}
result: