文章目录
六、IO流
File文件对象
创建一个File对象 ,可以表示文件或文件夹
文件路径的连接,对于window系统使用\右斜杠连接路径,在java中可使用/或\(需要两个转义)连接
三种创建方式:
File f1 = new File("F:/abc");//绝对路径
File f2 = new File("abc");//相对路径,相对于项目目录
File f3 = new File(f1,"abc");//f1的子目录
文件常用的方法:
import java.io.File;
import java.io.IOException;
import java.util.Date;
public class test {
public static void main(String[] args) throws IOException {
File f1 = new File("F:/test/123.txt");//绝对路径
System.out.println("判断文件或文件夹是否存在:"+f1.exists());
System.out.println("判断是否是文件:"+f1.isFile());
System.out.println("判断是否是文件夹:"+f1.isDirectory());
System.out.println("获取文件长度(字节数):"+f1.length());
System.out.println("获取文件最后修改时间:"+new Date(f1.lastModified()) );
File f2 = new File("F:/test1/abc.txt");
f1.renameTo(f2);
File f3 = new File("F:/test/");//绝对路径
// 以字符串数组的形式,返回当前文件夹下的所有文件(不包含子文件及子文件夹)
for (String name:f3.list()) {
System.out.print(name +"\t\t");
}
System.out.println();
// 以文件数组的形式,返回当前文件夹下的所有文件(不包含子文件及子文件夹)
for (File f:f3.listFiles()) {
System.out.print(f + "\t\t");
}
System.out.println();
// 以字符串形式返回获取所在文件夹
System.out.println(f3.getParent());
// 以文件形式返回获取所在文件夹
System.out.println(f3.getParentFile());
File f4 = new File("F:/test1/123/");//绝对路径
// 创建文件夹,如果父文件夹test1不存在,创建就无效
f4.mkdir();
// 创建文件夹,如果父文件夹test1不存在,就会创建父文件夹
f4.mkdirs();
File f5 = new File("F:/test/wc.txt");//绝对路径
// 创建一个空文件,如果父文件夹test不存在,就会抛出异常
f5.createNewFile();
// 所以创建一个空文件之前,通常都会创建父目录
f5.getParentFile().mkdirs();
File f6 = new File("F:/test/wc.txt");//绝对路径
// 列出所有的盘符c: d: e: 等等
for (File f:File.listRoots()) {
System.out.println(f);
}
// 刪除文件
//f6.delete();
// JVM结束的时候,刪除文件,常用于临时文件的删除
f6.deleteOnExit();
while (true){}//当程序死循环没有结束时,f6没有被删除,当手动结束运行时,f6被删除
}
}
什么是流
流就是一系列的数据,当不同的介质之间有数据交互时,java就使用流来实现
字节流
InputStream字节输入流,OutputStream字节输出流,用于以字节的形式读取或写入数据
ASCII码,所有的数据存储在计算机中都是以数字的形式存储的
以字节流的形式读取文件
InputStream是字节输入流,同时也是抽象类,只提供方法声明,不提供方法的具体实现
FileInputStream 是InputStream子类,以FileInputStream 为例进行文件读取
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class test {
public static void main(String[] args) throws IOException {
File f1 = new File("F:/test/123.txt");//绝对路径
FileInputStream fis = new FileInputStream(f1);
System.out.println(fis.read()+"\t");//一次读取一个字节。读取结尾返回-1
byte[] b = new byte[(int) f1.length()];
fis.read(b);//读取全部文件到字节数组
for (byte bb : b) {
System.out.println(bb);
}
fis.close();//使用完关闭流
}
}
以字节流的形式向文件写入数据
OutputStream是字节输出流,同时也是抽象类,只提供方法声明,不提供方法的具体实现
FileOutputStream 是OutputStream子类,以FileOutputStream 为例向文件写出数据
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class test {
public static void main(String[] args) throws IOException {
//如果文件不存在会创建文件,如果目录不存在,则报错
File f1 = new File("F:/test/123.txt");//绝对路径
FileOutputStream fos = new FileOutputStream(f1);
//开始写时,是由文件开头进行写,会覆盖源文件
fos.write(95);//一次写一个字节
byte[] b = {69,70};
fos.write(b);//写字节数组到文件
fos.close();//使用完关闭流
}
}。
流的关闭方式
1、在try中关闭,这种有弊端,当读取文件发生异常时,关闭流的语句则不会执行,这会造成资源的浪费
2、在finally中关闭(标准关闭方式):
a、首先把流的引用声明在try的外面,如果声明在try里面,其作用域无法抵达finally
b、在finally关闭之前,要先判断该引用是否为空
c、关闭的时候,需要再一次进行try catch处理
3、使用try()的方式,把流定义在try()里,try,catch或者finally结束的时候,会自动关闭。这种编写代码的方式叫做 try-with-resources, 这是从JDK7开始支持的技术。所有的流,都实现了一个接口叫做 AutoCloseable,任何类实现了这个接口,都可以在try()中进行实例化。 并且在try, catch, finally结束的时候自动关闭,回收相关资源。
try (FileInputStream fis = new FileInputStream(f)) {}
字符流
操作方式和字节流类似,只不过字符流读取时会把一个字符的所有字节都读到,字节流只读一个字节
文件编码格式
ISO-8859-1 包含 ASCII
GB2312 是简体中文,BIG5是繁体中文,GBK同时包含简体和繁体以及日文。
unicode 包括了所有的文字,无论中文,英文,藏文,法文,世界所有的文字都包含其中。
unicode每个字符占4个字节,对存储数字和字母很不友好,造成空间浪费,所有就有utf-8。
UTF-8对数字和字母就使用一个字节,而对汉字就使用3个字节。
不希望byte数组输出负数,可以让结果与上0xFF,来使结果为正数
对于字节数组打印成字符,可以使用String ss = new String(c,“utf-8”);
FileReader得到的是字符,所以一定是已经把字节根据某种编码识别成了字符了,而FileReader使用的编码方式是Charset.defaultCharset()的返回值,如果是中文的操作系统,就是FileReader是不能手动设置编码方式的,为了使用其他的编码方式,只能使用InputStreamReader来代替GBK。
缓存流
以介质是硬盘为例,字节流和字符流的弊端,在每一次读写的时候,都会访问硬盘。 如果读写的频率比较高的时候,其性能表现不佳
BufferedReader读取文件
缓存字符输入流 BufferedReader 可以一次读取一行数据
FileReader fr = new FileReader(f1);
BufferedReader bis = new BufferedReader(fr);
String str = bis.readLine();
System.out.println(str);
PrintWriter写出数据
PrintWriter 缓存字符输出流, 可以一次写出一行数据
FileWriter fw = new FileWriter(f1);
PrintWriter bis = new PrintWriter(fw);
bis.println("我是第一行");
bis.println("我是第二行");
bis.println("我是第三行");
flush
强制把缓存中的数据写到硬盘
数据流
DataInputStream 数据输入流,DataOutputStream 数据输出流
使用数据流的writeUTF()和readUTF() 可以进行数据的格式化顺序读写
通过DataOutputStream 向文件顺序写出 布尔值,整数和字符串。 然后再通过DataInputStream 顺序读入这些数据。
要用DataInputStream 读取一个文件,这个文件必须是由DataOutputStream 写出的,否则会出现EOFException,因为DataOutputStream 在写出的时候会做一些特殊标记,只有DataInputStream 才能成功的读取
对象流
对象流指的是可以直接把一个对象以流的形式传输给其他的介质,比如硬盘
一个对象以流的形式进行传输,叫做序列化。 该对象所对应的类,必须是实现Serializable接口
练习
1)遍历文件夹(忽略子目录)
遍历这个C:\WINDOWS目录的所有文件,找出最大最小的文件,打印他们的名字
import java.io.File;
import java.io.IOException;
public class Exercise {
public static void main(String[] args) throws IOException {
File f = new File("F:/test");
long maxFileSize = 0;
long minFileSize = 0;
String maxName = "";
String minName = "";
boolean isFirst = true;
if (f.exists()) {
File[] files = f.listFiles();//目录下所有文件和文件夹对象
if (files !=null && files.length != 0) {//确保不会空指针
for (File file : files) {
if (file.isFile()) {
if (isFirst) {//第一次查询到文件,把文件信息保存,然后后面的文件都和保存的做对比
maxFileSize = file.length();
minFileSize = file.length();
maxName = file.getName();
minName = file.getName();
isFirst = false;
}
if (file.length() > maxFileSize) {
maxName = file.getName();
maxFileSize = file.length();
}
if (file.length() < minFileSize) {
minName = file.getName();
minFileSize = file.length();
}
}
}
System.out.println("最大文件为:" + maxName + ",大小为:" + maxFileSize);
System.out.println("最小文件为:" + minName + ",大小为:" + minFileSize);
} else {
System.out.println("目录中没有文件或对象为null");
}
} else {
System.out.println("目录不存在");
}
}
}
2)遍历文件夹(包括子目录)
遍历这个C:\WINDOWS目录的所有文件,找出最大最小的文件,打印他们的名字
import java.io.File;
import java.io.IOException;
/***
* 如果抽象路径名不表示一个目录,或者发生 I/O 错误,则返回 null。
* 在读取windows目录时发生了I/O错误,这是怎么回事呢?通过上网查阅资料,
* 发现,存在一些文件/文件夹的访问权限很高,我们没有权限对其进行读写,
* 此时就发生了所谓的I/O错误
*/
public class Exercise {
private static long maxFileSize = 0;
private static long minFileSize = 0;
private static String maxName = "";
private static String minName = "";
private static boolean isFirst = true;
public static void main(String[] args) throws IOException {
File f = new File("F:/test");
if(f.exists()){
for (File file : f.listFiles()) {
MaxAndMinFile(file);
}
System.out.println("最大文件为:" + maxName + ",大小为:" + maxFileSize);
System.out.println("最小文件为:" + minName + ",大小为:" + minFileSize);
}
else {
System.out.println("目录不存在");
}
}
public static void MaxAndMinFile(File file){
if(file.isDirectory()) {
try {
if(file.listFiles().length != 0){
File[] files = file.listFiles();
for (File f : files) {
MaxAndMinFile(f);
}
}else {
System.out.println("为空文件夹");
}
}catch (NullPointerException e){
System.out.println(file.getAbsolutePath());
}
}else {
if (isFirst) {//第一次查询到文件,把文件信息保存,然后后面的文件都和保存的做对比
maxFileSize = file.length();
minFileSize = file.length();
maxName = file.getName();
minName = file.getName();
isFirst = false;
}
if (file.length() > maxFileSize) {
maxName = file.getName();
maxFileSize = file.length();
}
if (file.length() < minFileSize) {
minName = file.getName();
minFileSize = file.length();
}
}
}
}
3)写入数据到文件,如何解决目录不存在的问题
判断父目录是否存在,不存在就创建
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Exercise {
public static void main(String[] args) throws IOException {
File f = new File("F:/test1/yy");
File dir = new File(f.getParent());
if(!dir.exists()){
dir.mkdirs();
}
FileOutputStream fis = new FileOutputStream(f);
fis.write(98);
fis.close();
}
}
4)练习拆分文件
找到一个大于100k的文件,按照100k为单位,拆分成多个子文件,并且以编号作为文件名结束。
import java.io.*;
public class Exercise {
public static void main(String[] args) throws IOException {
File f = new File("F:/test1/222.exe");
splitFile(f,100);//以100k大小拆分文件
}
public static void splitFile(File f ,int chunks) throws IOException {
int readContent = 1;//每次读取源文件的内容
int chunkCount = 0;//拆分块的数量
File fdir = new File(f.getParent()+"/splited/");
fdir.mkdirs();//创建一个文件夹,存放拆分的文件
if(f.exists() && f.isFile()){
FileInputStream fis = new FileInputStream(f);
//计算需要拆分多少块
if(f.length()%chunks*1024 == 0)
{
chunkCount =(int) f.length()/(chunks*1024);
}
else {
chunkCount =(int) f.length()/(chunks*1024) +1;
}
//循环读取内容,并写入新文件
for (int i = 0; i <chunkCount; i++) {
FileOutputStream fos = new FileOutputStream(new File(f.getParent()+"/splited/"+f.getName()+"-"+i));
for (int j = 0; j < chunks*1024; j++) {
readContent = fis.read();
if(readContent == -1)//读取最后一个块的时候可能不是完整的块大小,需要判断
{
break;
}
fos.write(readContent);
}
fos.close();
}
}
else {
System.out.println("文件不存在或文件是一个目录");
}
fis.close();
}
}
5)练习合并文件
将上题拆分的文件合并,合并后可以正常打开
import java.io.*;
public class Exercise {
public static void main(String[] args) throws IOException {
File fileMerged = new File("F:/test1/222-副本.exe");//合并后的文件
FileOutputStream fos = new FileOutputStream(fileMerged);
File fdir = new File(fileMerged.getParent()+"/splited/");//合并块的目录
File[] farray = fdir.listFiles();
for (File files : farray) {
FileInputStream fis = new FileInputStream(files);
for (int i = 0; i < files.length(); i++) {
fos.write(fis.read());
}
fis.close();
}
System.out.println("合并完成");
}
}
6)练习加密解密文件
准备一个文本文件(非二进制),其中包含ASCII码的字符和中文字符。
设计一个方法public static void encodeFile(File encodingFile, File encodedFile);
在这个方法中把encodingFile的内容进行加密,然后保存到encodedFile文件中
加密算法:
数字:原数字加一,数字9变成零;字母:原字母往后移一个字母,z变成a,保留大小写
设计一个方法解密public static void decodeFile(File decodingFile, File decodedFile);
import java.io.*;
public class Exercise {
public static void main(String[] args) throws IOException {
File f = new File("F:/test/encoding.txt");
File f2 = new File("F:/test/encoded.txt");
File f3 = new File("F:/test/decoded.txt");
encodeFile(f, f2);
decodeFile(f2,f3);
}
public static void encodeFile(File encodingFile, File encodedFile) throws IOException {
FileReader fr = new FileReader(encodingFile);
FileWriter fw = new FileWriter(encodedFile);
int c;
while ((c = fr.read()) != -1) {
if(c<=122){
if(Character.isLetter(c) || Character.isDigit(c)) {
if (c == 57) {
fw.write(48);
} else if (c == 90) {
fw.write(65);
} else if (c == 122) {
fw.write(97);
} else {
fw.write(c + 1);
}
fw.flush();
}
else {
fw.write(c);
fw.flush();
}
}
else {
fw.write(c);
fw.flush();
}
}
}
public static void decodeFile(File decodingFile, File decodedFile) throws IOException {
FileReader fr = new FileReader(decodingFile);
FileWriter fw = new FileWriter(decodedFile);
int c;
while ((c = fr.read()) != -1) {
if(c<=122){
if(Character.isLetter(c) || Character.isDigit(c)) {
if (c == 48) {
fw.write(57);
} else if (c == 65) {
fw.write(90);
} else if (c == 97) {
fw.write(122);
} else {
fw.write(c - 1);
}
fw.flush();
}
else {
fw.write(c);
fw.flush();
}
}
else {
fw.write(c);
fw.flush();
}
}
}
}
7)练习数字对应的中文
找出 E5 B1 8C 这3个十六进制对应UTF-8编码的汉字
import java.io.IOException;
public class Exercise {
public static void main(String[] args) throws IOException {
byte[] barray = new byte[]{(byte) 0xE5,(byte) 0xB1,(byte) 0x8C,};
System.out.println(new String(barray,"utf-8"));
}
}
9)练习移除utf-8编码方式中,字节前面的标识符
如果用记事本根据UTF-8编码保存汉字就会在最前面生成一段标示符,这个标示符用于表示该文件是使用UTF-8编码的。找出这段标示符对应的十六进制,并且开发一个方法,自动去除这段标示符
import java.io.*;
public class Exercise {
public static void main(String[] args) throws IOException {
File f = new File("F:/test/wbom.txt");
FileInputStream fr = new FileInputStream(f);
byte[] barray = new byte[(int) f.length()];
fr.read(barray);
System.out.print("utf-8的标识符为:");
for (int i = 0; i < 3; i++) {
int bom = barray[i] & 0x000000ff;
System.out.print(Integer.toHexString(bom) + "\t");
}
System.out.println();
splitBom(f);
fr.close();
}
public static void splitBom(File file) throws IOException {
FileInputStream fr = new FileInputStream(file);
File f = new File("F:/test/wnobom.txt");
FileOutputStream fos = new FileOutputStream(f);
int cha;
int flag = 0;
while ((cha = fr.read())!=-1){
if(flag >=3){
fos.write(cha);
}else {
flag++;
}
}
}
}
10)移除注释
设计一个方法,用于移除Java文件中的注释,移出以//开头的注释行
import java.io.*;
public class Exercise {
public static void main(String[] args) throws IOException {
File f = new File("F:/test/comment.txt");
removeComments(f);
}
public static void removeComments(File javaFile) throws IOException {
FileReader fis =new FileReader(javaFile);
BufferedReader br = new BufferedReader(fis);
File f = new File("F:/test/removeComment.txt");
FileWriter fos = new FileWriter(f);
BufferedWriter bw = new BufferedWriter(fos);
//完全复制原文件
/***
* 因为写每行字符串需要加回车,如果在每行写完在加,会在最后行多出来一行空行
* 回车写在前,就会避免,不过会出现另外的问题,第一行会多出来空行
* 那么就把第一行单独写了的,再写后面行
*
* !!!第一行如果有注释,我没有做处理!!!!
*/
String str =br.readLine();
bw.write(str);
while ((str = br.readLine()) != null){
if(str.contains("//")){
if(!str.trim().startsWith("//")){
str = str.substring(0,str.indexOf("//"));
bw.write("\r\n"+str );
}
}else
{
bw.write("\r\n"+str );
}
}
bw.flush();
bw.close();
}
}
11)练习-向文件中写入两个数字,然后把这两个数字分别读取出来
第一种方式: 使用缓存流把两个数字以字符串的形式写到文件里,再用缓存流以字符串的形式读取出来,然后转换为两个数字。
注: 两个数字之间要有分隔符用于区分这两个数字。 比如数字是31和15如果不使用分隔符,那么就是3115,读取出来就无法识别到底是哪两个数字。 使用分隔符31@15能解决这个问题。
import java.io.*;
public class Exercise {
public static void main(String[] args) throws IOException {
File f = new File("F:/test/w.txt");
FileWriter fw = new FileWriter(f);
BufferedWriter bw = new BufferedWriter(fw);
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
bw.write(String.valueOf(3123));
bw.write("@");
bw.write(String.valueOf(3554));
bw.close();
StringBuffer sb = new StringBuffer();
int temp;
while ((temp=br.read()) != -1){
if(temp != 64){
sb.append((char)temp);
}else {
sb.append(' ');
}
}
System.out.println(sb);
}
}
第二种方式: 使用数据流DataOutputStream向文件连续写入两个数字,然后用DataInpuStream连续读取两个数字
import java.io.*;
public class Exercise {
public static void main(String[] args) throws IOException {
File f = new File("F:/test/w.txt");
FileOutputStream fos = new FileOutputStream(f);
DataOutputStream dos = new DataOutputStream(fos);
dos.writeInt(31356);
dos.writeInt(35485);
dos.close();
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
System.out.println(dis.readInt());
System.out.println(dis.readInt());
dis.close();
}
}
12)序列化数组
准备一个长度是10,类型是Person的数组,使用10个Person对象初始化该数组
然后把该数组序列化到一个文件persons.p
接着使用ObjectInputStream 读取该文件,并转换为Person数组,验证该数组中的内容,是否和序列化之前一样
import java.io.*;
public class Exercise {
public static void main(String[] args) throws IOException, ClassNotFoundException {
File f = new File("F:/test/person.p");
Person[] parray = new Person[10];
for (int i = 0; i < parray.length; i++) {
parray[i] = new Person("名字" + i, (i + 10));
}
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
//序列化对象
oos.writeObject(parray);
oos.close();
//反序列化对象,并打印属性
Person[] p13 = (Person[]) ois.readObject();
for (Person p : p13) {
System.out.println(p.getName() + "," + p.getAge());
}
}
}
class Person implements Serializable {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
13)自动创建类
自动创建有一个属性的类文件
通过控制台,获取类名,属性名称,属性类型,根据一个模板文件,自动创建这个类文件,并且为属性提供setter和getter
import java.io.*;
import java.util.Scanner;
public class Exercise {
public static void main(String[] args) throws IOException {
File templet = new File("F:/test/templet.txt");
String classN;
String type;
String property = null;
String Uproperty;
Scanner s = new Scanner(System.in);
System.out.println("输入类名:");
classN = s.nextLine();
System.out.println("输入属性类型:");
type = s.nextLine();
boolean flag = true;
while (flag){
System.out.println("输入属性名:");
property = s.nextLine();
if(Character.isLowerCase(property.charAt(0))){
flag = false;
}else {
System.out.println("属性名首字母应该小写");
}
}
Uproperty = property.replace(property.charAt(0),Character.toUpperCase(property.charAt(0)));
FileReader fr = new FileReader(templet);
FileWriter fw = new FileWriter(templet.getParent()+"/"+classN+".java");
BufferedReader br = new BufferedReader(fr);
BufferedWriter bw = new BufferedWriter(fw);
String str;
while ((str = br.readLine()) != null){
str = str.replace("@class@",classN);
str = str.replace("@type@",type);
str = str.replace("@property@",property);
str = str.replace("@Uproperty@",Uproperty);
bw.write(str+"\r\n");
}
bw.close();
}
}
14)复制文件
实现复制源文件srcFile到目标文件destFile
public static void copyFile(String srcFile, String destFile){}
import java.io.*;
public class Exercise {
public static void main(String[] args) throws IOException {
String srcFilePath = "F:/test/test.exe";
String destFilePath= "F:/test/test-copy.exe";
copyFile(srcFilePath,destFilePath);
}
public static void copyFile(String srcFile, String destFile) throws IOException {
File srcf = new File(srcFile);
File destf = new File(destFile);
FileInputStream fis = new FileInputStream(srcf);
FileOutputStream fos = new FileOutputStream(destf);
int c;
//使用数组缓冲一下,速度会快一些
while ((c = fis.read()) != -1){
fos.write(c);
}
}
}
15)复制文件夹
把源文件夹下所有的文件 复制到目标文件夹下(包括子文件夹)
public static void copyFolder(String srcFolder, String destFolder){}
import java.io.*;
public class Exercise {
public static void main(String[] args) throws IOException {
String srcFolderPath = "F:/test";
String destFolderPath= "F:/test1";
copyFolder(srcFolderPath,destFolderPath);
}
public static void copyFile(String srcFile, String destFile) throws IOException {
File srcf = new File(srcFile);
File destf = new File(destFile);
FileInputStream fis = new FileInputStream(srcf);
BufferedInputStream bis = new BufferedInputStream(fis);
if(!destf.exists()){
destf.getParentFile().mkdirs();
}
FileOutputStream fos = new FileOutputStream(destf);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int c;
//使用缓冲流,速度会快很多
while ((c = bis.read()) != -1){
bos.write(c);
}
bos.close();
bis.close();
}
public static void copyFolder(String srcFolder, String destFolder) throws IOException {
File srcf = new File(srcFolder);
File destf = new File(destFolder);
for (File f : srcf.listFiles()) {
if(f.isFile()){
copyFile(f.getAbsolutePath(),destFolder+"/"+f.getName());
}else{
//复制空文件夹
if(f.listFiles().length == 0){
new File(destFolder+"/"+f.getName()).mkdirs();
}
copyFolder(f.getAbsolutePath(),destFolder+"/"+f.getName());
}
}
}
}
16)查找文件内容
假设你的项目目录是 e:/project,遍历这个目录下所有的java文件(包括子文件夹),找出文件内容包括 Magic的那些文件,并打印出来。
public static void search(File folder, String search);
import java.io.*;
public class Exercise {
public static void main(String[] args) throws IOException {
File f = new File("F:/Java/JavaProject");
search(f,"Magic");
}
public static void search(File folder, String search) throws IOException {
String str;
for (File f : folder.listFiles()) {
if (f.isFile()){
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
while ((str = br.readLine()) != null){
if(str.contains(search)){
System.out.println(f.getAbsolutePath());
break;
}
}
br.close();
}else {
search(f,search);
}
}
}
}