Java中File文件的基本操作

File文件的基本操作

一、File类简介

File类不但代表文件和目录的双重含义,还表示一个刚新建于内存中尚未同步去硬盘的文件或目录。File类的作用描述了文件本身的属性,包括用来获取或处理与磁盘文件相关的信息,例如大小、权限、生成时间、最后修改时间和目录路径等等。此外,浏览子目录层次结构也是经常做的操作。尽管File类的实例对象并不打开文件,也不提供任何文件内容的处理功能。但是其他java.io包中的类通常都需要使用File对象来指定要操作的文件或目录。

二、注意问题

由于File需要和操作系统的文件打交道,而Window和Linux的文件系统差异性比较大,所以我们首先要先讲解一下两个注意问题:

1、分割符

Unix/Linux在路径名中分隔符是下斜杠“/”(位于键盘的下端),比如:

/usr/java/jdk7/bin/java.bin

在Windows系统中沿用Dos系统使用的路径分隔符上斜杠“\”(位于键盘的上端)。不过Java编程时很快就会发现这样定义字符串路径是行不通的:

String path=”C:\java\jdk\bin\java.exe”; //报错

上斜杠“\”在java中是转移字符的开始标记,因此你需要进行必要的转义操作:

String path=”C:\\java\\jdk\\bin\\java.exe”; //正确

对于上面问题还有很多解决方法,可以统一使用Java约定是用UNIX和URL风格的斜线来作路径分隔符,这样的写法经过测试,在window下面也是可以正常运行的:

String path=”C:/java/jdk/bin/java.exe”; //正确

File类还提供了一个属性File.separator代替分隔符,这个也可以解决问题。

2、相对路径和绝对路径

  1. 绝对路径:是window系统中指的是从盘符开始的路径,linux系统中指的是以"/"开头——代表根目录的路。

    像一下这些路径就是绝对路径

    C:\java\jdk\bin\java.exe

    /usr/hello.java

  2. 相对路径,顾名思义,相对路径就是相对于当前文件的路径。相对路径的真实路径要根据当前所在目录决定的,如:当前所在的路径是c:/java,那么路径hello/abc.txt路径就表示在c:/java/hello/abc.txt。相比绝对路径而言,相对路径灵活而且效率更高。相对路径还有两个特殊符号:

"./":代表目前所在的目录。

"../":代表上一层目录。

三、代码示例

1、构造方法。只需要写上路径,既可以指向文件也可以指向目录。代码如下:

      //目录
    File path=new File("g:\\java\\abc\\cba\\dfd");
   //文件
    File file=new File("g:\\java//hello.java");

你可以去相应的目录下,查看是否建立成功。

2、建立目录和文件。建立目录和创建文件使用方法是不同的,其中建立目录方法有两个:mkdirs和mkdir。mkdir要求父级目录必须存在,否则会建立失败,而mkdirs会建立所有的目录。不管是建立文件还是目录最好都先判断是否有其权限,还得判断原文件是否存在,否则会覆盖原文件。代码如下:

//新建目录和新建文件方法
   //System.out.println(path.exists());
   if(!path.exists()){
       //mk make dir
     if(path.mkdirs()){
       System.out.println("建立成功");
     }else{
       System.out.println("建立失败");
     }
   }
        
   //新建文件
   if(!file.exists()){
    try {
        file.createNewFile();
    } catch (IOException e) {
        e.printStackTrace();
    }
   }

3、其他操作。我们可以通过File类读取文件的基本属性,还可以删除文件,重命名文件等操作。具体大家可以运行下面代码:

System.out.println("是否可读:"+file.canRead());
System.out.println("是否可写:"+file.canWrite());
System.out.println("是否可执行:"+file.canExecute());
		
System.out.println("是否是目录:"+path.isDirectory());
System.out.println("是否是文件:"+path.isFile());
		
System.out.println("是否隐藏:"+file.isHidden());
		
/System.out.println("删除文件:"+file.delete());
		
System.out.println("删除目录:"+path.delete());
		
System.out.println("获得文件的完整路径:"+file.getAbsolutePath());
		
file.renameTo(new File("d://abc.txt"));
		
//浏览目录
File javaFile=new File("g://java");
		
File files[]= javaFile.listFiles();
System.out.println("文件名称\t修改时间\t类型\t大小");
for(int i=0;i<files.length;i++){
	File f=files[i];
			
	Date date=new Date(f.lastModified());
	SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
			
	String ftype=f.isDirectory()?"目录":"文件";
			
	System.out.println(f.getName()+"\t"+sdf.format(date)+
		"\t"+ftype+"\t"+f.length());
			
}

