一:文件
什么是文件? 文件对于我们来说并不陌生,文件是保存数据的地方,比如word文档,excel文件....它既可以保存图片,也可以保存视频......
Thompson的文件系统有两个重要的概念,分别是:
所有的程序或系统装置都是文件
不管建构编辑器还是附属文件,所写的程序只有一个目的,且要有效的完成目标。
文件流
文件在程序中是通过流的形式来操作的。
流:数据在数据源(文件)与程序(内存)之间的路经。可以拿外卖物流类似,包裹类似文件,物流类似文件流。
常见的文件操作
创建文件对象相关构造器和方法
new File(String pathname)//根据路径构建一个File对象
new File(File parent,String child) //根据父目录文件+子路径构建
new File(String parent,String child) //根据父目录+子路径构建
createNewFile 创建新文件 //构造器仅仅创建了对象,并没有在硬盘中创建文件
public class Wen {
public static void main(String[] args) throws IOException {
//1、创建文件对象 new File(String pathname)//根据路径构建一个File对象
File file1 = new File("D:\\test1.txt");
//2、new File(File parent,String child) //根据父目录文件+子路径构建
File parentfile = new File("D:/");
File file2 =new File(parentfile,"test2.txt");
//3、new File(String parent,String child) //根据父目录路径+子路径构建
File file3 = new File("D:/","test3.txt");
//构造器仅仅创建了对象,并没有在硬盘中创建文件
file1.createNewFile();
file2.createNewFile();
file3.createNewFile();
}
}
获取文件信息操作
//获取文件信息
System.out.println("文件名:"+file1.getName());
System.out.println("文件绝对路径:"+file1.getAbsolutePath());
System.out.println("文件父级目录:"+file1.getParent());
System.out.println("文件是否存在:"+file1.exists());
System.out.println("文件是否可读:"+file1.canRead());
System.out.println("文件是否可写:"+file1.canWrite());
System.out.println("文件是否隐藏:"+file1.isHidden());
System.out.println("文件是否是目录:"+file1.isDirectory());
System.out.println("文件是否是文件:"+file1.isFile());
System.out.println("文件长度:"+file1.length());
System.out.println("文件最后修改时间:"+file1.lastModified());
System.out.println("=======================================");
运行结果:
文件名:test1.txt
文件绝对路径:D:\test1.txt
文件父级目录:D:\
文件是否存在:true
文件是否可读:true
文件是否可写:true
文件是否隐藏:false
文件是否是目录:false
文件是否是文件:true
文件长度:0
文件最后修改时间:1715436615002
=======================================
目录的操作和文件删除
//创建一级目录
File dir1=new File("D:/dir1"); //创建一级目录对象
dir1.mkdir(); //真正在磁盘创建一级目录
//创建多级目录
File dir2=new File("D:/dir2/dir3");
dir2.mkdirs();
//删除文件
dir2.delete(); //删除了dir2目录下的所有文件,但不会删除dir2目录本身
二:IO流原理及流的分类
Java IO流原理
I/O是Input/Output的缩写。I/O技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等。
Java程序中,对于数据的输入/输出操作以"流(stream)" 的方式进行。 java.io包下提供了各种"流"类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中
输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中
流的分类
按操作数据的单位不同分为:字节流(8 bit 0~255),字符流(按字符) 按数据流的流向不同可以分为:输入流,输出流 按流的角色的不同可以分为:节点流,处理流/包装流(对节点流的处理和保证,以加强IO)
抽象基类 | 字节流 | 字符流 |
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
Java的io流共涉及40多个类,实际上非常规则,都是以4个抽象基类派生的
由这四个类派生出来的子类名称都是以其父类名作为子类名后缀
常见的类
FileInputStream
FileInputStream是 Java 中用于从文件中读取数据的输入流类。它允许程序以字节为单位从指定文件中读取数据。通过创建FileInputStream对象并调用相关方法,可以逐字节地读取文件内容,进行数据处理等操作。
FileInputStream有以下一些常见的构造方法:
FileInputStream(File file):通过指定的File对象来创建输入流。
FileInputStream(String pathname):通过指定文件的路径字符串来创建输入流。FileInputStream主要有以下一些常用方法:
int read():从输入流中读取一个字节的数据。
int read(byte[] b):从输入流中读取一定数量的字节到字节数组中,返回长度。
available():返回可以从该输入流中读取的剩余字节数的估计值。
close():关闭此输入流并释放与该流关联的任何系统资源。
public class FIS {
public static void main(String[] args) throws IOException {
FileInputStream fis1 =new FileInputStream(new File("src\\hello.txt"));
FileInputStream fis2 =new FileInputStream(new File("src\\hello.txt"));
//读取文件方式一:int read() 返回读取的字节
int read=0;
while((read=fis1.read())!=-1){
System.out.print((char)read);
}
fis1.close();
//读取文件方式二:int read(byte[] b) 返回读取的字节数
int readLen=0;
byte[] b=new byte[1024];
while((readLen=fis2.read(b))!=-1){
System.out.println(new String(b,0,readLen));
}
fis2.close();
}
}
FileOutStream
FileOutputStream是 Java 中用于向文件写入数据的类。它可以将数据以字节流的形式写入指定的文件。通过创建FileOutputStream对象,并调用其方法,如write()来将字节数据写入文件。这在需要将数据持久化到文件中时非常有用。
FileOutputStream类提供了多种方法用于向文件写入数据,以下是一些常见的方法:
write(int b):写入一个字节到文件。
write(byte[] b):将一个字节数组写入文件。
write(byte[] b, int off, int len):从字节数组的指定位置开始,写入指定长度的字节到文件。
close():关闭输出流,释放相关资源。
这些方法帮助字节数据写入文件中。在使用FileOutputStream时,还需要注意以下几点:
创建FileOutputStream对象时,可以指定文件的路径和模式(如覆盖或追加)。
在写入数据后,建议使用close()方法关闭输出流,以释放相关资源。
如果需要写入字符串或其他类型的数据,可以先将其转换为字节数组再进行写入。
处理文件操作时,需要处理可能出现的异常,如文件不存在、权限问题等。
class Fos{
File file;
FileOutputStream fos;
Fos() throws FileNotFoundException {
file = new File("C:\\Users\\86186\\IdeaProjects\\u\\Market\\src\\hello.txt");
try {
fos = new FileOutputStream(file,true); // true表示追加写入, false表示覆盖写入
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void fosTest(){
try {
//写入方法一:write(int b):写入一个字节到文件。
fos.write('h');
fos.write('e');
fos.write('l');
fos.write('l');
fos.write('o');
//写入方法二:write(byte[] b):写入一个字节数组到文件。
//String类中的getBytes()方法可以获取到字符串对应的字节数组。
byte[] bytes = "hello".getBytes();
fos.write(bytes);
//写入方法三:write(byte[] b, int off, int len):写入一个字节数组的一部分到文件。 off:起始位置,len:写入长度
fos.write(bytes, 0, 3);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fos.close(); // 关闭流, 释放资源,只有关闭流, 才能保证数据全部写入到文件,因为默认情况下,流是缓冲的,缓冲区满了才会写入文件
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) throws FileNotFoundException {
Fos fos = new Fos();
fos.fosTest();
}
}
FileReader
FileReader类主要用于从文件中读取字符数据。它是一个字符输入流,继承自InputStreamReader(转换流),抽象基类为Reader。可以通过构造方法传入文件路径来创建
FileReader的构造方法主要有以下几种:
FileReader(File file):创建一个与指定文件对象相关联的FileReader。
FileReader(String fileName):创建一个与指定文件路径名相关联的FileReaderFileReader类的一些主要方法包括:
int read():从输入流中读取一个字符,返回该字符的整数表示(到达文件末尾返回 -1)
int read(char[] cbuf):将字符读入数组。返回读取的长度
void close():关闭该流并释放与之关联的所有资源。相关API:
String(char[]) 将字符数组转换成StringString(char[],int off,int len)
public class FR {
public static void main(String[] args) {
FR fr = new FR();
try {
fr.readFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readFile() throws IOException {
FileReader fr = new FileReader("C:\\Users\\86186\\IdeaProjects\\u\\Market\\src\\hello.txt");
// 读取文件方式一:int read():从输入流中读取一个字符,返回该字符的整数表示(到达文件末尾返回 -1)
int date = 0;
while ((date = fr.read())!= -1) {
System.out.print((char) date);
}
fr.close(); // 这里要关闭,否则下面再次读取会出错
// 在这个例子中,FileReader对象不能重复使用是因为每次读取文件时,需要重新创建一个新的FileReader对象。
// 当使用FileReader对象读取文件时,它会将文件的指针移动到文件的末尾,导致无法再次读取相同的文件。
// 为了解决这个问题,可以通过创建一个新的FileReader对象来读取相同的文件。
// 代码中,第一次读取文件时创建了一个FileReader对象fr,并在读取完成后关闭了它。
// 然后,在第二次读取文件时,你继续使用已经关闭的fr对象,这就导致了异常。
// 修改后的代码中,在第二次读取文件时,重新创建了一个FileReader对象fr2,
// 并使用它来读取文件,这样就可以避免异常的发生。
// 读取文件方式二:int read(char[] cbuf):从输入流中读取一定数量的字符,并将它们存储到字符数组 cbuf 中
char[] cbuf = new char[1024];
while ((date = fr.read(cbuf))!= -1) {
System.out.print(new String(cbuf, 0, date));
}
fr.close(); // 最后还要关闭
}
}
FileWriter
FileWriter类用于将字符数据写入文件。它的构造方法可以接受一个文件对象或文件路径作为参数,以便指定要写入的文件。FileWriter提供了一些方法来写入字符数据,如write()方法可以写入单个字符或字符数组。此外,还可以使用flush()方法刷新缓冲区,将数据写入文件,以及使用close()方法关闭文件并释放相关资源。
FileWriter类提供了以下一些常用的方法:
write(int c):写入单个字符到文件中。
write(char[] cbuf):将字符数组写入文件中。
write(String str):写入字符串到文件中。
write(String str, int off, int len):写入字符串的一部分到文件中。
flush():刷新缓冲区,将数据写入文件。
close():关闭文件并释放相关资源。
public class FW {
public static void main(String[] args)
{
try {
new FW().writeFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeFile() throws IOException {
FileWriter fw = new FileWriter("C:\\Users\\86186\\IdeaProjects\\u\\Market\\src\\hello.txt");
// 写入数据方式一:write(int c):写入单个字符到文件中。
fw.write('h');
fw.write('e');
fw.write('l');
fw.write('l');
fw.write('o');
fw.write('\n');
// 写入数据方式二:write(char[] cbuf):写入字符数组到文件中。
char[] cbuf =new char[]{'h','e','l','l','o','\n'};
String str = "你好\n";
char[] charArray = str.toCharArray(); // 字符串转字符数组
fw.write(cbuf);
fw.write(charArray);
fw.close(); // 关闭流 释放资源 才能写入文件当中
}
}
运行结果 :
hello
hello
你好
节点流与处理流
在 Java 中,节点流和处理流是输入/输出(I/O)流的两种主要类型。
节点流(Node Stream):节点流是直接与数据源或目的地进行连接的流。它可以从数据源读取数据或向目的地写入数据。常见的节点流包括文件流(FileInputStream、FileWriter)、字节流(ByteArrayInputStream、ByteArrayOutputStream)等。
处理流(Processing Stream):处理流是对节点流进行包装或处理的流[修饰器设计模式]。它不直接与数据源或目的地连接,而是在节点流的基础上提供了更高级的功能,如缓冲、过滤、转换等。常见的处理流包括缓冲流(BufferedReader、BufferedWriter)、过滤器流(FilterReader、FilterWriter)等。
处理流的主要作用包括:
1.性能优化:通过缓冲数据,可以减少 I/O 操作的次数,提高数据读取和写入的效率。
2.数据处理:可以对数据进行过滤、转换、加密等处理,使数据符合特定的需求。
3.增强功能:处理流可以提供一些额外的功能,如换行处理、字符编码转换等,使 I/O 操作更加方便和灵活。
节点流和处理流的关系是:
节点流处于 I/O 操作的第一线,所有的操作都必须通过节点流进行;处理流则是对节点流的进一步封装和处理,以提供更强大的功能和更好的性能。
在实际应用中,通常会根据具体的需求选择使用节点流或处理流。如果需要直接与数据源或目的地进行交互,可以使用节点流;如果需要对数据进行处理或优化,可以使用处理流。同时,也可以根据需要将多个处理流组合使用,以实现更复杂的 I/O 操作。
BufferedInputStream
BufferedInputStream是Java IO库中的一个类,它提供了对输入流的缓冲处理。当从输入流中读取数据时,缓冲区会在后台将数据预先读取到缓冲区中,以便提高读取性能。
BufferedInputStream有以下一些常见构造方法:
1.BufferedInputStream(InputStream in):创建一个带有默认缓冲区大小的缓冲输入流,关联到指定的输入流in。
2.BufferedInputStream(InputStream in, int size):创建一个具有指定缓冲区大小的缓冲输入流,关联到指定输入流in。
对象流
在 Java 中,对象流用于将对象写入到输出流中,或从输入流中读取对象。 对象流使用ObjectOutputStream和ObjectInputStream类来实现。
1.ObjectOutputStream类用于将对象写入到输出流中。它实现了java.io.OutputStream接口,并提供了将对象写入流的方法。ObjectOutputStream类的构造函数接受一个OutputStream对象作为参数,用于指定要写入的输出流。
2.ObjectInputStream类用于从输入流中读取对象。它实现了java.io.InputStream接口,并提供了从流中读取对象的方法。ObjectInputStream类的构造函数接受一个InputStream对象作为参数,用于指定要读取的输入流。