File类:
Java API:java.io.File 类 是用来操作文件或文件夹的,无法用来读写
1.首先创建一下file的对象:
里面可以写相对路径或者绝对路径
File file = new File("CCC.java");
也可以使用其他构造方法
//String path = "D:\\ch06";
//String fileName = "1.txt";
File file = new File(path);
或者
File file1 = new File(path,fileName);
File类常用方法:
只有file对象才能够使用下面这些方法,字符串是不可以的(例如path.exsit是错误的)
代码示例:
这里的 isDirectory() 也可以判断这个file是否存在,不存在也返回false
isFile()也同理
public static void main(String[] args) throws IOException {
String path = "D:\\ch06";
String fileName = "1.txt";
File file = new File(path);
File file1 = new File(path,fileName);
if (!file.exists()&&!file.isDirectory()){
//没有就重新创建
file.mkdirs();//加上s就是创建多级
System.out.println("创建文件夹成功");
}
if (!file1.exists()&&!file1.isFile()){
file1.createNewFile();
System.out.println("创建成功");
}
System.out.println("判断文件或目录是否存在:"+file.exists());
System.out.println("只有file对象才能使用exists方法"+file1.exists());
System.out.println("判断是否是文件夹"+file.isFile());
System.out.println("判断是否是目录"+file.isDirectory());
System.out.println("file1的相对路径"+file1.getPath());
System.out.println("file的相对路径"+file.getPath());
System.out.println("它的绝对路径"+file.getAbsolutePath());
System.out.println("获得文件或目录名称"+file.getName());
System.out.println("获得文件字节数"+file.length());
System.out.println("删除文件或目录"+file.delete());
}
流:
java如何读写文件?:通过流
流是一组有序的数据序列以先进先出方式发送信息的通道
Java流的分类:
1.按照流向区分
输入流和输出流
对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。
2.按照处理数据单元划分
字符流和字节流
字节流是8位通用字节流,字符流是16位Unicode字符流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。字节流和字符流的区别:
(1)读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
(3)字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的;而字符流在操作的时候下后是会用到缓冲区的,是通过缓冲区来操作文件,我们将在下面验证这一点。
结论:优先选用字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。
字节流概述(InputStream和OutputStream):
InputStream被看成一个输入管道,OutputStream被看成一个输出管道,数据通过InputStream从源设备输入到程序,通过OutputStream从程序输出到目标设备,从而实现数据的传输。由此可见,I/O流中的输入/输出都是相对于程序而言的。
InputStream类(读取文件):
常用方法:
第一个read()方法是从输入流中逐个读入字节,而第二个和第三个read()方法则将若干字节以字节数组的形式一次性读入,从而提高读数据的效率。
方法 | 方法描述 |
int read( ) | 从输入流读取一个8位的字节,把它转换为0~255之间的整数,并返回这一整数。当没有可用字节时,将返回-1 |
int read(byte[] b) 装字节数组 | 从输入流读取若干字节,把它们保存到参数b指定的字节数组中,返回的整数表示读取字节的数目 |
int read(byte[] b,int off,int len) | 从输入流读取若干字节,把它们保存到参数b指定的字节数组中,off指定字节数组开始保存数据的起始下标,len表示读取的字节数目 |
void close( ) | 关闭此输入流并释放与该流关联的所有系统资源 |
int available(); | 获取当前流中可用的字节数。 |
字节流读取文件内容:
问题1:为什么把默认的throw new RuntimeException(e);都变成e.printStackTrace():
答:
e.printStackTrace();
如果你的主要目标是确保程序继续运行,并记录发生的异常。
throw new RuntimeException(e);
如果你希望在资源清理过程中发生异常时,中断程序以确保异常得到处理。
问题2:
要确保记事本的编码和idea的编码一致传过来才不报错,不然会乱码,原因是:
如果你用 GBK 编码保存文件,而 IntelliJ IDEA 使用 UTF-8 解码,那么字节会被错误地解释成字符,导致显示为乱码。(GBK用两个字节表示一个中文和英文,UTF-8用三个字节表示中文一个自己表示英文)
步骤:
1.创建FileInputStream输入流文件对象
2.获得文件内容:is.available()获取的文件放在数组中
3.使用read方法读取字节数组
4.将字节数组转为字符串,通过String str = new String(b,"GBK"); 将字节数组转换为字符串可以使数据更具可读性。
public static void main(String[] args) {
//读取文件
InputStream is = null;
try {
is = new FileInputStream("D:\\ch06/1.txt");
byte b[] = new byte[is.available()];
//available()可获得的文件字节数
is.read(b);
//将字节数组转为字符串
String str = new String(b,"GBK");
System.out.println(str);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
子类FileInputStream常用的构造方法:
第一种:FileInputStream(File file)
File file1 = new File("D:\\ch06/1.txt");
InputStream is = new FileInputStream(file1);
第二种:FileInputStream(String name)
放String路径
String str1 = "D:\\ch06/1.txt";
InputStream is = new FileInputStream(str1);
InputStream is2 = new FileInputStream( "D:\\ch06/1.txt");
OutputStream类(写入文件):
常用方法:
第一个方法逐个写入字节,后两个方法是将若干个字节以字节数组的形式一次性写入,从而提高写数据的效率。
方法 | 描述 |
void write(int c) | 向输出流写入一个字节 |
void write(byte[] buf) 放字节数组 | 把参数b指定的字节数组的所有字节写到输出流 |
void close() | 刷新此输出流并强制写出所有缓冲的输出字节 |
void flush(): 这个后面讲 | 强制把缓冲区的数据写到输出流中 |
字符串对象.getBytes() |
|
将字符串写入文件:
步骤:
1.首先创建OutputStream对象
2.写出要写入的字符串
3.使用getBytes()方法将字符串转为字节数组mag.getBytes()
3.使用write方法读取字符串 os.write(mag.getBytes());
public static void main(String[] args) throws IOException {
String str1 = "D:\\ch06/1.txt";
OutputStream os = new FileOutputStream(str1,true);
String mag = "蛋蛋怪嘎达嘎达";
//将字符串转为字节数组
//mag.getBytes()
os.write(mag.getBytes());
System.out.println("写入成功");
os.close();
}
子类FileOutputStream常用的构造方法:
1.直接放文件
OutputStream os = new FileOutputStream( "D:\\ch06/1.txt");
2.直接放路径字符串
String str1 = "D:\\ch06/1.txt";
OutputStream os = new FileOutputStream(str1);
3.可以在后面追加
String str1 = "D:\\ch06/1.txt";
OutputStream os = new FileOutputStream(str1,true);
1.前两种构造方法在向文件写数据时将覆盖文件中原有的内容,因为前两种默认append是false
2.创建FileOutputStream实例时,如果相应的文件并不存在,则会自动创建一个空的文件
FileInputStream和 FileOutputStream文件的拷贝:
while循环将字节逐个进行拷贝。每循环一次,就通过FileInputStream的read()方法读取一个字节,并通过FileOutputStream的write()方法将该字节写入指定文件,循环往复,直到读取的长度len的值为-1,表示读取到了文件的末尾,结束循环,完成文件的拷贝。
public static void main(String[] args) throws Exception {
// 创建文件输入流对象读取指定目录下的文件
FileInputStream in = new FileInputStream("source/src.png");
// 创建文件输出流对象将读取到的文件内容写入到指定目录的文件中
FileOutputStream out = new FileOutputStream("target/dest.png");
// 定义一个int类型的变量len
int len = 0;
// 获取拷贝文件前的系统时间
long beginTime = System.currentTimeMillis();
// 通过循环将读取到的文件字节信息写入到新文件
while ((len = in.read()) != -1) {
out.write(len);
}
// 获取拷贝之后的系统时间
long endTime = System.currentTimeMillis();
// 输出拷贝花费时间
System.out.println("花费时间为:"+(endTime-beginTime) +"毫秒");
// 关闭流
in.close();
out.close();
}
字符流(Reader和Writer):
InputStream类和OutputStream类在读写文件时操作的都是字节,如果希望在程序中操作字符,使用这两个类就不太方便了
同字节流一样,字符流也有两个抽象的顶级父类,分别是Reader和Writer。其中Reader是字符输入流,用于从某个源设备读取字符。Writer是字符输出流,用于向某个目标设备写入字符。
其中FileReader和FileWriter用于读写文件,BufferedReader和BufferedWriter是具有缓冲功能的流,使用它们可以提高读写效率。
InputStramReader输入流(读取):
Reader——>InputStreamReader(字节流InputStream,编码)——>FileReader(路径||"编码")
InputStream——>FileInputStream
乱码问题:
因为FileInputStream是InputStream的子类,所以可以直接在InputStreamReader中new
reader = new InputStreamReader(new FileInputStream("D:\\ch06/1.txt"),"utf-8");
读取只能读字符数组,输出只能输出字符串
所以读完数组之后,把数组转成字符串
1.使用InputStreamReader读取文件:
public static void main(String[] args) {
Reader reader = null;
try {
reader = new InputStreamReader(new FileInputStream("D:\\ch06/1.txt"));//这里面也可以放file对象);
char c[] = new char[100];
//因为这个时候无法确定读取长度,就随便设一个长度
reader.read(c);
String msg = new String(c);
System.out.println(msg);
reader. close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
2.使用FileReader读取文件:
public static void main(String[] args) {
try {
Reader reader = null;
reader = new FileReader("D:\\ch06/1.txt");
char c[] = new char[100];
reader.read(c);
//把字符数组转为字符串
String msg = new String(c);
System.out.println(msg);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
BufferReader缓冲区读取数据:
因为使用read()方法会频繁读取输入流,压力太大了,所以用缓冲区来减小压力
子类BufferedReader特有的方法:
我们可以用BufferReader的.readLine()方法用来读取一行
public static void main(String[] args) {
Reader reader = null;
BufferedReader br = null;
try {
reader = new InputStreamReader(new FileInputStream("D:\\ch06/1.txt"));
br = new BufferedReader(reader);
String msg = null;
while ((msg = br.readLine())!=null){
System.out.println(msg);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
输出流OutputStramReader(写入):
Writer——>OutputStreamWriter(字节流OutputStream,编码)——>FileWriter(路径||File对象,append)
OutputStream——>FileOutputStream
weite(字符串) 写入方法
close() 释放资源
flush() 刷新缓冲区
直接write方法就写进去了,不需要什么数组
1.使用FileWriter写入文本:
public static void main(String[] args) {
//输出流
Writer writer = null;
try {
writer = new FileWriter("D:\\ch06/1.txt",true);
//写入
writer.write("我是新写入的内容,不覆盖你好蛋蛋怪");
} catch (IOException e) {
e.printStackTrace();
}
try {
writer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
2.使用OutputStreamWriter写入文本:
public static void main(String[] args) {
//OutputStreamWriter写
Writer writer = null;
try {
writer = new OutputStreamWriter(new FileOutputStream("D:\\ch06/1.txt"),"utf-8");
writer.write("你好蛋蛋怪");
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferWriter缓冲区读取数据:
减少直接对磁盘的写入次数,从而提升性能。写入的数据首先被存储在缓冲区中,只有当缓冲区满了或者调用了 flush()
方法时,数据才会实际写入文件。
子类BufferedWriter的方法:
flush(); 强制将缓冲区中的所有数据写入到目标流或文件中
bw.newLine();换行
public static void main(String[] args) {
Writer writer = null;
BufferedWriter bw = null;
try {
writer = new FileWriter("D:\\ch06/1.txt");
bw = new BufferedWriter(writer);
bw.write("嘎嘎小啾啾");
bw.newLine();
bw.write("鳞斑响尾蛇");
bw.newLine();
bw.write("啾啾小啾啾");
//强制将缓冲区中的所有数据写入到目标流或文件中
bw.flush();
System.out.println("写入成功");
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
bw.close();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}