Java IO流经典练习题
转载于:https://blog..net/wenzhi20102321/article/details/52582705
博主对转载的原代码进行了调试,改了一些小问题后,亲测可用。
本文对javaIO流的13道经典的练习题做解答,里面有详细的思路解析,做题时最好养成先写思路在编程的习惯。
(一) 在电脑D盘下创建一个文件为HelloWorld.txt文件,判断他是文件还是目录,在创建
一个目录IOTest,之后将HelloWorld.txt移动到IOTest目录下去;之后遍历IOTest这个目录下的文件
import java.io.File;
import java.io.IOException;
public class Test1 {
/**
* 1. 在电脑D盘下创建一个文件为HelloWorld.txt文件,
* 判断他是文件还是目录,再创建一个目录IOTest,
* 之后将HelloWorld.txt移动到IOTest目录下去;
* 之后遍历IOTest这个目录下的文件
*
* 程序分析:
* 1、文件创建使用File的createNewFile()方法
* 2、判断是文件用isFile(),判断是目录用isDirectory
* 3、创建目录用:mkdirs()方法
* 4、移动文件用:renameTo
* 5、遍历目录用:list()方法获得存放文件的数组,foreach遍历的方法把文件打印出来
* */
public static void main(String[] args) {
//在电脑D盘下创建一个文件为HelloWorld.txt文件
File file=new File("D:","HelloWorld.txt");
//创建文件,返回一个布尔值
boolean isCreate;
try {
isCreate = file.createNewFile();
if (isCreate) {
System.out.println("创建文件成功!");
}else {
System.out.println("创建文件失败!文件已经存在");
}
} catch (IOException e) {
System.out.println("创建文件失败!");
}
// 判断他是文件还是目录,
if (file.isFile()) {
System.out.println("这是一个文件");
} else {
System.out.println("这是一个目录");
}
//再创建一个目录IOTest
File file2=new File("D:/IOTest");
file2.mkdirs();
//HelloWorld.txt移动到IOTest目录下去
//移动文件用:renameTo(File file)里面需要传入一个file类型的对象
File file3 = new File(file1.getPath()+"/"+file1.getName());
//File file3 = new File("D:/IOTest/文件名"); //这里的代码加上
//file.renameTo(file3)会创建一个文件
if(file.renameTo(file3)) {
System.out.println("移动成功");
}else {
System.out.println("移动失败");
}
//遍历IOTest目录下的文件
//list() 返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。
String[] list = file1.list();
for(String str:list) {
System.out.println(str);
}
}
}
(二) 递归实现输入任意目录,列出文件以及文件夹,效果看图
1.先建一个FileUtile工具类
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* 这是一个获取目录下所有文件夹内的所有文件的封装类
* 当然前提是你要传进来一个正确路径的文件夹
* */
public class FileUtils {
//获取文件夹下所有的文件
public static List getAllFiles(String dir){
//创建一个集合存放遍历到的File
List< File >files=new ArrayList();
File file=new File(dir);
//文件夹必须存在 并且要是文件夹
if (file.exists()&&file.isDirectory()) {
//重点! 这里要本身一直遍历
longErgodic(file,files);//把遍历得到的东西存放在files里面
}
return files;
}
//重点理解,这是一个递归方法,会不断来回调用本身,但是所有获得的数据都会存放在集合files里面
private static void longErgodic(File file, List files) {
//.listFiles()方法的使用
//把文件夹的所有文件(包括文件和文件名)都放在一个文件类的数组里面
File[] fillArr=file.listFiles();
//如果文件夹有内容,遍历里面的所有文件(包括文件夹和文件),都添加到集合里面
for (File file2 : fillArr) {
//如果只是想要里面的文件或者文件夹或者某些固定格式的文件可以判断下再添加
files.add(file2);
//添加到集合后,在来判断是否是文件夹,再遍历里面的所有文件
//方法的递归
if(file2.isDirectory()) {
longErgodic(file2, files);
}
}
}
}
2.再建一个主方法调用类
import java.io.File;
import java.util.List;
/**
* 递归实现输入任意目录,列出文件以及文件夹
*
* 设计:在FileUtils类里面实现了逻辑操作,在另一边调用就可以了
* */
public class Test2 {
public static void main(String[] args) {
//比如输入D盘下自己建的测试文件夹
List list = FileUtileTest2.getAllFiles("D:/test");
//输出所有的文件和文件夹的名字
for(File file:list) {
System.out.println(file);
}
}
}
(三) 递归实现列出当前工程下所有.java文件
import java.io.File;
import java.util.List;
import com.xykj.lesson2.FileUtils;
public class Test3 {
/**
* 递归实现列出当前工程下所有.java文件
* 还是要题目2的遍历文件的工具类来获取所有的文件,再过滤.java文件就可以了
* 当前目录的地址:输入.就可以获取
* */
public static void main(String[] args) {
//输入. 获取当前文件的 所有文件
List list=FileUtils.getAllFiles(".");
//输出.java后缀的文件的名字
for (File file : list) {
if (file.toString().endsWith(".java")) {
System.out.println(file.getName());
}
}
}
}
(四)从磁盘读取一个文件到内存中,再打印到控制台
import java.io.File;
import java.io.FileInputStream;
public class Tset4 {
/**
* 从磁盘读取一个文件到内存中,再打印到控制台
*
* 程序设计:
* 1、读取文件用到FileinputSteam
* 2、把读取的内容不断加入到StringBuffer,
* 3、再把StringBuffer打印出来就可以
* */
public static void main(String[] args) {
// 读取D:\notePad\aa.txt里面的内容
//java7可以对实现了Closable接口的类使用try catch resource
//不用将close写在finally{}里面了,不用书写
File file = new File("D:\\notePad\\aa.txt");
// 创建读取流即输入流
try( FileInputStream fis = new FileInputStream(file);) {
int len = 0;
byte[] buf = new byte[1024];
StringBuffer sb = new StringBuffer();
// 把读取的数据添加到StringBuffer里面
while ((len = fis.read(buf)) != -1) {
sb.append(new String(buf, 0, len));
}
// 把StringBuffer里面的内容打印出来
System.out.println(sb);
} catch (Exception e) {
e.printStackTrace();
}
}
}
(五) 在程序中写一个"HelloJavaWorld你好世界"输出到操作系统文件Hello.txt文件中
import java.io.File;
import java.io.FileOutputStream;
public class Test5 {
/**
* 在程序中写一个"HelloJavaWorld你好世界"输出到操作系统文件Hello.txt文件中
*
* 程序分析:文件写入,要用到输出流FileOutputStream
* */
public static void main(String[] args) {
// 向文件D:/Hello.txt,写入内容
File file = new File("D:/Hello.txt");
try( FileOutputStream fos = new FileOutputStream(file);) {
// 创建输出流
//把String类型的字符串转化为byte数组的数据保存在输出流中
fos.write("HelloJavaWorld你好世界".getBytes());
fos.flush();//刷新输出流
} catch (Exception e) {
e.printStackTrace();
}
}
}
(六) 拷贝一张图片,从一个目录到另外一个目录下(PS:是拷贝是不是移动)
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Test6 {
/**
* 拷贝一张图片,从一个目录到另外一个目录下(PS:是拷贝是不是移动)
*
* 程序设计思路:
* 这题不能使用renameTo,
* 解题步骤:
* 1、在目的地址创建一个图片文件
* 2、读取源地址文件的字节流
* 3、把读取到的字节流写入到目的地址的文件里面
* 4、刷新输出流,并关闭就可以了
*
* @throws Exception
* */
public static void main(String[] args) {
// 本题示范把D盘下的mm.jpg复制到D盘java文件夹里面
// 源文件地址
File fileFrom = new File("D:/mm.jpg");
// 目的文件地址
File fileTo = new File("D:/java/mm.jpg");
// 1、创建目的文件地址
try {
if (!fileTo.createNewFile()) {
System.out.println("创建文件失败!");
}
// 2、读取源地址文件的字节流
FileInputStream fis = new FileInputStream(fileFrom);
FileOutputStream fos = new FileOutputStream(fileTo);
int len = 0;
byte[] buf = new byte[1024];
while ((len = fis.read(buf)) != -1) {
// 3、把读取到的字节流写入到目的地址的文件里面
fos.write(buf, 0, len);
}
// 刷新下输出流
fos.flush();
// 关闭输入流和输出流
fis.close();
fos.close();
System.out.println("文件复制成功!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
(七) 统计一个文件calcCharNum.txt(见附件)中字母'A'和'a'出现的总次数
import java.io.File;
import java.io.FileInputStream;
public class Test7 {
/**
* 统计一个文件calcCharNum.txt(见附件)中字母'A'和'a'出现的总次数
*
* 程序分析:
* 读取文件用FileInputStream
* 一次只读一个字节(一个字母就是一个字节),当字节内容和A或a相等时,相应的数量加1
* */
public static void main(String[] args) {
try {
//添加文件路径
File file = new File("D:/java/calcCharNum.txt");
//创建文件读取流
FileInputStream fis = new FileInputStream(file);
int numA = 0;//字母A的数量
int numa = 0;//字母a的数量
int len = 0;//每次读取的字节数量
while ((len=fis.read())!= -1) {
//统计字母a的数量
if (new String((char)len+"").equals("a")) {
numa++;
}
//统计字母A的数量
if (new String((char)len+"").equals("A")) {
numA++;
}
}
//打印出文件内字母的数量
System.out.println("a的数量是:"+numa);
System.out.println("A的数量是:"+numA);
System.out.println("a和A出现的总次数:"+(numA+numa));
fis.close();//关闭输入流
} catch (Exception e) {
e.printStackTrace();
}
}
}
(八)统计一个文件file.txt中各个字母出现次数:(可复制内容于文件中测试:A(8),B(16),C(10),a(12),b(10),c(3),A(8),B(16),C(10),a(12),b(10),c(3))
A(8),B(16),C(10)...,a(12),b(10),c(3)....,括号内代表字符出现次数;
import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
public class Test8 {
/**
* 统计一个文件calcCharNum.txt(见附件)中各个字母出现次数:
* A(8),B(16),C(10)...,a(12),b(10),c(3)....,括号内代表字符出现次数;
*
* 程序分析:
* 1.这里没中文字符,依然可以只用字节流来读取文件
* 2.不能保存相同的主键值,可以使用HashMap:key-value来实现
* 3.先获得该key的value,如果存在key的话value的值加1
* */
public static void main(String[] args) {
// 文件路径
File file = new File("file.txt");
try {
// 创建读取文件的输入流
FileInputStream fis = new FileInputStream(file);
// 创建集合HashMap类存放要保存的key-value
HashMap map = new HashMap<>();
// 读取文件
int len = 0;// 每次读取的文件长度
int count = 0;
while ((len = fis.read()) != -1) {
// 每次获取到的字母
char c = (char) len;
//这里使用try catch是因为 map.get(c + ""),第一次get不到东西会出现空指针
try {
// 通过每次的key值获取它的value值,
// 但是在它的key值没有时或报空指针错误,所以要try catch处理
// 当她有key值,就可以获取到相应的value值
count = (int) map.get(c + "");
} catch (Exception e) {// 什么都不用输出
}
// 如果有它的key值对应的value值要加1
map.put(c + "", count + 1);
}
fis.close();
// 读完后把结果打印出来
//迭代器的使用
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Entry entry = (Entry) iterator.next();
System.out.println(entry.getKey() + "{" + entry.getValue()+ "} \t");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
其实本题也可以直接用字符流来读取的。
(九)统计一个文件calcCharNum2.txt中各个字母出现次数:(复制下面进行测试)
A(8),B(16),C(10),a(12),b(10),c(3),中(5),国(6),括号内代表字符出现次数;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
public class Test9 {
/**
* 统计一个文件calcCharNum2.txt(见附件)中各个字母出现次数:
* A(8),B(16),C(10)...,a(12),b(10),c(3)....中(5),国(6),
* 括号内代表字符出现次数;
*
* 程序分析:
* 1.这出现中文字符,依然只能用字符流来读取文件
* 2.不能保存相同的主键值,可以使用HashMap:key-value来实现
* 3.先获得该key的value,如果存在key的话value的值加1
* */
public static void main(String[] args) {
// 文件路径
File file = new File("D:/java/calcCharNum2.txt");
// 创建集合HashMap类存放要保存的key-value
HashMap map = new HashMap<>();
try {
// 创建字符流
FileReader fr = new FileReader(file);
// 每次读取的字符长度
int len = 0;
int count=0;//出现该字符的次数
while ((len = fr.read()) != -1) {
// 获取对应的字符
char c = (char) len;
try {
// 通过每次的key值获取它的value值,
// 但是在它的key值没有时或报空指针错误,所以要try catch处理
// 当她有key值,就可以获取到相应的value值
count = (int) map.get(c + "");
} catch (Exception e) {// 什么都不用输出
}
// 如果有它的key值对应的value值要加1
map.put(c + "", count + 1);
}
// 读完后把结果打印出来
Iterator iterator = map.entrySet().iterator();
//迭代器的使用
while (iterator.hasNext()) {
Entry entry = (Entry) iterator.next();
System.out.print(entry.getKey() + "(" + entry.getValue()+ ") \t");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
(十) 使用随机文件流类RandomAccessFile将一个文本文件倒置读出。
import java.io.File;
import java.io.RandomAccessFile;
public class Test10 {
/**
* 使用随机文件流类RandomAccessFile将一个文本文件倒置读出。
*
* 程序分析:
* RandomAccessFile的seek方法能把读取文件的光标移动到具体的位置
* 但是还是有地点值得注意的是一个字母或数字是占用一个字节的, 一个汉字是占用两个字节的
* */
public static void main(String[] args) {
// 要读取的文件的地址
File file = new File("D:/java/calcCharNum2.txt");
try {
RandomAccessFile raf = new RandomAccessFile(file, "r");
long length = raf.length();
StringBuffer sb = new StringBuffer();
while (length > 0) {
length--;
raf.seek(length);
int c = (char) raf.readByte();
// 如果asc码<=255,>=0,则判断是个英文字符,添加到字符串中.
if (c >= 0 && c <= 255) {
sb.append((char) c);
} else {
// 如果不在asc码范围内,则判断是个汉字字符
// 汉字字符是占2个字节的,所以length再退一个字节
length--;
raf.seek(length);
byte[] cc = new byte[2];
// cc被复制为文件中连续的两个字节
raf.readFully(cc);
sb.append(new String(cc));
}
}
System.out.println(sb);
raf.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(十一) 编写一个Java应用程序,可以实现Dos中的type命令,并加上行号。
即将文本文件在控制台上显示出来,并在每一行的前面加上行号。
import java.io.File;
import java.io.IOException;
public class Test1 {
/**
* 1. 在电脑D盘下创建一个文件为HelloWorld.txt文件,
* 判断他是文件还是目录,再创建一个目录IOTest,
* 之后将HelloWorld.txt移动到IOTest目录下去;
* 之后遍历IOTest这个目录下的文件
*
* 程序分析:
* 1、文件创建使用File的createNewFile()方法
* 2、判断是文件用isFile(),判断是目录用isDirectory
* 3、创建目录用:mkdirs()方法
* 4、移动文件用:renameTo
* 5、遍历目录用:list()方法获得存放文件的数组,foreach遍历的方法把文件打印出来
* */
public static void main(String[] args) {
//在电脑D盘下创建一个文件为HelloWorld.txt文件
File file=new File("D:","HelloWorld.txt");
//创建文件,返回一个布尔值
boolean isCreate;
try {
isCreate = file.createNewFile();
if (isCreate) {
System.out.println("创建文件成功!");
}else {
System.out.println("创建文件失败!文件已经存在");
}
} catch (IOException e) {
System.out.println("创建文件失败!");
}
// 判断他是文件还是目录,
if (file.isFile()) {
System.out.println("这是一个文件");
} else {
System.out.println("这是一个目录");
}
//再创建一个目录IOTest
File file2=new File("D:/IOTest");
file2.mkdirs();
//HelloWorld.txt移动到IOTest目录下去?失败?》
if (file.renameTo(file2)) {
System.out.println("文件移动成功!");
} else {
System.out.println("文件移动失败");
}
//遍历IOTest目录下的文件
String[] arr=file2.list();
for (String string : arr) {
System.out.println(string);
}
}
}
(十二)输入两个文件夹名称,将A文件夹内容全部拷贝到B文件夹,要求使用多线程来操作。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.xykj.lesson2.FileUtils;
public class Test12 {
/*
* 输入两个文件夹名称,将A文件夹内容全部拷贝到B文件夹,要求使用多线程来操作。
*
* 程序分析:
* 1.拷贝文件里面的东西,要分析的东西还是蛮多的,要先建文件夹再拷贝里面的东西,而且要一层层的来搞
* 2.这里也需要文件遍历工具,直接调用第二题的工具类,不再重写
* 3.多线程的使用,可以直接在方法里面直接新建线程
* 4.对整个文件夹进行复制 文件夹分隔符可以用\\或/,其他的都是不对的
* 所有其中还对输入的分割符进行了替换
* 这题看起来比较长,分开看其实也不长
* */
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("要复制的文件夹:");
String fromDir = scanner.next();// 接收输入
System.out.println("要复制到哪里去:");
String toDir = scanner.next();// 接收输入
// 把输入的地址转化为File类型
File fromFile = new File(fromDir);
File toFile = new File(toDir);
//新建线程
new Thread(){
//里面做实际操作
public void run() {
// 判断如果要复制的是文件,直接复制就可以了
if (fromFile.isFile()) {
System.out.println("复制单个文件");
copy(fromFile, toFile);
} else {
// 要复制文件夹
// 要防止一种无法进行的复制:比如说,要把复制的文件复制到自己的子文件夹里面
// 举个例子:把D:/java/jsp文件夹复制到D:/java/jsp/js文件夹里面,
// 这会导致子文件不断增加的同时,而父文件也要不断增加,的一个死循环
// 如果反过来,就没事,相当于只是简单的覆盖而已
// 具体实现就是看:目的地地址包含复制的文件夹地址,就不允许操作
if (toDir.replace("/", "\\").toLowerCase()
.startsWith(fromDir.replace("/", "\\").toLowerCase())) {
return;
}
// 复制文件(包括文件和文件夹)操作
// 先获取所有的文件(包括文件和文件夹)
List list = FileUtils.getAllFiles(fromDir);
// 创建一个线程池,加快复制的速度
ExecutorService threadPool = Executors.newFixedThreadPool(20);
// 需要对每一个文件的路径进行处理
for (File file : list) {
// 复制文件名
String name = file.getAbsolutePath();
// 把原来的文件路径换成新的文件路径
String toName = name.replace(fromFile.getParent(), toDir + "/");
System.out.println(name + "变成了" + toName);
// 如果是文件夹,直接创建
if (file.isDirectory()) {
new File(toName).mkdirs();
} else {
// 如果是文件,在线程里面复制
threadPool.execute(new Runnable() {
@Override
public void run() {
File copyFile = new File(toName);
// 先要有父文件夹
copyFile.getParentFile().mkdirs();
// 开始复制文件
copy(file, copyFile);
}
});
}
}
}
scanner.close();
};
}.start();//开始线程
}
//复制文件的操作
public static void copy(File fromFile, File toFile) {
// 定义一个输入流
FileInputStream fis = null;
// 定义一个输出流
FileOutputStream fos = null;
try {
// 把复制地址的File,封装后赋值给输入流对象
fis = new FileInputStream(fromFile);
// 把目的地的File,封装后复制给输出流的对象
fos = new FileOutputStream(toFile);
// 创建一个容量,
byte[] buf = new byte[1024];
// 每次读取/写入的字节长度
int len = 0;
// 边读边写
while ((len = fis.read(buf)) != -1) {// 判断是否还能读到数据
// 把输入放到输出流里面
fos.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 关闭输入流和输出流
fis.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
(十三)查看D盘中所有的文件和文件夹名称,并且使用名称升序降序,文件夹在前和文件夹在
后,文件大小排序等。
import java.io.File;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.xykj.lesson2.FileUtils;
public class Test13 {
/**
* 查看D盘中所有的文件和文件夹名称,并且使用名称升序降序,
* 文件夹在前和文件夹在后,文件大小排序等。
*
* 程序分析:
* 1.查找文件和文件夹,需要例题二里遍历文件的工具类(这里直接调用,不在重写)
* 2.排序需要用到list集合里面的Collections工具类类的sort方法
* 3.这里有三重排序:首先是要按是否是文件夹来排序,然后按名称来排序,最后按大小来排序
* 其实这里还是会有问题的,按照某一个排序还没事,但是三个都排序就不一定有效!
实际应用中也是只按一种排序就可以了的
* */
public static void main(String[] args) {
List list =FileUtils.getAllFiles("D:");
//按文件夹先显示的顺序:
Collections.sort(list, new Comparator() {
@Override
public int compare(File o1, File o2) {
return (o2.isDirectory()?1:-1)-(o1.isDirectory()?1:-1);
}
});
//按文件名称显示的顺序:
Collections.sort(list, new Comparator() {
@Override
public int compare(File o1, File o2) {
return (o1.getName()).compareTo(o2.getName());
}
});
//按文件名称显示的顺序:
Collections.sort(list, new Comparator() {
@Override
public int compare(File o1, File o2) {
return (int)(o1.length()-o2.length());
}
});
//遍历集合的文件
for (File file : list) {
//打印排序后的文件或文件夹
System.out.println(file.getName());
}
}
}
以上是这些题目的详细的解题过程,当然很多题目的解决方法不是固定的,
但是对于基本的解题方式还是要了解的。对于知识点的掌握的话,
文件的基本操作,读取文件的基本方法,和写文件的基本方法都是要掌握的,
还有字节流的读取和字符流的读取方式和用处也要会区分。