javaio流总结
File类介绍
1.File类的理解:
- file类的一个对象,代表了一个文件或者文件夹
- file类声明在java.io包下
- file类涉及到文件或者目录的创建,删除,重命名,查看等方法,并未涉及到写入或者读取文件内容的操作,如果需要写入或者读取需要通过io流来完成
- 后续file类的对象常作为参数传递到流的构造器中,指明读取或写入的终点
2.File类的实例化
-
常用的构造器
File(String filePath)
File(String parentPath,String childPath)
File(File parentFile,String childPath)
-
路径的分类
相对路径:相较于某个路径下,知名的路径
绝对路径:包含盘符在内的文件或者文件夹路径
-
路径分隔符
windows和dos系统默认使用"\"来表示
unix和url使用"/"来表示
3.File类中的一些常用方法
public String getAbsolutePath()//获取绝对路径
public String getPath()//获取路径
public String getName()//获取名称
public string getParent()//获取上层文件目录路径,若无返回null
public long length()//获取文件长度(即:字节数),不能获取目录的长度
public long lastModified()//获取最后一次修改的时间,毫秒值
public String[] list()//获取指定目录下的所有文件或者文件目录的名称数组
public boolean renameTo(File dest)//把文件重命名为指定的文件路径
public boolean isDirectory()//判断是否是文件夹
public boolean isFile()//判断是否是文件
public boolean exists()//判断是否存在
public boolean canRead()//判断是否可读
public boolean canWrite()//判断是否可写
public boolean isHidden()//判断是否隐藏
public boolean createNewFile()//创建文件
public boolean mkdirs()//创建目录
public boolean delete()//删除文件或者目录,如果是删除目录,那么目录下不能有文件或者文件夹
IO流介绍
io流是什么:i代表input输入,o代表output输出
输入输出流的意思:Java程序进行数据传输的管道,这个流就是管道的意思
- I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读写文件,网络通信等。
- java程序中,对于数据的输入/输出操作以流stream的方式进行
- java.io包下提供了各种流类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据
输入:读取外部数据(磁盘,光盘等存储设备的数据)到程序(内存)中
输出:将程序(内存)的数据输出到磁盘,光盘等存储设备中
我们应该处在程序中来判断这是输入还是输出,不应该从内存的位置来看
io流的分类:
- 按操作数据单位不同分为:字节流(8bit)(非文本的数据都主要用字节流来处理)和字符流(16bit)(文本数据主要用字符流来处理)
- 按数据流的流向不同可以分为:输入流和输出流
- 按流的角色不同分为:节点流和处理流
下面来看具体的一个图
主要解释一下节点流和处理流
节点流就相当于直接用一根管道把数据和程序连接起来,而处理流就是在这个管道的上面再加上一个管道,可以加速数据的传输,处理流可以多次叠加
java的Io流共涉及到40多个类,实际上非常规则都是,都是从下面这四个基类派生的,这些子类名称都是父类名称作为后缀的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ma27rhF4-1604632941624)(C:\Users\24239\Desktop\数据库截图\屏幕截图 2020-11-05 092026.png)]
下面来看下io流的一个体系
在这上面中处了访问文件的四个流是节点流之外,它以下的所有流都是处理流,其中蓝色表示的流是主要用到的流
当我们看到一个流时,应该马上就能知道它是出于什么流,我们主要通过流的后面部分来判断这是一个什么流。
FileReader流和FileWriter流的操作
我们可以通过FileReader来读取文件,通过FileWriter来写入文件,结合两种可以进行文件的复制,但是不能用来处理图片,下面通过代码来看下
public class FileReaderWriterTest {
private FileReader filereader;
//单元测试Test,这个也是可以运行的,和Main方法中的相对路径的不同
//单元测试中的相对路径是基于Module的
//Main方法中的相对路径是基于Project的
@Test
//throws没有try catch finally 好用
public void fileReaderTest01() {
//为了保证流资源一定可以执行关闭操作,需要使用try-catch-finally
try {
//这个相对路径是较于当前Module中的(io流)
//1、实例化File对象,指明我们要操作的文件
//读入的文件一定要存在,不然会出现错误
File file = new File("hello.txt");
//2、提供具体的流,流的实例化
filereader = new FileReader(file);
//3、数据的读入
//read():返回读入的一个字符,如果达到末尾,返回-1
//字符char是可以自动转换成为int的
//方式一
/*int data = filereader.read();//data返回的是-1表示文件已经读完
while (data != -1) {
System.out.print((char) data);
data = filereader.read();
}*/
//方式二,语法上的修改
int data1;
while ((data1 = filereader.read()) != -1){
System.out.print((char)data1);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、流的关闭操作
try {
filereader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//对read()操作升级,使用read的重载方法
@Test
public void FileReaderTest02(){
FileReader f1 = null;
try {
//File类的实例化
File file = new File("hello.txt");
//FileReader流的实例化
f1 = new FileReader(file);
//读取的操作
//read(char[] cbuf):返回每次读入cbuf数组中的字符个数,达到文件末尾返回-1
char[] cbuffer = new char[1024];
int data ;
while ((data = f1.read(cbuffer)) != -1){
//方式一
// for (int i = 0; i < cbuffer.length; i++) {
// System.out.print(cbuffer[i]);
// }这样写是有问题的,当最后读取的字符不够五个时,依然是输出五个字符,因为它是采用填充式的
// ,不够的字符依然采用上一次没有被覆盖的字符
//正确的写法
for (int i = 0; i < data; i++) {
System.out.print(cbuffer[i]);
}
//方式二
// String str = new String(cbuffer);
// System.out.println(str);
// 这种错误和方式一中的错误是一样的,都会多输出
//正确方式
//这个构造器就是输出你输入进来的字符个数,
/*String str = new String(cbuffer,0,data);
System.out.println(str);*/
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(f1 != null){
try {
//资源的关闭
f1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//从内存中写出数据到硬盘文件中
/*
* 说明
* 输出操作,对应的File可以不存在,如果不存在,在输出地过程中会自动地创建
* 如果存在,想要接着写,就要在创建FileWriter流的时候,进行说明
* fw = new FileWriter(file,true);表示接着写
* fw = new FileWriter(file);表示写入的内容会把原来的内容给覆盖住
* fw = new FileWriter(file,false);表示写入的内容会把原来的内容给覆盖住
* */
@Test
public void fileWriterTest(){
FileWriter fw = null;
try {
//提供File类的对象,指明写出到的文件
//写出时文件不存在时,会自动地帮我们创建,
File file = new File("hello1.txt");
//提供FileWriter流的实例化,用于数据的写出
fw = new FileWriter(file,true);
//写入操作
fw.write("I have a dream!\n");//可以写入字符串或者字符数组
fw.write("You need to a dream!\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
//流的关闭
if (fw != null){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//文件的复制功能的实现
@Test
public void FileWriterFileReaderTest(){
FileReader fr = null;
FileWriter fw = null;
try {
//1、创建File类对象,指明读入和写出的文件
File file1 = new File("hello1.txt");
File file2 = new File("hello.txt");
//2、创建输入流和输出流的对象
fr = new FileReader(file1);
fw = new FileWriter(file2);
//3、数据的读入和写出操作
char[] cbuf = new char[5];
int data1 ;//记录每次读入到cbuf数组中的字符个数
while ((data1 = fr.read(cbuf)) != -1){
// for (int i = 0; i < data1; i++) {
// fw.write(cbuf[i]);
// }
//也可以直接就下面这样写
fw.write(cbuf,0,data1);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
/*if(fr != null || fw != null){
try {
//4、关闭流资源
fr.close();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}//这是我写的
}*/
//谁先关,谁后关没有关系,有两种方式来释放
//第一种,两个都会执行
try {
if (fr != null){
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fw != null){
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
//第二种
/*try {
if (fr != null){
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fw != null){
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}*/
}
}
}
FileInputStream流和FileOutputStream流的操作
如果我们需要对图片、视频等字节资源进行操作我们就要使用FileInputStream和FileOutputStream来操作,下面来看代码
//测试FileInputStream和FileOutputStream的使用
public class FileInputOutputStreamTest {
//测试图片的复制
@Test
public void FileInputOutputStreamTest() {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//File类的创建
File file1 = new File("流的分类.png");//被复制的图片
File file2 = new File("流的分类2.png");//复制后的图片
//创建流的实例
fis = new FileInputStream(file1);
fos = new FileOutputStream(file2);
//复制的过程
byte[] buffer = new byte[1024];
int data ;
while ((data = fis.read(buffer)) != -1){
fos.write(buffer,0,data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//流的关闭
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
我们可以写一个复制的方法来实现对非文本的复制
//指定路径下文件的复制方法
public void copyFile(String srcPath,String destPath){
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//File类的创建
File file1 = new File(srcPath);
File file2 = new File(destPath);
//创建流的实例
fis = new FileInputStream(file1);
fos = new FileOutputStream(file2);
//复制的过程
byte[] buffer = new byte[1024];
int data ;
while ((data = fis.read(buffer)) != -1){
fos.write(buffer,0,data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//流的关闭
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testCopy(){
long start = System.currentTimeMillis();
copyFile("鄙视链.png","鄙视链2.png");
long end = System.currentTimeMillis();
long result = end - start;//复制一张图片需要的时间(毫秒)
System.out.println(result);
}
其实上面的方法也可以用来复制文本,但是不能在控制台输出,有可能会乱码,
字节流也可以用来文本,就是不能在控制台输出,但是字符流不能用来复制非文本
缓冲流操作
缓冲流由于有了一个缓冲区,所以速度要file类的快
//实现非文本文件的复制
@Test
public void BufferedStreamTest() {
FileInputStream fis = null;
FileOutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//可以简写一二两步
//BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("鄙视链.png")));
//1、创建File对象
File srcfile = new File("鄙视链.png");
File destfile = new File("鄙视链3.png");
//2、创建流对象
//2、1创建节点流对象
fis = new FileInputStream(srcfile);
fos = new FileOutputStream(destfile);
//2、2创建处理流(缓冲流)对象
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//3、复制操作
byte[] buffer = new byte[1024];
int data;
while((data = bis.read(buffer)) != -1){
bos.write(buffer,0,data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//资源的关闭
//要求:先关闭外层的流,在关闭内层的流
//关闭四个流
try {
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bis != null) {
bis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//说明,再关闭外层流的时候,内层流也会进行自动的关闭,我们可以省略内层流的关闭
// fos.close();
// fis.close();
}
public void copyFileWithBuffered(String srcPath,String destPath){
FileInputStream fis = null;
FileOutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1、创建File对象
File srcfile = new File(srcPath);
File destfile = new File(destPath);
//2、创建流对象
//2、1创建节点流对象
fis = new FileInputStream(srcfile);
fos = new FileOutputStream(destfile);
//2、2创建处理流(缓冲流)对象
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//3、复制操作
byte[] buffer = new byte[1024];
int data;
while((data = bis.read(buffer)) != -1){
bos.write(buffer,0,data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//资源的关闭
//要求:先关闭外层的流,在关闭内层的流
//关闭四个流
try {
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bis != null) {
bis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//说明,再关闭外层流的时候,内层流也会进行自动的关闭,我们可以省略内层流的关闭
// fos.close();
// fis.close();
}
@Test
public void testBuffered(){
long start = System.currentTimeMillis();
String srcPath = "C:\\Users\\24239\\Videos\\录像\\整合好应用.mp4";
String destPath = "C:\\Users\\24239\\Videos\\录像\\整合好应用01.mp4";
copyFileWithBuffered(srcPath,destPath);
long end = System.currentTimeMillis();
long result = end - start;
System.out.println("复制的时间是:"+result+"毫秒");//24毫秒
}
//使用BufferedReader和BufferedWriter实现文本文件的复制
@Test
public void BufferedReaderBufferedWriterTest() {
BufferedReader br = null;
BufferedWriter bw = null;
try {
//1、创建File对象
File file1 = new File("hello.txt");
File file2 = new File("hello2.txt");
//2、创建流对象
//2、1创建FileWriter和FileReader对象
FileReader fr = new FileReader(file1);
FileWriter fw = new FileWriter(file2);
//2、2创建BufferedWriter和BufferedReader对象
br = new BufferedReader(fr);
bw = new BufferedWriter(fw);
//3、复制操作,有两种方式
//方式一,使用Char[]数组
/*char[] buffer = new char[1024];
int data ;
while((data = br.read(buffer)) != -1){
bw.write(buffer,0,data);
}*/
//方式二,使用String
String data;
while ((data = br.readLine()) != null){//一次读取一行
//换行的两种方式
//方法一
bw.write(data +"\n");//data中不包含换行
//方式二
/*bw.write(data);
bw.newLine();*/
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流资源,只需关闭外层即可,内层会自动地关闭,我们可以省略
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bw != null) {
bw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭流资源
// br.close();
// bw.close();
}
下面来看下我们在上面中使用到的不同的构造方法
转换流操作
转换流实现了字符流和字节流之间的转换
Java中提供了两个转换流
- InputStreamReader:将InputStream转换为Reader
- OutputStreamWriter:将OutputStream转换为Writer
字节流中的数据都是字符时,转换为字符流操作更加高效
很多时候我们使用转换流来处理文件乱码问题。实现编码和解码功能
下面就来看下这两个流的使用
//测试转换流
//转换流,属于字符流:
// InputStreamReader:将一个字节的输入流转换为字符的输入流
// outputStreamWriter:将一个字符的输出流转化为字节的输出流
//作用:提供字节流和字符流之间的转换
//解码:字节,字节数组->字符串,字符数组
//编码:字符串,字符数组->字节,字节数组
import org.junit.Test;
import java.io.*;
//字符集
public class InputStreamReaderTest {
@Test
public void test1() {
InputStreamReader isr2 = null;
try {
//1、创建File对象
FileInputStream fis = new FileInputStream("hello.txt");
//使用系统默认的字符集,默认的是utf-8
//InputStreamReader isr1 = new InputStreamReader(fis);
//参数2,指明了字符集,具体使用什么字符集,取决于文件hello.txt保存时使用的字符集
isr2 = new InputStreamReader(fis,"UTF-8");
char[] cbuf = new char[1024];
int data ;
while ((data = isr2.read(cbuf)) != -1){
//输出到控制台
String str = new String(cbuf,0,data);
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (isr2 != null) {
//还是只要关闭最外层的流即可
isr2.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//综合使用InputStreamReader 和 outputStreamWriter
@Test
public void test2() {
InputStreamReader isr = null;
OutputStreamWriter osw = null;
try {
//创建File对象
File file1 = new File("hello.txt");
File file2 = new File("hello_gbk.txt");//这个文件在idea中打开中文会出现乱码的现象
//创建流对象
FileInputStream fis = new FileInputStream(file1);
FileOutputStream fos = new FileOutputStream(file2);
//指明字符集
isr = new InputStreamReader(fis,"utf-8");
osw = new OutputStreamWriter(fos,"gbk");
//读写的过程
char[] cbuf = new char[1024];
int len ;
while ((len = isr.read(cbuf)) != -1){
osw.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//资源的关闭
try {
if (isr != null){
isr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (osw != null){
osw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
标准输入,输出流(了解)
import org.junit.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
//其它流的使用
//标准的输入,输出流
//打印流
//数据流
public class OtherStreamTest {
/*标准的输入,输出流
System.in:标准的输入流,默认从键盘输入
System.out:标准的输出流,默认从控制台输出*/
//练习
//从键盘输入字符串,要求将读取到的整行字符串转成大写输出,然后继续进行输入操作,
//直至输入"e"或者"exit"时,退出程序
//方法一:使用scanner实现,调用next()返回一个字符串
//方法二:使用System.in实现,,System.in-->转换流-->BufferedReader的readLine()
@Test
public void test1(){
BufferedReader br = null;
try {
InputStreamReader isr = new InputStreamReader(System.in);
br = new BufferedReader(isr);
while (true){
System.out.println("请输入字符串:");
String str = br.readLine();
if ("e".equalsIgnoreCase(str) || "exit".equalsIgnoreCase(str)){
System.out.println("程序结束");
break;
}
String upCase = str.toUpperCase();
System.out.println(upCase);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}