一.文件的定义
什么是文件?
文件分为狭义上的文件和广义上的文件
狭义上的文件:文件夹中的文件:包括视频、图片、文本、可执行文件等等......
其中有些文件是有后缀名的,而有一些文件是没有后缀名的
广义上的文件:在Linux系统中,所有的设备都是文件,包括键盘、网卡、硬盘.......
java中存在一个File类,通过File类创建出来的对象时java中的一个普通对象,这个文件对象在系统中不一定存在。
二.File类中常用的方法
①构造方法
②常用方法
三.文件内容的读写
我们可以观察发现:这些方法都是对文件信息进行操作:包括创建,查找,查看,删除,列表,重命名等等....,但是并没有对文件内容进行操作:对文件内容的读写则包括:(Input和Output)(读取和写出)
3.1流和数据输送:
数据传输的过程,我们可以抽象化为流传输(数据流)Stream的过程:通过下图进行理解:
我们进行文件的输入和输出的过程,我们可以理解为数据流传输的过程:比如是从原水池中传输水源到目标水池,我们中间通过缓冲站进行传输,其中,缓冲站的大小是我们可以自己定义的:比如我们传输100L的水,但是缓冲站大小为10L,那就需要分10次运输才能完成(10次IO),如果运输1000L,那么则需要100次运输才能完成
而计算机中关于这个模型的应用场景如下:
比如我们需要30G的内存加载到显示器,那么我们需要将内存先输入到内存,然后通过内存加载到显示器:而我们每次只能往内存中输入(Input)100M的数据,每次内存需要将这100M的数据输出(output)到显示器,再这样多次重复下,最终30G的电影最终被播放在显示器上
通过以上两个例子我们进行总结:对于计算机而言,输入和输出是相对于内存而言的,其它设备将数据送往内存叫数据的输入(input),内存将设备输送到别的地方叫数据的输出(output)。
在java中,将input和output提供了两个抽象类:InputStream(将数据输入到内存)和outPutStream(将数据从内存输出)
而系统中存在着不同类型的文件,包括:文本文件和二进制文件,针对不同的文件类型,java也提供了不同的处理类
①FileInputStream
我们有两种输入方式,一种是直接用int数据接收从文件中读取到的值,另一种是利用数组进行暂时储存
我们通过代码进行说明:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
/**
* @author tongchen
* @create 2023-02-12 21:48
*/
public class PutStream {
public static void main(String[] args) throws IOException {
//创建文件输入流
InputStream fileInputStream = new FileInputStream("D:/360安全浏览器下载/test/aa/bb/test.txt");
while(true){
//每次读一个二进制字符
int read = fileInputStream.read();
if(read==-1){
break;
}
System.out.print((char)read);
}
fileInputStream.close();
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @author tongchen
* @create 2023-02-12 21:53
*/
public class exer02 {
public static void main(String[] args) throws IOException {
//创建输入流对象
FileInputStream fileInputStream = new FileInputStream("D:\\360安全浏览器下载\\test\\aa\\bb\\test.txt");
//每次使用字符数组对的方式进行读取
byte[] reads=new byte[1024];
while(true){
int read = fileInputStream.read(reads);
if(read==-1){
break;
}
for (int i = 0; i <read ; i++) {
System.out.print((char) reads[i]);
}
}
}
}
当我们采用一个一个数据进行读取时,我们发现其源码给出的范围是:-1-255,这个二进制数字是对应着
ASCII码值的,一旦超出这个范围,就有可能出现乱码问题。(由于编码方式的问题,汉字采用的是utf-8的编码方式,ASCII码的编码方式无法对汉字进行输入和输出)
②FileOutputStream
写出的时候同样如此,我们既可以一个一个数据进行写入,同时我们也可以通过数组的方式进行写入
我们依然通过代码的方式对这两种方式进行举例:
public class exer03 {
public static void main(String[] args) throws IOException {
//创建文件输出流
FileOutputStream fileOutputStream = new FileOutputStream("D:\\360安全浏览器下载\\test\\aa\\bb\\test.txt");
//每次读入一个二进制文件
fileOutputStream.write(69);
fileOutputStream.write(70);
fileOutputStream.write(71);
//一定要注意的是:我们在写入时会将原来的数据全部清除
fileOutputStream.flush();
fileOutputStream.close();
}
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author tongchen
* @create 2023-02-12 22:04
*/
public class exer04 {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("D:\\360安全浏览器下载\\test\\aa\\bb/test.txt");
byte[]inserts=new byte[1024];
for (int i = 0; i <127 ; i++) {
inserts[i]=(byte) i;
}
fileOutputStream.write(inserts);
}
fileoutputStream.flush();
fileoutputStream.close();
}
我们在往文件中写入数据时,会将文件之前的内容进行覆盖。
写入的时候我们需要注意的一个点:flush()方法,该方法用于刷新缓存区:一般而言,我们每次进行write()操作,并不是直接将数据写入硬盘中,而是先写入缓存区(避免过多次数的IO,提高效率),将缓存区写满之后再将数据存入硬盘,但是很多情况下我们需要把数据立即写入硬盘,所以需要我们手动进行刷新,将缓存区中的数据写到硬盘中。
我们再介绍一个点:关于文件手动关闭的重要性:我们都知道的是,每个进程的启动都会开辟一些资源,其中有一项是文件描述符表,我们在操作进程时打开的任何文件都是一个文件描述符,会被存入文件描述符表,我们可以将文件描述符表理解为一个数组:如果我们仅仅只是不断地往数组中加元素(文件描述符),而不进行及时地销毁,那么必然无法避免一种情况的发生:文件描述符表被填满了,这时会导致进程卡死,这时只能通过重启进程来解决,这时会导致很多数据的丢失或者其他情况,问题很严重,所以我们需要在用完一个文件之后进行关闭(将文件在文件描述符表中删除)
在write()方法中我们虽然发现源码中没有对数值范围的限制,但是事实上当我们输出的字符一旦超过ASCII码的数值范围,编码格式就会发生改变,则会产生乱码等问题,所以一般我们很少直接使用二进制流的方式向文件中输入内容,而是使用print()使用字符串和指定编码格式进行输入,从而降低出现乱码问题的可能性。
③FileReader
filereader和filewriter都是基于字符的输入输出方式,通过这种方式我们可以进行汉字的输入和输出
我们通过代码将其的使用方式进行举例:
import java.io.FileReader;
import java.io.IOException;
/**
* @author tongchen
* @create 2023-02-12 22:10
*/
public class exer07{
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader("D:\\360安全浏览器下载\\test\\aa\\bb/test.txt");
char[] chars = new char[1024];
while(true){
int read = fileReader.read(chars);
if (read==-1){
break;
}
System.out.print(chars);
}
}
}
④FileWriter
我们通过代码将其的使用方式进行举例:
import java.io.FileWriter;
import java.io.IOException;
/**
* @author tongchen
* @create 2023-02-12 22:07
*/
public class exer05 {
public static void main(String[] args) throws IOException {
//创建字符写入流
FileWriter fileWriter = new FileWriter("D:\\360安全浏览器下载\\test\\aa\\bb/test.txt");
fileWriter.write("你爱我");
fileWriter.write("我爱你");
fileWriter.write("相亲相爱一家人");
fileWriter.flush();
fileWriter.close();
}
}
关于利用Scanner个和PrintWriter简化读写操作:
通过这两种方式依然可以实现对汉字的是输入和输出
public class PutStream {
public static void main(String[] args) throws IOException {
//创建文件输入流
InputStream fileInputStream = new FileInputStream("D:/360安全浏览器下载/test/aa/bb/test.txt");
Scanner scan=new Scanner(fileInputStream,"UTF-8");
System.out.println(fileInputStream.read());
//在文件中读取下一行
while(scan.hasNextLine()){
String s = scan.nextLine();
System.out.println(s);
}
scan.close();
fileInputStream.close();
}
}
public class exer03 {
public static void main(String[] args) throws IOException {
//创建文件输出流
FileOutputStream fileOutputStream = new FileOutputStream("D:\\360安全浏览器下载\\test\\aa\\bb\\test.txt");
PrintWriter printWriter = new PrintWriter(fileOutputStream);
//每次读入一个二进制文件
fileOutputStream.write(69);
fileOutputStream.write(70);
fileOutputStream.write(71);
//一定要注意的是:我们在写入时会将原来的数据全部清除
printWriter.println("hdsjhdak");
printWriter.println("死锁");
fileOutputStream.flush();
printWriter.flush();
printWriter.close();
fileOutputStream.close();
}
}