William的总结(八):文件和IO流

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_21918021/article/details/88182489

一、文件File

文件大家都不陌生,查看JDK帮助文档,我们知道File的定义——文件和目录(文件夹)路径名的抽象表示形式。

1、构造方法

File(String pathname):根据一个路径得到File对象。
File(String parent, String child):根据一个目录和一个子文件/目录得到File对象。
File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象。

2、创建功能

public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了。
public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了。
public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来。

举例:
需求1:我要在e盘目录下创建一个文件demo

File file = new File("e:\\a.txt");

大家可能会认为这里用了关键字new,那么文件File就会出来了,其实不是,因为File的定义是:文件和目录(文件夹)路径名的抽象表示形式。它仅仅是文件的表示形式,不是真实的文件。 所以需要调用这样一句代码file.createNewFile()

需求2:我要在e盘目录test下创建一个文件b.txt

File file = new File("e:\\test\\b.txt");
System.out.println("createNewFile:" + file.createNewFile());

运行之后可以看到控制台打印出:

Exception in thread "main" java.io.IOException: 系统找不到指定的路径。

所以注意:要想在某个目录下创建内容,该目录首先必须存在。我们可以这么做:

File file1=new File("e:\\test");
file1.mkdir();
//先把文件夹(目录)创建出来然后在:

File file2=new File("e:\\test\\b.txt");
file2.createNewFile();//在创建文件

//看下面这行代码
File file = new File("e:\\liuyi\\a.txt");
System.out.println("mkdirs:" + file.mkdirs());

//你会看到a.txt是个目录,不要认为指定了.txt后缀就是文件了,要看它调用的是creatNewFile()还是mkdir();

3、删除功能

public boolean delete()
public class Demo1_File {
 
	public static void main(String[] args) throws IOException {
		
		File file1 = new File("abc.txt");
		File dir = new File("aaa");
		File dir2 = new File("bbb");
		System.out.println(file1.delete());
		System.out.println(dir.delete());
		System.out.println(dir2.delete());
		
	}

运行之后,发现bbb文件夹删除不了,原因是delete()方法不能删除文件夹下有文件或者文件夹的情况,只能删除空文件夹,还要注意,这里删除是不走回收站,删除文件之前需要小心。

这个方法比较简单,注意:

  • 如果你创建文件或者文件夹忘了写盘符路径,那么,默认在项目路径下。
  • Java中的删除不走回收站。
  • 要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹,所以delete一次只能删除一个文件,如果想删除一个文件夹,那必须要循环遍历了。

4、重命名功能

public boolean renameTo(File dest)

如果路径名相同,就是改名。
如果路径名不同,就是改名并剪切。

public class Demo1_File {
 
	public static void main(String[] args) throws IOException {
		
		File file1 = new File("cba.txt");
		File file2 = new File("C:\\Users\\user1\\Desktop\\abc.txt");
		System.out.println(file1.renameTo(file2));
		
	}

运行之后,发现确实把文件给重命名并剪切到桌面。

需求:将G盘所有视频文件该名成“0X-网络编程(概述).avi”,原来视频文件名称为:黑马程序员_毕向东_Java基础视频教程第23天-0X-网络编程(概述).avi

public class FileDemo {
	private static File dest;
	public static void main(String[] args) {
		//封装目录
		File  file=new File("G:\\黑马入学\\网络编程");
		File[] sorcFolder = file.listFiles();
		for (File f : sorcFolder) {
			String name = f.getName();
			//黑马程序员_毕向东_Java基础视频教程第23天-01-网络编程(概述).avi
			//System.out.println(name);			
			int index = name.indexOf('-');
			String string = name.substring(index+1);
			//再次封装新的文件目录
             dest = new File(file,string);
             f.renameTo(dest);            
		}
	}
}

在这里插入图片描述

5、判断功能

  public boolean isDirectory():判断是否是目录
  public boolean isFile():判断是否是文件
  public boolean exists():判断是否存在
  public boolean canRead():判断是否可读
  public boolean canWrite():判断是否可写
  public boolean isHidden():判断是否隐藏

6、简单获取功能

