10.18-文件的创建与写入

Java IO流(InputStream/OutputStream)

在变量、数组以及对象中存储的数据都是暂时的,在程序结束后就会丢失。

为了能够永久性保存程序创建的数据,需要将其保存在磁盘的文件中,这样就可以在其他程序中使用这些数据。

Java的IO技术可以将数据保存在文本文件、二进制文件甚至压缩文件中以达到数据永久性保存的目的。

掌握IO技术可以提高对数据的处理能力

File类

该类用于文件或者文件夹(目录),其实例就是用于描述文件系统上的一个文件/文件夹;通过File类就可以操作硬盘上的文件或目录。

注意

  • File类只能用于表达文件的信息(名称、大小、修改日期等等),不能对文件的内容进行操作,表示文件系统对文件、目录的管理操作

常用方法

File(String fileNmae) 指定文件名的构造器

long length() 获取文件的长度(字节量)

long lastModified() 获取文件最后一次的修改时间

String getName() 获取文件名

String getPath() 获取相对路径

boolean exists() 判断文件是否存在

file.isFile() 判断file是否为文件

dir.isDirectory 判断dir是否为目录

boolean canRead() 判断是否可读

boolean canWrite() 判断是否可写

mkdir() 创建一个目录(文件夹)

createNewFile() 创建一个文件

例子-基本方法

package day10_18;

import java.io.File;
import java.io.IOException;
import java.sql.Date;
import java.text.SimpleDateFormat;

public class FileDemo01 {
	/**
	 * java.io.File
	 * File类的每一个实例用于描述一个文件或文件夹
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		//绝对路径
//		File file = new File("C:\\eclipse\\eclipse-workspace\\se02\\test.ext");
	/*
	 * 使用绝对路径是不可取的,因为不易于程序的跨平台
	 * 使用相对路径
	 * '.'代表当前程序所在项目的根目录
	 * 
	 */
//		File file = new File(".\\test.txt");
		/*
		 * 在Windows平台下,目录的层级分隔符为\
		 * 在Linux平台下,目录层级分隔符为/
		 * File的常量separator:表示目录的层级分隔符
		 */
		File file = new File("."+File.separator+"test.txt");
		//获取文件名
		System.out.println(file.getName());
		//获取文件的长度
		System.out.println(file.length());
		//获取文件最后一次修改时间
		long lm = file.lastModified();
		System.out.println(lm);
		//毫秒值转换
		Date date = new Date(lm);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
		System.out.println(sdf.format(date));
		//获取相对路径
		System.out.println(file.getPath());
		//获取绝对路径
		System.out.println(file.getAbsolutePath());
		//获取系统标准绝对路径
		System.out.println(file.getCanonicalPath());
		//判断文件是否存在
		System.out.println(file.exists());//true
		//判断file对象是不是文件
		System.out.println(file.isFile());//true
		//判断file对象所表示文件夹
		System.out.println(file.isDirectory());//false
		//文件的读写状态只有两种:只读/可读可写
		//判断当前文件是否可读
		System.out.println(file.canRead());//true
		//判断当前文件是否可写
		System.out.println(file.canWrite());//true
	}
}

例子-创建文件

package day02;

import java.io.File;

public class FileDemo02 {
	/**
	 * 使用File对象创建目录:
	 * 在当前目录(项目的根目录)下创建一个demo目录
	 */
	public static void main(String[] args) {
		/*
		 * .\demo  这里的.\可以省略不写,
		 * 默认就是在当前目录下
		 */
		File dir = new File("demo");
		if(!dir.exists()) {
			/*
			 * boolean mkdir()
			 * 创建当前File对象路径中所描述的目录
			 */
			dir.mkdir();
		}
		System.out.println("创建完毕");
	}
}

例子-创建目录

package day02;

import java.io.File;

public class FileDemo03 {
	/**
	 * 在当前目录下创建目录
	 * a\b\c\d\e\f
	 */
	public static void main(String[] args) {
		File dir = new File("a"+File.separator+
				"b"+File.separator+
				"c"+File.separator+
				"d"+File.separator+
				"e"+File.separator+
				"f");
		if(!dir.exists()) {
			/*
			 * boolean mkdirs()
			 * 创建当前目录时会连同创建所有不存在
			 * 的父目录(上一级目录)
			 */
			dir.mkdirs();
		}
		System.out.println("创建完毕");
	}
}

例子-有参构造器创建文件

package day02;

import java.io.File;
import java.io.IOException;

