java IO 字节流、字符流操作总结一之File类

这篇文章将介绍有关java IO输入输出流的知识。首先说说字符编码的问题,比较常用的编码有gbk,utf-8等。

1.gbk 编码中文占用2个字节,英文占用1个字节。

2、utf-8编码中文占用3个字节,英文占用1个字节。

Java是双字节编码,utf-16be编码。即char占用2个字节。注意:当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,也需要用这种编码方式。否则会出现乱码。文本文件就是字节序列,可以是任意编码的字节序列。但是通常我们在中文的机器上直接创建文件,那么该文件只认识ANSI编码。


首先,介绍IO常用的第一个类File类(普通文件类)。

1、File类常用的API介绍

Java.IO.File类用于表示文件(目录),File类只用于表示文件(目录)的信息(大小,名称)等,不能用于文件内容的访问。常用的API如下:

boolean exists();判断文件是否存在
File file=new File(String path);<span style="font-family: Arial, Helvetica, sans-serif;">创建File对象,</span>这里path就是文件的绝对位置,如:c:\\file\\dooc 或者c:/file/dooc.txt都可以。
file.mkdir();创建目录
file.isDirectory();测试此抽象路径名表示的文件是否是一个目录。
file.isfile();测试此抽象路径名表示的文件是否是一个文件。
file.delete();删除这个文件或者目录
file.creatNewFile();创建新文件
file.getName();获取文件名或者目录的名称
file.getAbsolutepath();获取绝对路径
file.getParent();获取父级路径,如果没有则返回null
String[] list();返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
File[] listfiles();返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
File类中的list()方法用于列出当前的目录下的子目录和文件,返回的是字符串数组。直接列出子目录的文件,但不包含子目录的文件内容。

代码如下:

//实现一个遍历File对象的指定文件目录下的所有文件

public static void listDirectory(File dir) throws IOException{
		//判断dir目录存不存在
		try {
			if(dir.exists()){
				System.out.println("该目录存在");
			}else{
				throw new IllegalArgumentException("这个目录不存在");
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e);
		}
		//判断目录下是否有文件
		try {
			if(dir.isDirectory()){
				System.out.println("该目录存在文件夹");
			}else{
				throw new IllegalArgumentException("该目录不存在文件");
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e);
		}
		
		//方法一是调用list()方法来遍历,该方法返回的是一个字符串类型的数组
		//我们依次遍历看看看结果
//		String[] strs=dir.list();//返回的是路径名字符串数组
//		//使用foreach语句来遍历
//		for (String string : strs) {
//			System.out.println(dir+"\\"+string);//加上根目录显示
//		}
//		
//		System.out.println("上面的方法只能显示到子文件类型,既不能显示具体"
//				+ "的文件名称,也不能显示子文件下的文件");
		System.out.println("");
		//下面调用listFile()方法,该方法返回的是File对象的数组。同时可以直接获取file下的所有文件
		File[] files=dir.listFiles();//返回的是文件对象数组
		if(files!=null && files.length>0){//获取的数组即不为空,也不为0长度数组
			for (File file : files) {//遍历每一个文件
				
				if(file.isDirectory()){//查看是否还有文件在下面
					listDirectory(file);//递归调用,直到没有子文件为止
				}
				else{
					System.out.println(file);
				}
			}
		}
	}

总结:上面的测试类中包装了一些File的常用操作,例如过滤和遍历等:

1、列出指定目录下的(包含子目录)的所有文件。(这里是通过获取文件数组、遍历文件和递归调用实现的)

如果传进来的目录不存在或者不是文件夹,则应该抛出异常。这时我们需要用到判断语句。

2、file.list()方法;该方法返回当前目录下的文件名的字符串数组,但是不包含子目录下的文件和目录。

3、File[] files=file.listFile();可以直接获取file文件下的所有文件或者目录对象。然后以File对象数组的形式返回。然后可以调用递归就可以把所有的目录下的文件路径读出来,或者获取文件。

 

2、任意操作的文件类,RandomAccessFile类介绍。  

RandomAccessFile类对文件进行访问读写文件。随机访问文件即指在文件的任意的位置上都可以。java文件模型在硬盘上的文件时,是以(字节)byte byte byte存储的,是数据的集合。

--打开文件

RandomAccessFile类,在打开文件时有2种模式可以打开文件:rw 读写模式和r只读模式。

如:RandomAccessFile  raf=new RandomAccessFile(file,”rw”);