四、实例

把目录hello下所有文件后缀名是txt的文件全部删除。 提示可以使用递归,实现代码如下:

public class Exe6 {

	public static void main(String[] args) {
		Exe6 exe6 = new Exe6();
		exe6.deleteFile("e://hello");
	}

	public void deleteFile(String path) {
		File file = new File(path);

		File[] files = file.listFiles();
		for (int i = 0; i < files.length; i++) {
			File temp = files[i];
			//如果是文件才判定是否要删除
			if (temp.isFile()) {
				// 文件后缀名是txt
				if (temp.getName().endsWith("txt")) {
					System.out.println(temp.getName() + "删了");
					temp.delete();
				}
			}else{
				//目录 ,再进入目录删除,
				//获得目录的路径
				String son=path+"//"+temp.getName();
				//递归调用
				deleteFile(son);
			}

		}

	}

}

 

字节流

一、理解流的概念

流是对计算机系统中的输入输出进行的抽象。流是指一连串流动的字符,是以先进先出方式发送信息的通道,。在java中流的实现建立在四个抽象类的基础上:InputStream、OutputStream、Reader和Writer。其中InputStream/OutputStream 设计成输入/输出字节流类,而Reader/Writer设计为输入/输出字符流设计。字节流类和字符流类形成分离的层次结构。一般说来,处理字符或字符串时应使用字符流类,处理字节或二进制文件对象时应用字节流类。

InputStream、OutputStream、Reader和Writer这些都是抽象类,任何输入输出都是都可以抽象成为这几个流,流的来源可以是网络,硬盘等等,所以这些抽象类有很多不同的实现类。这里我们主要学习的是以硬盘作为流的来源和目的。输入和输出是以内存作为参照的,也就是凡是流入内存的就是输入,从内存流出的就是输出,记住这点,就不会混乱了。

二、文件字节流实现类

字节流是从InputStream和OutputStream派生出来的一系列类,这一系列流以字节(byte)为基本的处理单位,在命名特点上类名是通常以Stream结尾,如标准的FileInputStream、FileOutputStream、带缓存的BufferedOutputStream、BufferedInputStream等。

我们先看看输入流InputStream,它是一个抽象类,定义了Java流在处理字节输入数据的行为,因此所有的字节输入流都扩展于它。该类下的所有方法都有可能抛出IOException异常。常用的一些方法介绍如下:

int available()

返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。

void close()

关闭此输入流并释放与该流关联的所有系统资源。

void mark(int readlimit)

在此输入流中标记当前的位置。

boolean markSupported()

测试此输入流是否支持 mark 和 reset 方法。

abstract int read()

从输入流中读取数据的下一个字节。

int read(byte[] b)

从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。

int read(byte[] b, int off, int len)

将输入流中最多 len 个数据字节读入 byte 数组。

void reset()

将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。

long skip(long n)

跳过和丢弃此输入流中数据的 n 个字节。

从这些方法上大致可以看出字节输入流的常规处理方法。

1、文件输入流FileInputStream。就是把硬盘中的文件内容读取到内存中,我们先在E:盘中新建一个abc.txt文件,并在文件中输入几个英文字符,然后我们再打印在控制台上,示例代码如下:

