CSDN话题挑战赛第2期
参赛话题:Java技术分享
文章目录
文件
文件的概念
文件,就是存储在硬盘上的,用来保存数据的一个抽象出来的独立的单位;
文件的路径
文件的路径一般而言有:
- 绝对路径:从文件的根目录开始,一直到达文件本身的路径;一般都带有盘符;
- 相对路径:从任意的目录开始,到达当前文件本身的路径;
通过文件的路径,我们可以快速定位文件在系统中的位置;
文件的分类
一般,根据文件保存数据的不同,我们将文件分为:
- 二进制文件:没有被字符集编码过的文件,规则复杂;
- 文本文件:被字符集编码过的文件,规则简单;
文本文件和二进制文件都是存储的二进制0和1,但由于编码情况的不同而存在差异;
文件系统
文件同样也是被操作系统所管理的,在操作系统内核中用来专门管理文件的模块,就被称为文件系统;
java也针对文件进行了一系列的封装,有助于我们更加方便地进行文件操作,即File类;
File的构造方法
import java.io.File;
public class demo1 {
public static void main(String[] args) {
//File(String pathname) 根据文件路径创建一个新的 File 实例;
File file1=new File("d:/test.txt");
//File(File parent, String child) 根据父目录 + 孩子文件路径,创建一个新的 File 实例
File file2=new File("d:/tmp","./tmp/test");
}
}
使用File类,需要引入包: java.io.File;
File类的构造方法创建实例时的路径可以是绝对路径或者相对路径;
构造方法是创建了一个File对象的实例,有File对象,不代表文件真正存在;
File类的基本方法
- 访问文件的基本属性:
public static void main(String[] args) {
//File(String pathname) 根据文件路径创建一个新的 File 实例;
File file1=new File("./test.txt");
//返回对象的父目录文件路径
System.out.println(file1.getParent());
//返回对象的文件名称
System.out.println(file1.getName());
//返回对象的文件路径
System.out.println(file1.getPath());
//判断对象描述的文件是否存在
System.out.println(file1.exists());
//返回对象的绝对路径
System.out.println(file1.getAbsolutePath());
}
- 文件的创建;
import java.io.File;
import java.io.IOException;
public class demo1 {
public static void main(String[] args) throws IOException {
//File(String pathname) 根据文件路径创建一个新的 File 实例;
File file1=new File("./test.txt");
//判断对象描述的文件是否存在
System.out.println(file1.exists());
//判断对象描述的文件是否是一个普通文件
System.out.println(file1.isFile());
//根据对象自动创建一个空白文件,创建成功返回true;
System.out.println(file1.createNewFile());
System.out.println(file1.exists());
System.out.println(file1.isFile());
System.out.println(file1.getAbsolutePath());
}
}
此时,一个文件真正创建成功:
- 文件的删除;
import java.io.File;
import java.io.IOException;
public class demo1 {
public static void main(String[] args) throws IOException {
File file1=new File("./test2.txt");
System.out.println(file1.exists());
System.out.println(file1.createNewFile());
System.out.println(file1.exists());
System.out.println(file1.delete());
System.out.println(file1.exists());
}
}
delete() 根据 File 对象,删除该文件。成功删除后返回 true;
public static void main(String[] args) throws IOException {
File file1=new File("./test2.txt");
System.out.println(file1.exists());
System.out.println(file1.createNewFile());
System.out.println(file1.exists());
//程序退出时删除
file1.deleteOnExit();
System.out.println(file1.exists());
}
- 目录的创建;
import java.io.File;
import java.io.IOException;
public class demo1 {
public static void main(String[] args) throws IOException {
File file1=new File("tmp/test.txt/123");
System.out.println(file1.exists());
System.out.println(file1.isDirectory());
//创建目录
System.out.println(file1.mkdir());
//创建目录,同时创建中间目录
System.out.println(file1.mkdirs());
System.out.println(file1.exists());
}
}
使用mkdir()创建目录时,如果中间目录不存在,则无法创建成功;使用mkdirs()则可以同时创建中间目录;
文件读写
文件内容的读写,实际就是一种数据流方式的过程;而所谓的数据流,是指连续而不是分批发送数据记录的过程;
Java中对文件的读写有提供专门的类,即InputStream与OutputStream,以及Reader与Writer;
InputStream
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class demo1 {
public static void main(String[] args) throws IOException {
File file=new File("./test.txt");
file.createNewFile();
System.out.println(file.getAbsolutePath());
InputStream inputStream=null;
//打开文件
inputStream=new FileInputStream("test.txt");
//读取文件
while (true){
int a=inputStream.read();
if (a==-1){
break;
}
System.out.println(a);
}
//关闭文件
inputStream.close();
}
}
执行上述代码时,必须首先使文件存在,同时在文件中写入一定的内容,例如:
运行结果:
上面的运行结果是hello的ASCII码的十进制表示形式;
由于InputStream不能直接实例化(被abstract修饰),因此借助子类FileInputStream来完成;
我们使用read()来读取文件的内容,而read()方法也提供了多种形式来读取:
第一种形式即一次读取一个字节,一般借助循环读取,上面代码即采用了这种形式;
//读取文件
byte [] b=new byte[1024];
int len=inputStream.read(b);
System.out.println(len);
for (int i=0;i<len;i++){
System.out.println(b[i]);
}
第二种形式是借助数组完成;
public static void main(String[] args) throws IOException {
File file=new File("./test.txt");
file.createNewFile();
System.out.println(file.getAbsolutePath());
InputStream inputStream=null;
//打开文件
inputStream=new FileInputStream("test.txt");
//读取文件
byte [] b=new byte[1024];
int len=inputStream.read(b);
String s=new String(b,0,len);
System.out.println(s);
//关闭文件
inputStream.close();
}
第三种形式是:对数组中的内容,从off下标的位置开始读取,读取len的长度;
当文件中的内容为中文时,为了避免乱码,可以在第三个参数之后继续指明字符的编码方式,即 String s = new String(b, 0, len, “UTF-8”);
inputStream的作用,实际是相对于一个“遥控器”的作用,因为文件是存储在硬盘,而直接操作硬盘无疑是困难的,因此我们再内存中构造一个与文件关联的对象即inputStream,通过操作这个对象来实现操作文件的目的;在计算机中,充当“遥控器”功能的对象,我们称其为“句柄”;
在读取文件结束之后,关闭文件的操作是很重要的;简单来说,及时关闭文件可以释放资源。除此之外,是由于文件描述表的存在,文件描述表是PCB中的一个属性,它是一个顺序表的结构,每个元素代表着一个当前进程打开的文件,而每个元素的下标就被称为“文件描述符”,因此每一个打开的文件,在文件描述表中都占据着一个位置,由于文件描述表是有一定容量限制的,如果只是一味地打开文件,而不及时进行关闭,自然就会出现最终无法打开其他文件的情况;另外,打开文件之后忘记关闭,还会引起文件资源的泄露,由于这个泄露是一个逐渐泄露的过程,可能无法及时察觉到这个泄露,自然就带来了更大的安全隐患;因此在打开文件之后一定要及时关闭文件;
为了我们上面代码的完整性和安全性,我们可以做这样的改进:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class demo1 {
public static void main(String[] args) throws IOException {
File file=new File("./test.txt");
file.createNewFile();
InputStream inputStream=null;
try{
//打开文件
inputStream=new FileInputStream("test.txt");
//读取文件
byte [] b=new byte[1024];
int len=inputStream.read(b);
String s=new String(b,0,len);
System.out.println(s);
}catch(IOException e){
e.printStackTrace();
}finally {
try{
//关闭文件
inputStream.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
为核心代码加上try-catch的操作,在文件没有及时关闭时抛出异常;
除此之外,还有一种更加方便同时稳妥的方法:
public class demo1 {
public static void main(String[] args) throws IOException {
File file=new File("./test.txt");
file.createNewFile();
try(InputStream inputStream=new FileInputStream("test.txt")){
//打开文件
//读取文件
byte [] b=new byte[1024];
int len=inputStream.read(b);
String s=new String(b,0,len);
System.out.println(s);
}catch(IOException e){
e.printStackTrace();
}
}
}
这种写法,会在try执行结束之后,自动调用inputStream的close方法;这是一种try with resources的操作,对于实现了Closeable接口的类,都可以进行这样的操作;
上面使用InputStream进行读取实际是字节流的方式,我们还可以使用字符流的方式来读取:
Reader
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class demo2 {
public static void main(String[] args) throws IOException {
Reader reader=new FileReader("test.txt");
char [] buffer=new char[1024];
int len=reader.read(buffer);
for (int i=0;i<len;i++){
System.out.println(buffer[i]);
}
reader.close();
}
}
顾名思义,字符流就是以字符为单位的流,一般用来操作文本文件;
Scanner
上面的例子中,使用InputStream进行读取略显繁琐,因此我们尝试使用Scanner类来解决:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
public class demo3 {
public static void main(String[] args) throws IOException {
InputStream inputStream=new FileInputStream("test.txt");
Scanner scanner=new Scanner(inputStream);
String s=scanner.next();
System.out.println(s);
inputStream.close();
}
}
OutputStream
使用OutputStream的writer()方法进行字符写入,writer()同样提供了多种形式:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
public class demo4 {
public static void main(String[] args) {
try(OutputStream outputStream=new FileOutputStream("test.txt")) {
//write (int b)
outputStream.write('h');
outputStream.write('e');
outputStream.write('l');
outputStream.write('l');
outputStream.write('o');
String s="happy everyday";
outputStream.write(s.getBytes());
//write(byte[] b)
byte[] str=new byte[]{'g','o','o','d'};
outputStream.write(str);
//write(byte[] b,int off,int len)
int len=str.length;
outputStream.write(str,0,len);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Writer
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class demo5 {
public static void main(String[] args) {
try (Writer writer = new FileWriter("test.txt")) {
writer.write("hello world");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Writer写入字符的方式同样是字符流的方式;
PrintWriter
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
public class demo6 {
public static void main(String[] args) {
try(OutputStream outputStream=new FileOutputStream("test.txt")){
PrintWriter printWriter=new PrintWriter(outputStream);
printWriter.println("hhhhhhhhhhh");
}catch (IOException e){
e.printStackTrace();
}
}
}
PrintWriter 类同样可以完成输出,PrintWriter 类也提供了输出不同形式结果的方法 ,即print/println/printf ;
over!