这里file的初始化如下:File file=new File(String path);

其中在读写文件时会有文件指针的存在,打开文件时文件的指针在开头,即pointer=0;

--写方法

raf.write(int);当写一个int型数据时只写一个字节(即最后8位,注意这里是一个字节一个字节的写。所以一个int型数据要分4次写进),同时文件指针pointer指向下一个位置准备再次写入。

--读方法

 raf.seek(0);//将文件指针指向最开始的头部

 byte[] buf=new byte[(int)raf.length()];//读取指定长度的字节内容

 raf.read(buf);//读取指定长度的字节内容,并将内容存储在buf数组中

 //读取一个字节

 raf.seek(0);//将文件指针指向最开始的头部

 int b=raf.read();//只读取一个字节

文件读写完毕后,一定要记得关闭文件

raf.close(); 

代码如下:

package com.ll.iofile;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;

/**
 * 此方法用来测试RandomAccessFile类,用于读写文件
 * @author LULEI
 *
 */
public class testRandomAccessFile {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		
		File file=new File("Demo");//判断相对路径中是否存在指定的目录
		if(!file.exists()){
			file.mkdir();//新建一个Demo目录
		}
		File file2=new File(file,"wq.bat");//将指定的文件实例化给file2对象
		if(!file2.exists()){
			file2.createNewFile();//新建一个wq.bat文件
		}
		
		//创建一个从中读取和向里面写入的一个随机访问的文件流.该文件要有指定的名称
		RandomAccessFile raf=new RandomAccessFile(file2,"rw");//设置为读写模式
		//首先观察一下文件指针的位置
		System.out.println("文件指针的初始化位置在:"+raf.getFilePointer());
		
		//向文件流中进行写,注意一次只写一个字节
		raf.write('A');//注意char型字符占两个字节
		System.out.println("文件指针的位置在:"+raf.getFilePointer());
		String s="中";
		byte[] sTObyte=s.getBytes("gbk");//设置为国标
		raf.write(sTObyte);
		System.out.println("添加中文后的文件指针的位置:"+raf.getFilePointer());
		
		int iNum=89;//Int型数据要分4次写入到文件中,一次一个byte
		raf.write(iNum>>>24);
		raf.write(iNum>>>16);
		raf.write(iNum>>>8);
		raf.write(iNum>>>0);
		System.out.println("普通方法添加int型数据后的文件指针的位置:"+raf.getFilePointer());
		byte[] bt={1,2,3,4};
		//可以写数组
		raf.write(bt);
		System.out.println("添加byte数组后的文件指针的位置:"+raf.getFilePointer());
		//可以直接写一个Int类型的数据
		raf.writeInt(20);//int占4个字节
		System.out.println("添加int型数据后的文件指针的位置:"+raf.getFilePointer());
		
		/*
		 * 向文件流进行读操作
		 */
		//一次只读一个字节的内容
		
		raf.seek(0);//读取数据之前一定要将文件指针指向头部
		int num=raf.read();
		System.out.println("只读一个字节返回的内容:"+Integer.toString(num));
		int num2=raf.read();
		System.out.println("只读一个字节返回的内容(十六进制显示):"+Integer.toHexString(num2&0xff));
		
		/*读取一定长度的字节的内容
		 * 读取文件前,一定要把文件指针指向开头
		 */
		raf.seek(0);
		int n=(int)raf.length();//获取文件流中内容的字节长度
		//创建一个同样长度大小的byte数组
		byte[] buf=new byte[n];
		raf.read(buf);//读取指定长度的字节内容,并将内容复制到buf数组中
		System.out.println("读取一定长度返回的内容");
		System.out.println(Arrays.toString(buf));
		for (byte b : buf) {
			System.out.print(Integer.toHexString(b & 0xff)+" ");
		}
		
		/*
		 * 最后关掉文件
		 */
		raf.close();
	}

}

这篇就先介绍到这里。其实我在写这句代码时(如下):

RandomAccessFile  raf=new RandomAccessFile(file,”rw”);
不知道有没有想到设计模式。是的,这里实际上就是一个装饰器模式。RandomAccessFile类是装饰器类,而File类是被装饰器类。通过包装,我们将原来的File类扩展为RandomAccessFile类。所以功能也就大大的提高了,其实在Java的整个IO框架中都大量的使用了装饰器模式。

这一篇就介绍到这里,下一篇将介绍Java 中IO的字节流。

你可能感兴趣的:(java,IO流)