public void input() {
		// File file=new File("e://abc.txt");
		InputStream input = null;// 定义
		try {
			input = new FileInputStream("e://abc.txt");
			// 用于保存每次读取出来的数据(一个字节8位)
			int temp = 0;
			temp = input.read();//
			// 当文件读取到最后一个适合会返回-1;
			while (temp != -1) {
				// 输出出来
				System.out.print((char) temp);
				temp = input.read();// 继续读取
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				input.close();// 关闭文件,以释放资源
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

在main方法中调用这个方法,查看控制台是否能读入文件的内容并打印,这里要注意的是,文件流操作完毕后必须要关闭流,否则只要程序没有结束,这个文件会一直占用。

2、文件输出流FileOuputStream。就是把内存中的信息输出到硬盘指定的文件中。示例代码如下:

// 写入文件
	public void output() {
		try {
			// 释放追加信息
			OutputStream output = new FileOutputStream("e://abc.txt", true);
			/*output.write('I');//一个英文=一个字节
			output.write(' ');
			output.write('L');
			output.write('o');
			output.write('v');
			output.write('e');
			output.write(' ');
			output.write('Y');
			output.write('o');
			output.write('u');*/
			
			output.write('我');//一个汉字=2个字节
			output.write('爱');
			output.write('中');
			output.write('国');

			// 关闭文件
			// 清空内存缓存
			output.flush();
			output.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

由上面的代码可见每次只能输出一个字节。我们尝试先输出普通的英文字符,打开abc.txt文件,查看是否已经把内容正确的输出到文件中。然后再尝试输出中文字符,结果发现中文发生了乱码,因为一个中文是使用两个字节保存的,可见字节流对字符的处理并不强大。

三、实例。

下面我们自己写一个实现文件复制功能的方法copy(String srcpath,String tarpath),然后我们尝试一下复制一张图片,看看能否复制成功。

public class StuFileStream {

	public static void main(String[] args) throws Exception {
		
		StuFileStream stream = new StuFileStream();
		stream.copy("e://P1080092.jpg", "d://aa.jpg");
	}

	// 复制
	public void copy(String srcpath, String tarpath) {
		//
		InputStream input = null;// 定义
		OutputStream output = null;
		try {
			input = new FileInputStream(srcpath);
			output = new FileOutputStream(tarpath);
			// 用于保存每次读取出来的数据(一个字节8位)
			int temp = 0;
			temp = input.read();//
			// 当文件读取到最后一个适合会返回-1;
			while (temp != -1) {

				// 写到目标文件里
				output.write(temp);
				temp = input.read();// 继续读取
			}
		} catch (Exception e) {
			// TODO: handle exception
		}finally{
			//关闭资源
			try {
				input.close();
				output.flush();
				output.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}

	}

}

你可以自己拿一张jpg图片尝试复制,最终你可以在d:盘中见到这个图,并打开文件查看能否成功?最终应该可以复制成功。

 

字符流

一、字符流

有了上一节学习字节流的经验,那么字符流就比较简单了。文件在计算机中的作用是存储信息,要读写这些信息需要使用流的相关类型。大量的文字信息都是以字符的方式存在的,Java中的字符是Unicode编码,每个字符是双字节的。字符流从Reader和Writer派生出的一系列类,这类流以16位的Unicode码表示的字符为基本处理单位,处理效率相对字节流Stream极大提高,但局限与只能处理文本类文件。字符流层次结构的顶层是Reader和Writer抽象类,实现类都是以使用Reader或Writer结尾,如FileReader、FileWriter、BufferedReader、BufferedWriter等。

1、FileReader和FileWriter

我们也实现从硬盘读入文件和把内存信息输出到硬盘的文件中。代码如下:

//通过字符流FileReader读取文件
	public  void input(){
		try {
			FileReader reader=new FileReader("e://abc.txt");
			int temp;
			while((temp=reader.read())!=-1){			
				System.out.print((char)temp);
			}
			
			reader.close();//关闭资源
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	//通过字符流FileWriter写入文件
	public void output(){
		try {
			FileWriter writer=new FileWriter("e://abc.txt");
			
			writer.write("我爱中国");
			
			//writer.write('c');
			//writer.write('我');
			
			writer.flush();
			writer.close();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

二、实例

下面我们也实现一个复制文件的方法,并分别尝试复制普通文本和复制图片,发现文本复制成功,而图片复制失败。原因我们下面介绍。

public class Stuer {
	
	public static void main(String[] args) {
		Stuer stuer=new Stuer();		
		stuer.copy("e://abc.txt", "d://abc.txt");//成功
		stuer.copy("e://P1080092.jpg", "d://aa.jpg");//失败
	}
	
	public void copy(String srcpath,String targetpath){
		FileReader reader=null;
		FileWriter writer=null;
		
		try {
			reader=new FileReader(srcpath);
			writer=new FileWriter(targetpath);
			int temp;
			while((temp=reader.read())!=-1){			
				//System.out.print((char)temp);
				writer.write(temp);
			}

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				reader.close();
				writer.flush();
				writer.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
	
}

三、字符流和字节流的区别

1、存储单元

字符流处理的单元为2个字节的Unicode字符,可以操作字符、字符数组或字符串,字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的。

字节流处理单元为1个字节, 操作字节和字节数组。

2、作用

字符流只能处理字符或者字符串,所以它对多国语言支持性比较好。如果是关系到中文,用字符流好点。

字节流可用于任何类型的对象,包括二进制对象如果是图片、音频、歌曲就用字节流好点。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值