 public String getAbsolutePath():获取绝对路径
 public String getPath():获取相对路径
 public String getName():获取名称
 public long length():获取长度。字节数
 public long lastModified():获取最后一次的修改时间,毫秒值

示例代码:

public static void main(String[] args) {
		// 创建文件对象
		File file = new File("demo\\test.txt");
 
		System.out.println("getAbsolutePath:" + file.getAbsolutePath());
		System.out.println("getPath:" + file.getPath());
		System.out.println("getName:" + file.getName());
		System.out.println("length:" + file.length());
		System.out.println("lastModified:" + file.lastModified());
 
		// 1432518063391
		Date d = new Date(1432518063391L);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String s = sdf.format(d);
		System.out.println(s);
	}

执行结果是:
在这里插入图片描述

7、高级获取功能

public String[] list():获取指定目录下的所有文件或者文件夹的名称数组。
public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组。

后者功能更为强大一点,因为返回的是File对象,所以可以得到File的各种属性。

8.文件名称过滤器——FilenameFilter

需求:判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出此文件名称

public String[] list(FilenameFilter filter)
public File[] listFiles(FilenameFilter filter)

示例代码:

public static void main(String[] args) {
	
		//封装e盘
		File file=new File("e:\\");	
		// 获取该目录下所有文件或者文件夹的String数组
		String[] list = file.list(new FilenameFilter() {			
			@Override
			public boolean accept(File dir, String name) {
				//如果是文件并且是以.jpg结尾的,返回true,一旦返回true,name就会被放进String数组中,
				return new File(dir, name).isFile() && name.endsWith(".jpg");
			}
		});
		for (String string : list) {
			System.out.println(string);
		}
	}

虽然普通的方式也能实现,这样看起来,代码更加优雅,现在我们来看看list(FilenameFilter filter)的源码

public String[] list(FilenameFilter filter) {
        String names[] = list();
        if ((names == null) || (filter == null)) {
            return names;
        }
        List<String> v = new ArrayList<>();
        for (int i = 0 ; i < names.length ; i++) {
            if (filter.accept(this, names[i])) {
                v.add(names[i]);
            }
        }
        return v.toArray(new String[v.size()]);

二、IO流相关操作

在这里插入图片描述

1、IO流概述

(1)用来处理设备(硬盘,控制台,内存)间的数据。
(2)java中对数据的操作都是通过流的方式。
(3)java用于操作流的类都在io包中。
(4)按照流操作的数据的类型不同:分为字节流和字符流。字符流是为了方便中文的操作而来的。
(5)按照流的流向不同分为:输入流,输出流

2、字节流操作InputStream/OutputStream

2.1、输入字节流:InputStream

FileInputStream读取数据

构造方法
FileInputStream(String name) 
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
FileInputStream(File file) 
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
方法摘要
int available() (字节读取流特有方法!!!)
返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。

int read() 
从此输入流中读取一个数据字节。 

int read(byte[] b) 
从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 

int read(byte[] b, int off, int len) 
从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。 

long skip(long n) 
从输入流中跳过并丢弃 n 个字节的数据。 
操作步骤
a:创建字节输入流对象
b:调用read()方法
c:释放资源
代码体现:
FileInputStream fis = new FileInputStream("fos.txt");

//方式1,我们一次读取一个字节
int by = 0;
while((by=fis.read())!=-1) {
System.out.print((char)by);
} 

//方式2  我们一次读取一个字节数组
byte[] bys = new byte[1024];
int len = 0;
while((len=fis.read(bys))!=-1) {
System.out.print(new String(bys,0,len));
} 
fis.close();

BufferedInputStream读取数据

构造方法
BufferedInputStream(InputStream in) 
创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 

BufferedInputStream(InputStream in, int size) 
创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 
方法摘要
int available() (字节读取流特有方法!!!)
返回可以从此输入流读取(或跳过)、且不受此输入流接下来的方法调用阻塞的估计字节数。 

int read() 
参见 InputStream 的 read 方法的常规协定。 

int read(byte[] b, int off, int len) 
从此字节输入流中给定偏移量处开始将各字节读取到指定的 byte 数组中。 

long skip(long n) 
参见 InputStream 的 skip 方法的常规协定。

2.2、输出字节流:OutputStream

FileOutputStream写出数据

构造方法
FileOutputStream(String name) 
创建一个向具有指定名称的文件中写入数据的输出文件流。

FileOutputStream(String name, boolean append) 
创建一个向具有指定 name 的文件中写入数据的输出文件流。

FileOutputStream(File file) 
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 

FileOutputStream(File file, boolean append) 
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
方法摘要
void flush()刷新此缓冲的输出流。 
void close() 关闭此文件输出流并释放与此流有关的所有系统资源。
void write(int b) 将指定字节写入此文件输出流。
void write(byte[] b, int off, int len) 
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 
void write(int b) 将指定字节写入此文件输出流。
操作步骤
a:创建字节输出流对象
b:调用write()方法
c:释放资源
示例代码
FileOutputStream fos = new FileOutputStream("fos.txt");
fos.write("hello".getBytes());
fos.close();

BufferedOutputStream写出数据

构造方法
BufferedOutputStream(OutputStream out) 
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 

BufferedOutputStream(OutputStream out, int size) 
创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。 
方法摘要
void flush() 刷新此缓冲的输出流。 
void write(byte[] b, int off, int len) 
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流。 
void write(int b) 将指定的字节写入此缓冲的输出流。

PrintStream打印流

可将各种类型的数据原样打印,有自动刷新功能。

构造方法
PrintStream(String fileName) 
创建具有指定文件名称且不带自动行刷新的新打印流。

PrintStream(File file) 
创建具有指定文件且不带自动行刷新的新打印流。

PrintStream(OutputStream out) 
创建新的打印流。

PrintStream(OutputStream out, boolean autoFlush) (当autoFlush为true时具有自动刷新功能)
创建新的打印流。
方法摘要
PrintStream append(char c) 
将指定字符添加到此输出流。

void close() 
关闭流。 

void flush() 
刷新该流的缓冲。

void print(各种类型的数据:) 
打印各种类型的数据。

void println(各种类型的数据):自动换行
打印各种类型的数据。

void write(byte[] buf, int off, int len) 
将 len 字节从指定的初始偏移量为 off 的 byte 数组写入此流。 

void write(int b) 
将指定的字节写入此流。

2.3、四种方式复制文件效率比较

  • FileInputStream、FileOutputStream这两个类我们称之为基本字节流,相对于基本字节流,IO中还有高效字节流BufferedInputStream、BufferedOutputStream。

看完了这个,那么问题来,哪种方式好呢?
下面我们来看一个例子:

需求:把G:\IO流(IO流小结图解).avi复制到当前项目目录下的copy.avi中。
字节流四种方式复制文件:

  • 基本字节流一次读写一个字节
  • 基本字节流一次读写一个字节数组
  • 高效字节流一次读写一个字节
  • 高效字节流一次读写一个字节数组
    G:\IO流(IO流小结图解).av的信息如下:
    在这里插入图片描述
    示例代码:
public class CopyAVI {

	public static void main(String[] args) throws IOException {
	
		long start = System.currentTimeMillis();
		 method1("G:\\IO流(IO流小结图解).avi", "copy1.avi");
		 //method2("G:\\IO流(IO流小结图解).avi", "copy2.avi");
	     //method3("G:\\IO流(IO流小结图解).avi", "copy3.avi");
		 //method4("G:\\IO流(IO流小结图解).avi", "copy4.avi");
		long end = System.currentTimeMillis();
		System.out.println("共耗时:" + (end - start) + "毫秒");
	}
 
 	// 基本字节流一次读写一个字节
	public static void method1(String srcString, String destString)throws IOException {
		FileInputStream fis = new FileInputStream(srcString);
		FileOutputStream fos = new FileOutputStream(destString);
		int by = 0;
		while ((by = fis.read()) != -1) {
			fos.write(by);
		}
		fos.close();
		fis.close();
	}
	
 	// 基本字节流一次读写一个字节数组
	public static void method2(String srcString, String destString)throws IOException {
		FileInputStream fis = new FileInputStream(srcString);
		FileOutputStream fos = new FileOutputStream(destString);
 
		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = fis.read(bys)) != -1) {
			fos.write(bys, 0, len);
		}
		fos.close();
		fis.close();
	}
	
