1.文件操作(IO)
1.1文件操作定义
IO是input和output的缩写,翻译为中文就是输入流、输出流。
IO操作就是将数据写入内存或从内存输出的过程,也指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接 。
在输入输出中,我们需要知道以什么为基准来定义输入、输出,我们所说的输入、输出是以cpu为基准来看待的。
1.2绝对路径与相对路径
路径的含义:文件目录是树状结构,我们取到一个文件所经过的所有节点,就是这个文件的文件路径。
绝对路径:从根结点开始,一层一层向下找,经过的所有节点,就是绝对路径。
相对路径:从给定的某个目录出发,一层一层向下找,经过的所有节点,就是相对路径。在相对路径时,我们需要明确基准目录是哪个。
1.3文本文件与二进制文件
文本文件: 存储的文本遵守某些字符集编码(ASCII、utf8等),打开时,会通过对比字符集编码进行内容显示,就像我们打开文本文件时,我们都可以看懂是什么,在打开二进制文件时,内容就会出现乱码的情况(在字符集编码中无法找到相匹配的内容)。
二进制文件:二进制文件大大加大了存储的内容,它可以存储图片、音乐、视频,打开时以二进制的形式打开。
常见的文本文件(后缀):.txt、.java、.c等。
常见的二进制文件(后缀):.class、.exe、.jpg、.mp3、.docx等。
如何辨别二进制文件和文本文件?
非常简单,我们只需打开记事本,把文件拉入到记事本中,不乱码就是文本文件,乱码就是二进制文件,如下图,打开.java文件没有出现乱码,打开.docx 文件就变成了乱码。
2.Java中操作文件
在Java中,它给出了File类对文件进行操作。
2.1File类
2.1.1构造方法
2.1.2常用方法
3.文件内容的读写
O流体系如下,它分为两组,一组是字节流,一组是字符流,对于二进制文件进行文件内容读写可以使用InputStream(读)和OutputStream(写)操作,对于文本文件进行读写使用Reader(读)和Writer(写)进行操作,上方所说的四个类是抽象类,如果需要具体实现,我们需要实例化它的子类,通过子类完成任务。
我们下面对于字节流中的类进行详细讲解:
3.1输入流概述
读文件时使用的方法
在read()方法中,它的返回值是byte类型,但是为什么我们要使用int来接收呢?
用int类型来代替byte类型是为了解决读到结尾时出现难以辨别的情况,因为byte的取值范围是-128~127,当我们读到文件内容的末尾时,read()的返回值会是-1(文本内容也可能是-1),因为-1在buye的取值范围内,因此你不能确定它是文本内容还是到了文本结尾,而改为int,int的取值范围是0-255,返回-1,就很容易辨别是末尾了。
3.1.1FileInputStream概述
该类是对字节流的读操作实现。
构造方法
因为InputStream类是一个抽象类,我们想要使用,就要实例它的子类(FileInputStream)。
代码使用FileInputStream类:
import java.io.*; public class ioDemo1 { public static void main(String[] args) { File file=new File("F:/test.txt"); try(InputStream inputStream=new FileInputStream("F:/test.txt")) { while (true){ int ret=inputStream.read(); //返回-1,读到尾部 if(ret==-1) { break; } System.out.println(ret); } } catch (IOException e) { e.printStackTrace(); } } }
代码运行结果(ASCII码):
3.1.2 FileReader概述
该类是对字符流的读操作实现。
构造方法
代码使用FileReader类:
import java.io.*; public class ioDemo3 { public static void main(String[] args) { File file=new File("F:/test.txt"); try(Reader reader=new FileReader("F:/test.txt")) { while (true) { int r = reader.read(); if (r == -1) { break; } System.out.print((char)r); } } catch (IOException e) { e.printStackTrace(); } } }
代码运行结果:
观察得出,他是打印的字符,他是如何打印的呢?原理很简单,在读取数据时,系统会对比对照,我们设置什么字符集编码它就以什么字符集编码对比。
3.3输出流概述
写文件时使用的方法
2.3.1FileOutputStream概述
该类是字节流的写操作。
构造方法:
代码使用FileOutputStream类:
import java.io.*; public class ioDemo4 { public static void main(String[] args) { try (OutputStream outputStream=new FileOutputStream("F:/test.txt") ){ outputStream.write(1); outputStream.write(2); outputStream.write(3); } catch (IOException e) { e.printStackTrace(); } } }
代码会将1 2 3以二进制的形式写入到F:/test.txt这个目录中的test文件中。
3.3.2FileWriter概述
该类是字符流写操作
构造方法:
代码使用FileWriter类:
import java.io.*; public class ioDemo5 { /** * 文本写 * @param args */ public static void main(String[] args) { try(FileWriter fileWriter=new FileWriter("F:/test.txt")){ fileWriter.write(1); fileWriter.write(2); fileWriter.write("c"); } catch (IOException e) { e.printStackTrace(); } } }
代码会以文本的形式将 1,2,c写入文件test中。
4.文件io小练习
要求:扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
import java.io.*; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Scanner; public class ioDemo2 { /** * 查询一个字符是否存在这个目录 * @param args */ public static void main(String[] args) { Scanner sc=new Scanner(System.in); //1.输入搜索根目录 System.out.println("输入需要找到扫描的路径"); String findRootPath=sc.next(); File findRoot=new File(findRootPath); if(!findRoot.isDirectory()) { System.out.println("您选择的不是路径,退出"); return; } //2.输入需要查询的字符 System.out.println("输入需要找的字符"); String findStr=sc.next(); //3.递归进行目录遍历 scanDirWithContent(findRoot, findStr); } private static void scanDirWithContent(File findRoot, String findStr) { File[] files=findRoot.listFiles(); if(files.length==0 || files==null) { return; } for (File file:files) { //是目录 if(file.isDirectory()) { scanDirWithContent(file,findStr); //是文件 }else if(file.isFile()) { String content=readFile(file); if(content.contains(findStr)) { System.out.println(file.getAbsolutePath()+"包含字符"); } //其他文件 }else { continue; } } } /** * 找字符,对的拼接起来 * @param file * @return */ private static String readFile(File file) { StringBuilder sb=new StringBuilder(); try(Reader reader=new FileReader(file)){ while (true) { int read=reader.read(); if(read==-1) { break; } sb.append((char)read); } } catch (IOException e) { e.printStackTrace(); } return sb.toString(); } }