public class FileDemo04 {
	/**
	 * 创建文件
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		//在当前目录下创建demo.txt
		File file1 = new File("demo.txt");
		if(!file1.exists()) {
			file1.createNewFile();
		}
		System.out.println("创建完毕");
		//在当前目录下的demo目录中创建demo.txt
//		File file2 = 
//				new File("demo"+File.separator+"demo.txt");
//		if(!file2.exists()) {
//			file2.createNewFile();
//		}
//		System.out.println("创建完毕");
		File dir = new File("demo");
		/*
		 * File(File dir,String fileName)
		 * 在给定的File对象所描述的目录中
		 * 表示给定名字的文件或者目录
		 */
		File file2 = new File(dir,"demo.txt");
		if(!file2.exists()) {
			file2.createNewFile();
		}
		System.out.println("创建完毕");
	}
}

例子-创建多重目录并创建文件

package day02;

import java.io.File;
import java.io.IOException;

public class FileDemo05 {
	/**
	 * 在当前目录创建
	 * g\h\i\j\k\mm.txt
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		File file = new File("g"+File.separator+
				"h"+File.separator+
				"i"+File.separator+
				"j"+File.separator+
				"k"+File.separator+
				"mm.txt");
		if(!file.exists()) {
			/*
			 * 在创建文件之前需要先创建目录
			 * File getParentFile()
			 * 获取当前File对象所描述的目录或者
			 * 文件的父目录
			 * 这里的父目录就是k目录
			 */
			File dir = file.getParentFile();
			if(!dir.exists()) {
				dir.mkdirs();
			}
			file.createNewFile();
		}
		System.out.println("创建完毕");
	}
}

例子-列出目录子项

package day02;

import java.io.File;
import java.io.IOException;

public class FileDemo06 {
	/**
	 * 查看当前目录下所有的子项
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		File dir = new File(".");
		System.out.println(dir.getCanonicalPath());
		if(dir.isDirectory()) {
			/*
			 * String[] list()
			 * 获取当前File对象所描述的目录中
			 * 所有子项的名称
			 */
			String[] subNames = dir.list();
			for(String subName:subNames) {
				System.out.println(subName);
			}
			System.out.println("--------------");
			/*
			 * File[] listFiles()
			 * 获取当前File对象所描述的目录中
			 * 所有的子项
			 */
			File[] subs = dir.listFiles();
			for(File sub:subs) {
				System.out.println
				(sub.getName()+":"+(sub.isFile()?"文件":"目录"));
			}
		}
	}
}

例子-删除文件

package day02;

import java.io.File;

public class FileDemo07 {
	/**
	 * 删除文件或者目录
	 */
	public static void main(String[] args) {
		//删除当前目录下的demo.txt文件
		File file = new File("demo.txt");
		file.delete();
		System.out.println("文件删除完毕");
		//删除当前目录下的demo目录
		File dir = new File("demo");
		/*
		 * 前提条件:
		 * 必须保证该目录是一个空目录(不
		 * 包含任何子项),才能删除成功
		 */
		dir.delete();
		System.out.println("目录删除完毕");
	}
}

例子-递归删除目录/文件

package day10_18;

import java.io.File;

public class FileDemo08 {
	public static void main(String[] args) {
		delete(new File(""));
	}

	// 定义方法,删除给定对像所描述的文件或文件夹
	public static void delete(File file) {
		if(file==null||!file.exists()) {
			throw new RuntimeException("指定文件不存在");
		}
		if(file.isFile()) {
			file.delete();
			return;
		}
		//获取file所描述文件夹中所有的子项
		
		File[] subs = file.listFiles();
		for(File sub:subs) {
			if(sub.isFile()) {
				//递归调用,删除子文件与子文件夹
				delete(sub);
			}
		}
		//子项删除完毕后,删除空文件夹
		file.delete();
	}
}

总结

  1. File类代表文件、文件夹

  2. 可以实现文件系统的操作(创建、修改、删除、查找),但没有提供递归处理

  3. new File()不是创建文件/文件夹,只是新建了一个内存对象来描述一个文件/文件夹

  4. File类不能操作文件里面的内容

    • 文件:一个长长的byte有序序列

RandomAccessFile类

可以用于操作/修改文件里面的内容

注意

  1. 此类以byte(字节,8bit)为单位处理文件

  2. 使用文件指针来读写文件,一次读写一个byte

  3. 当读写文件内容时,文件指针自动加1,为了方便下次的读写操作

  4. 为了方便读写基本类型的数据,提供了基本类型数据的读写方法,底层依旧以字节为单位进行读写操作