	// 高效字节流一次读写一个字节:
	public static void method3(String srcString, String destString)throws IOException {
	
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString));
		BufferedOutputStream bos = new BufferedOutputStream(newFileOutputStream(destString));
 
		int by = 0;
		while ((by = bis.read()) != -1) {
			bos.write(by);
 
		}
		bos.close();
		bis.close();
	}
 

    // 高效字节流一次读写一个字节数组:
	public static void method4(String srcString, String destString)throws IOException {
	
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString));
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destString));
		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = bis.read(bys)) != -1) {
			bos.write(bys, 0, len);
		}
 
		bos.close();
		bis.close();
	}

执行结果:

方法一执行:
在这里插入图片描述
方法二执行:
在这里插入图片描述
方法三执行:
在这里插入图片描述
方法四执行:
在这里插入图片描述
四种方式的性能差异,通过这个执行结果,想必大家也知道了 ,所以在实际开发中选择哪一个来操作文件,相信大家已经有了选择了,反正我是喜欢用方法四!!

3、字符流操作Reader/Write

3.1、输入字符流:Reader

FileReader读入数据

构造方法
FileReader(String fileName) 
在给定从中读取数据的文件名的情况下创建一个新 FileReader。

FileReader(File file) 
在给定从中读取数据的 File 的情况下创建一个新 FileReader。 

FileReader(FileDescriptor fd) 
在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。 
方法摘要

和Reader基类方法一致:

abstract void close() 关闭该流并释放与之关联的所有资源。
int read() 读取单个字符。
int read(char[] cbuf) 将字符读入数组
abstract int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。
long skip(long n) 跳过字符。 

BufferedReader读入数据

构造方法:
BufferedReader(Reader in) 
创建一个使用默认大小输入缓冲区的缓冲字符输入流。
方法摘要:
int read() 
读取单个字符。 
int read(char[] cbuf, int off, int len) 
将字符读入数组的某一部分。 
String readLine() 
读取一个文本行。 

InputStreamReader(字符通向字节的转换流)

涉及键盘录入时用。

构造方法:
InputStreamReader(InputStream in) 
创建一个使用默认字符集的 InputStreamReader。

方法摘要:

int read() 读取单个字符。
int read(char[] cbuf) 将字符读入数组。
abstract int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。
long skip(long n) 跳过字符。

LineNumberReader

跟踪行号的缓冲字符读取流。

构造方法:
LineNumberReader(Reader in) 
使用默认输入缓冲区的大小创建新的行编号 reader。
方法摘要
int read() 
读取单个字符。 
int read(char[] cbuf, int off, int len) 
将字符读入数组中的某一部分。 
String readLine() 
读取文本行。
long skip(long n) 
跳过字符。 
int getLineNumber() 
获得当前行号。 
void setLineNumber(int lineNumber) 
设置当前行号。 

3.2、输出字符流:Writer

FileWriter写出数据

构造方法:
FileWriter(String fileName) 
根据给定的文件名构造一个 FileWriter 对象。 

FileWriter(String fileName, boolean append) 
根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。 

FileWriter(File file) 
根据给定的 File 对象构造一个 FileWriter 对象。 

FileWriter(File file, boolean append) 
根据给定的 File 对象构造一个 FileWriter 对象。 

FileWriter(FileDescriptor fd) 
构造与某个文件描述符相关联的 FileWriter 对象。
方法摘要

跟Writer一样。

abstract void close() 关闭此流,但要先刷新它。
abstract void flush() 刷新该流的缓冲。
void write(int c) 写入单个字符。
void write(char[] cbuf) 写入字符数组。 
abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。 
void write(String str) 写入字符串。 
void write(String str, int off, int len) 写入字符串的某一部分。 

BufferedWriter写出数据

构造方法:
BufferedWriter(Writer out) 
创建一个使用默认大小输出缓冲区的缓冲字符输出流。 

BufferedWriter(Writer out, int sz) 
创建一个使用给定大小输出缓冲区的新缓冲字符输出流。 
方法摘要:
void close() 
关闭此流,但要先刷新它。 
void flush() 
刷新该流的缓冲。 
void newLine() 
写入一个行分隔符。 
void write(char[] cbuf, int off, int len) 
写入字符数组的某一部分。 
void write(int c) 
写入单个字符。 
void write(String s, int off, int len) 
写入字符串的某一部分。 

OutputStreamWriter(字节通向字符的转换流)

涉及键盘录入时用。

构造方法:
OutputStreamWriter(OutputStream out) 
创建使用默认字符编码的 OutputStreamWriter。
方法摘要:
void write(char[] cbuf, int off, int len) 
写入字符数组的某一部分。 
void write(int c) 
写入单个字符。 
void write(String str, int off, int len) 
写入字符串的某一部分。

PrintWriter

打印流,可处理各种类型的数据。

构造方法
PrintWriter(String fileName) 
创建具有指定文件名称且不带自动行刷新的新 PrintWriter。

PrintWriter(File file) 
使用指定文件创建不具有自动行刷新的新 PrintWriter。