常用方法

  1. 构造器 RandomAccessFile (String fileName,String mode)

    • mode(状态) r/rw

    • 创建该类对象时,会自动的打开该文件;

    • 如果是写的时候文件不存在时将会自动创建文件

    • 打开文件时,默认的文件指针位置为0

    • 如果打开已存在的文件后立即写入,就是对文件内容的覆盖

    • 如果将文件指针跳过

  2. read()/write()

    • read() 是读取一个byte字节(读取到的结果填充到低八位)

    • write() 是写出一个byte字节(写出数据的低八位)

  3. seek() 一定文件读写指针

  4. close() 文件的读写操作结束后需要关闭文件

  5. length() 返回文件的长度(字节量)

例子-写文件

package day02;

import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomAccessFileDemo01 {
	/**
	 * 文件内容的写操作
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		RandomAccessFile raf = //dat是一种文件格式
			new RandomAccessFile("raf.dat","rw");
		/*
		 * write(int d)
		 * 写出给定int值的"低8位"
		 */
//		raf.write(300);
		//英文字母可以直接写出,因为一个字节就可以描述
		raf.write('A');
		raf.write('B');
		//中文不行,因为中文要满两个字节
//		raf.write('中');
		/*
		 * 写字符串:要先将字符串按照某个
		 * 字符集转换为对应的字节序列
		 */
		String str = "大家好";
		byte[] strData = str.getBytes("UTF-8");//中文占3个字节
//		for(byte b:strData) {
//			raf.write(b);
//		}
		/*
		 * write(byte[] b)
		 * 将给定的字节序列中所有的字节一次性全部写出
		 */
		raf.write(strData);
		//写int类型的最大值
		int max = Integer.MAX_VALUE;
		raf.write(max>>>24);//位移符号,右移24位
		raf.write(max>>>16);
		raf.write(max>>>8);
		raf.write(max);
		//连续写出4个字节,将给定的int值直接写出
		raf.writeInt(123);//4
		raf.writeLong(123L);//8
		raf.writeChar('中');//2
		raf.writeDouble(12.3);//8
		//关闭文件
		raf.close();
	}
}

例子-读文件

package day02;

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

public class RandomAccessFileDemo02 {
	/**
	 * 文件的读操作
	 */
	public static void main(String[] args) {
		RandomAccessFile raf = null;
		try {
			raf = 
				new RandomAccessFile("raf.dat","r");
			/*
			 * int read()
			 * 从文件中读取一个字节,并以int值的形式
			 * 返回,该int值只有"低8位"有效,若是返回
			 * -1,则说明EOF
			 * EOF:end of file  文件读取到末尾
			 */
			System.out.println((char)raf.read());
			System.out.println((char)raf.read());
			/*
			 * int read(byte[] b)
			 * 一次性尝试最多读取给定字节数组长度的
			 * 字节,并存入到给定的字节数组中,返回值
			 * 为实际读取到的字节量
			 */
			byte[] strData = new byte[9];
			int i = raf.read(strData);
			System.out.println(i);
			System.out.println(Arrays.toString(strData));
			//解码
			String str = new String(strData,"UTF-8");
			System.out.println(str);
			/*
			 * int readInt()
			 * 一次性连续读取4个字节,拼接为int值
			 */
			System.out.println(raf.readInt());
			System.out.println(raf.readInt());
			System.out.println(raf.readLong());
			System.out.println(raf.readChar());
			System.out.println(raf.readDouble());
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				raf.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

例子-读写文件

package day02;

import java.io.RandomAccessFile;

public class RandomAccessFileDemo03 {
	public static void main(String[] args) throws Exception{
		RandomAccessFile raf = 
			new RandomAccessFile("raf2.dat","rw");
		/*
		 * long getFilePointer()
		 * 返回游标(文件指针)的当前位置
		 */
		System.out.println(raf.getFilePointer());
		/*
		 * 1.将给定的int值转换为4个字节
		 *   将数据转换为对应字节序列的过程称之为"序列化"
		 * 2.将4个字节写入磁盘的文件中
		 *   将字节写入磁盘做长久保存的过程称之为"持久化"
		 * 
		 */
		raf.writeInt(1234);
		System.out.println(raf.getFilePointer());
		//移动文件的指针
		raf.seek(0);
		/*
		 * 将字节序列转换为对应数据的过程称之为"反序列化"
		 */
		int i = raf.readInt();
		System.out.println(i);
		//写字符串
		String str = "我是一个字符串";
		raf.writeUTF(str);//21+2 双引号也会算进去
		raf.seek(4);
		System.out.println(raf.readUTF());
		raf.close();
	}
}

练习

  1. 将控制台输入的内容,写入到当前目录下的note.txt中

    • (要求可以重复输入)

  2. 将当前目录下的tomcat.rar复制为tomcatCopy1.rar

最后更新于