PrintWriter(Writer out) 
创建不带自动行刷新的新 PrintWriter。 

PrintWriter(Writer out, boolean autoFlush) 
创建新 PrintWriter。 

PrintWriter(OutputStream out) 
根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。 

PrintWriter(OutputStream out, boolean autoFlush) 
通过现有的 OutputStream 创建新的 PrintWriter。
方法摘要:
PrintWriter append(char c) 
将指定字符添加到此 writer。 
void print(各种类型的数据:) 
打印各种类型的数据 
void println(各种类型的数据:):自动换行
打印各种类型的数据
void write(char[] buf) 
写入字符数组。 
void write(char[] buf, int off, int len) 
写入字符数组的某一部分。 
void write(int c) 
写入单个字符。 
void write(String s) 
写入字符串。 
void write(String s, int off, int len) 
写入字符串的某一部分。 

3.3、字符流操作文件

我们先看一个字符流操作文件的例子。
需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中。

数据源:
a.txt – 读取数据 – 字符转换流 – InputStreamReader – FileReader – BufferedReader
目的地:
b.txt – 写出数据 – 字符转换流 – OutputStreamWriter – FileWriter – BufferedWriter

示例代码:

public static void main(String[] args) throws IOException {
		// 封装数据源
		BufferedReader br = new BufferedReader(new FileReader("a.txt"));
		// 封装目的地
		BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
 
		// 两种方式其中的一种一次读写一个字符数组,当然此处你也可以一次读取一个字节的方法
		// char[] chs = new char[1024];
		// int len = 0;
		// while ((len = br.read(chs)) != -1) {
		// 	bw.write(chs, 0, len);
		// 	bw.flush();
		// }
		
		// 还有一种方式读写数据,这就是BufferedWriter、BufferedReader的强大之处。。。。
		String line = null;
		//下面三句话,我习惯连着写,写入、换行、刷新,动作相当连贯有木有啊!!!!!!
		 while ((line = br.readLine()) != null) {
			 bw.write(line);
		     bw.newLine();
			 bw.flush();
		}
		
		// 释放资源
		bw.close();
		br.close();
	}

代码解读: bw.newLine();这句话的意思是换行,调用的效果和我们写“\r\n”是一样的,但是newLine可以夸平台的,这就是区别!
readLine()这个方法有点厉害,因为它一次读一行!!!
博客写到这里,我们发现,复制文件文件起码有5种方式,前面所讲的1.基本字节流一次读写一个字节、2.基本字节流一次读写一个字节数组、3.高效字节流一次读写一个字节、4.高效字节流一次读写一个字节数组共4种,再加上上面的一种,共5种。

三、IO编程实战

3.1、复制单级文件夹

需求:复制指定目录下的指定文件,并修改后缀名。

  • 指定的文件是:.java文件。
  • 指定的后缀名是:.txt
  • 指定的目录是:txt
  • 数据源:G:\designModel
  • 目的地:G:\txt

分析:

  • A:封装目录

  • B:获取该目录下的java文件的File数组

  • C:遍历该File数组,得到每一个File对象

  • D:把该File进行复制

  • E:在目的地目录下改名

  • 数据源:G:\designModel如下图所示:

在这里插入图片描述
示例代码:

public class CopyFolder {
 
	public static void main(String[] args) throws IOException {
	
		 //A:封装目录
	     File srcFolder=new File("G:\\designModel");
	     //封装目的地
	     File destFolder=new File("G:\\myNote");
	     //如果目的地文件不存在,就创建一个
	     if(!destFolder.exists()){
	    	 destFolder.mkdir();
	     }
	     //B:获取该目录下的java文件的File数组     
	     File[] srcFiles = srcFolder.listFiles(new FilenameFilter() {		
			@Override
			public boolean accept(File dir, String name) {
				// 文件过滤器,得到.java文件,去除其他类型的文件
				return new File(dir,name).isFile()&&name.endsWith(".java");
			}
		});
	     
	     // C:遍历该File数组,得到每一个File对象
	     
	      for (File file : srcFiles) {
	    	  String name = file.getName();
	    	  File newFile=new File(destFolder,name);
			  copyFile(file,newFile);
		  }
	      
	  	  //E:在目的地目录下改名
	      for (File file :destFolder.listFiles()) {
			
	    	  String name = file.getName();
	    	  String newName = name.replace(".java", ".txt");
	    	  File newFile=new File(destFolder,newName);
			  file.renameTo(newFile);
		}
	      
	}
 
		//	D:把该File进行复制
	private static void copyFile(File file, File newFile) throws IOException {
		
		BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
		BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(newFile));    
		byte [] bys=new byte[1024];
		int len=0;
		while((len=bis.read(bys))!=-1){
			bos.write(bys,0,len);
		}
		//关闭资源
		bis.close();
		bos.close();
	}

执行结果:
在这里插入图片描述

3.2、复制多级文件夹

思路分析

数据源:G:\
目的地:G:\

A:封装数据源File
B:封装目的地File
C:判断该File是文件夹还是文件

a:是文件夹

  • 就在目的地目录下创建该文件夹
  • 获取该File对象下的所有文件或者文件夹File对象
  • 遍历得到每一个File对象
  • 回到C

b:是文件

  • 复制(字节流)

示例代码:

public class CopyFolders{
	public static void main(String[] args) throws IOException {
		// 封装数据源File
		File srcFile = new File("G:\\");
		// 封装目的地File
		File destFile = new File("E:\\");
		// 复制文件夹的功能
		copyFolder(srcFile, destFile);
	}
 
	private static void copyFolder(File srcFile, File destFile)throws IOException {
		// 判断该File是文件夹还是文件
		if (srcFile.isDirectory()) {
			// 文件夹
			File newFolder = new File(destFile, srcFile.getName());
			newFolder.mkdir();
			// 获取该File对象下的所有文件或者文件夹File对象
			File[] fileArray = srcFile.listFiles();
			for (File file : fileArray) {
				copyFolder(file, newFolder);
			}
		} else {
			// 文件
			File newFile = new File(destFile, srcFile.getName());
			copyFile(srcFile, newFile);
		}
	}
 
	//复制文件
	private static void copyFile(File srcFile, File newFile) throws IOException {
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));
		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = bis.read(bys)) != -1) {
			bos.write(bys, 0, len);
		}
		bos.close();
		bis.close();
	}

3.3、 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件

思路分析:

A:创建学生类
B:创建集合对象
因为要排序,所以用TreeSet
C:键盘录入学生信息存储到集合
D:遍历集合,把数据写到文本文件

public class Student {
	// 姓名
	private String name;
	// 语文成绩
	private int chinese;
	// 数学成绩
	private int math;
	// 英语成绩
	private int english;
 
	//构造方法和setter/getter方法省去了。。。。。。。。  
}
public class StudentIO {
	public static void main(String[] args) throws IOException {
		// 创建集合对象(采用匿名内部类的方式,创建带有比较器的集合对象)
		TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
			@Override
			public int compare(Student s1, Student s2) {
				int num = s2.getSum() - s1.getSum();
				int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
				int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;
				int num4 = num3 == 0 ? s1.getName().compareTo(s2.getName()): num3;
				return num4;
			}
		});
 
		// 键盘录入学生信息存储到集合
		for (int x = 1; x <= 5; x++) {
			Scanner sc = new Scanner(System.in);
			System.out.println("请录入第" + x + "个的学习信息");
			System.out.println("姓名:");
			String name = sc.nextLine();
			System.out.println("语文成绩:");
			int chinese = sc.nextInt();
			System.out.println("数学成绩:");
			int math = sc.nextInt();
			System.out.println("英语成绩:");
			int english = sc.nextInt();
 
			// 创建学生对象
			Student s = new Student();
			s.setName(name);
			s.setChinese(chinese);
			s.setMath(math);
			s.setEnglish(english);
 
			// 把学生信息添加到集合
			ts.add(s);
		}
 
		// 遍历集合,把数据写到文本文件
		BufferedWriter bw = new BufferedWriter(new FileWriter("students.txt"));
		//以下三行代码连写
		bw.write("学生信息如下:");
		bw.newLine();
		bw.flush();
	    bw.write("姓名\t语文成绩\t数学成绩\t英语成绩");
		bw.newLine();
		bw.flush();
		for (Student s : ts) {
			StringBuilder sb = new StringBuilder();
			sb.append(s.getName()).append("\t").append(s.getChinese())
					.append("\t").append(s.getMath()).append("\t")
					.append(s.getEnglish());
			bw.write(sb.toString());
			bw.newLine();
			bw.flush();
		}
		// 释放资源
		bw.close();
		System.out.println("学习信息存储完毕");
	}
}

输入:
在这里插入图片描述
执行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_21918021/article/details/88182489