IO流入门
文章目录
文件
什么是文件?
Java文件类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建、文件的查找和文件的删除等。
File对象代表磁盘中实际存在的文件和目录。
通俗来讲,文件对象(File)是文件夹和文件的统称
注意:File 类只能操作文件的属性,文件的内容是不能操作的。
文件的创建
说明:文件路径不存在,也是可以创建文件对象的。
1、通过给定的路径创建
格式:
File(String pathname)
//通过文件路径进行创建(绝对路径)
String pathname = "E:\\java\\TRstudy\\testStudy\\IOStudy\\testIO";
File file = new File(pathname);
//不使用 Java 提供的分隔符字段,注意:这样写只能在 Windows 平台有效
File f1 = new File("D:\\IO\\a.txt");
//使用 Java 提供的分隔符
File f2 = new File("D:"+File.separator+"IO"+File.separator+"a.txt");
2、通过父路径(字符串)和子路径创建
父路径
: 文件夹路径
子路径
:文件路径
格式:
File(String parent, String child)
// 通过父路径和子路径创建file对象(相对路径)
String parentName = ".\test";
String childName = "Demo1.txt";
File file3 = new File(parentName,childName);
3、通过父路径(文件)和子路径创建2
格式:
File(File parent, String child);
// 通过父路径(文件对象)和子路径创建file对象
File parentFile = new File(".\test");
String cName = "Demo1.txt";
File file4 = new File(parentFile,childName);
4、通过URL创建
File(URI uri)
常用方法
创建文件或文件夹
方法 | 描述 |
---|---|
boolean createNewFile() | 创建一个新文件 |
boolean mkdirs() | 创建子文件夹,可以同时创建多级 |
查看文件或文件夹信息
方法 | 描述 |
---|---|
boolean exists() | 判断文件是否存在 |
String getName() | 获得文件或文件夹的名称 |
String getParentName() | 获取文件所在的父文件夹 |
String getPath() | 获得带路径的文件或文件夹的名称 |
boolean isDirectory() | 判断是否为文件夹 |
boolean isFile() | 判断是否为文件 |
long length() | 获得文件长度 |
long lastModified() | 获得文件的最后修改时间 |
查找定义目录下的文件或子文件夹
File[] listFiles() | 遍历文件夹中的所有子文件夹和文件 (只能一层) |
boolean delete() | 删除文件或文件夹 最好先判断一下文件或文件夹是否存在 |
文件过滤器
// 获取文件夹下的所有文件或文件夹对象
// 普通
File file = new File("C:\\testIO");
for (File f : file.listFiles()) {
System.out.println(f.getName());
}
// 过滤
for (File f : file.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
String name = pathname.getName();
// 定义过滤规则 假如只要.txt后缀的文件
if (name.endsWith(".txt") || pathname.isDirectory()) {
return true;
}
return false;
}
})) {
// 输出过滤后的文件
System.out.println(f.getName());
}
获取某文件下的所有子文件,及文件夹?
练习:
删除某文件下的所有txt文件?(递归)
package com.xhb.CharStream;
import java.io.File;
import java.io.FileFilter;
public class IOStream2_Zy2 {
public static void main(String[] args) {
File file = new File("c:testIO\\testDelete");
deleteFile(file);
}
private static void deleteFile(File file) {
// 判断文件夹是否存在
if (file.exists()) {
// 列出所有文件(文件和文件夹)
File[] list = file.listFiles();
for (File file2 : list) {
// 如果是文件夹,递归
if(file2.isDirectory()) {
deleteFile(file2);
}else {
// 是文件?判断是否是txt文件
if (file2.getName().endsWith(".txt")) {
boolean isDelete = file2.delete(); // 删除文件
System.out.println(file2.getPath()+":"+(isDelete==true?"删除成功":"删除失败"));
}
}
}
}else {
System.out.println("文件夹不存在");
}
}
}
I/O流
- I -> Input
- O-> Output
是指在计算机的输入输出操作中各部件之间的数据流动。
流向是针对程序而言:
- 从磁盘读入到程序内存中(输入 Input)
- 从程序中写到文件中(输出 Output)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i3GIdvcb-1622628810206)(D:\install\typora\images\image-20210601160936313.png)]
规律:
字符流:
Reader(抽象)
Writer(抽象)
凡是带Reader 或 Writer 结尾的,都是他的实现类,也就是字符输入流
字节流:
InputStream(抽象)
OutputStream(抽象)
凡是带 InputStream 或 OutputStream 结尾的,都是他的实现类,也就是字节输入流
Buffered开头的都是带缓存区的
字节流
OutputStream(抽象) 下面都是实现的子类
- FileOutputStream (字节输出流)
InputStream(抽象)下面都是实现的子类
- FileInputStream(字节输入流)
FileInputStream 读数据(三种)
int read() 读取一个字节,效率低,用得少
// InputStream 读一个字节
String pathname = "C:\\testIO\\name.txt";
InputStream is = new FileInputStream(pathname);
int len = 0;
System.out.println((char)is.read());
int read(byte[] b) 读取多个字节,字节数组越大,读到的字节就越多
返回实际读取到的字节数
String pathname = "C:\\testIO\\name.txt";
InputStream is = new FileInputStream(pathname);
int len = 0;
byte [] b = new byte[1024];
StringBuffer sb = new StringBuffer();
while((len = is.read(b))!=-1) {
sb.append(new String(b,0,len));
}
System.out.println(sb);
int read(byte[] b,int off,int len) 读取多个字节,字节数组越大,读到的字节就越多
返回实际读取到的字节数
String pathname = "C:\\testIO\\name.txt";
InputStream is = new FileInputStream(pathname);
byte[] b = new byte[1024];
int len=2,offset = 0;
StringBuffer sb = new StringBuffer();
while((len = is.read(b, offset, len))!=-1) {
offset+=len;
}
sb.append(new String(b,0,offset));
System.out.println(sb);
FileOutputStream 写数据
默认覆盖写入
// 常规写法
String parentName = "c:\\testIO";
String childName = "a.txt";
File file = new File(parentName,childName);
OutputStream os = new FileOutputStream(file);
String content = "你是谁,爱上谁";
os.write(content.getBytes());
注意:
文件不存在,则会自己创建,文件存在,则会覆盖(文件会自己创建,文件夹不会)
若需追加数据,在new Outputstream 时,添加参数true
OutputStream os = new FileOutputStream(file,true);
关流
必须关流
写在finally 里
is.close();
os.close();
拷贝案例
package com.xhb.io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class IOStream_Zy3 {
public static void main(String[] args) {
// 源文件路径
File file = new File("C:\\Users\\13500\\Desktop\\money.png");
// 源文件存在 才能被复制
if (file.exists()) {
// 图片的目的地址
File toParentFile = new File("c:\\testIO");
File toChildFile = new File("c:\\testIO\\copyimg.png");
// 目的地址父路径不存在就创建
if (!toParentFile.exists()) {
toParentFile.mkdirs();
}
// 目的地址子路径不存在就创建
if (!toChildFile.exists()) {
try {
toChildFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
// 复制图片
copyPhoto(file, toChildFile);
} else {
System.out.println("源文件不存在");
}
}
// 复制图片
public static void copyPhoto(File file, File toFile) {
InputStream is;
try {
is = new FileInputStream(file);
OutputStream os = new FileOutputStream(toFile);
byte[] b = new byte[1024];
int len ;
while ((len = is.read(b)) != -1) {
os.write(b);
}
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符流
只列出了常用的。
Reader(抽象)
- FileReader (实现类)
- BufferedReader (实现类)
Writer(抽象)
- FileWriter(实现类)
- BufferedWrite(实现类)
字符流是由字符组成的 ,包括字符、字符串和字符数组等 字符流处理由2个字节构成的Unicode编码
一般的文本文件(.txt)就使用使用字符流来处理
字符流与字节流的区别?
字符流由字符组成,只能包含文本
字节流由字节组成,可以包含任意类型的数据,比如图片、视频、文本等
因为文本涉及到编码的问题,所以用字节流的话,还需要解码,所以如果是纯文本的话,就用字符流
FileWriter
写数据
File file = new File("c:testIO\\a.txt");
Writer w = new FileWriter(file,true); // 表示追加
System.out.println("请输入一段文字:");
Scanner scanner = new Scanner(System.in);
String content = scanner.next();
w.write('\n');
w.write(content);
w.close();
scanner.close();
BufferedWrite
带缓冲区的写数据
System.out.println("请输入一段文字:");
Scanner scanner = new Scanner(System.in);
String content = scanner.next();
Writer fw = new FileWriter(file,true);// 追加
BufferedWriter bW = new BufferedWriter(fw);
bW.write(content);
bw.flush();
bW.close();
PrintWriter
PrintWriter pw = new PrintWriter(new FileOutputStream(file,true),true);
pw.write("the quick brown fox");
pw.close();
FileReader
读数据
如果定义的字符数组不够,则会出现问题。怎么解决?没想好
Reader reader = new FileReader(file);
int len = 0,size = 0;
StringBuffer sb = new StringBuffer();
char[] b = new char[1024];
while((len = reader.read(b,size,5))!=-1) {
size += len;
}
sb.append(new String(b,0,size));
System.out.println(sb);
reader.close();
BufferedReader
带缓冲区的读
Reader in = new FileReader(file);
BufferedReader br = new BufferedReader(in);
String line ;
while((line = br.readLine())!=null) {
System.out.println(line);
}
readLine(): 读一行数据,BufferedReader 中特有的
转换流
字节流 --> 字符流
- InputStreamReader: 将字节输入流装换成字符输入流
- OutputStreamWriter: 将字节输出流转换成字符输出流
InputStreamReader
//文件
File file = new File("c:\\testIO\\name.txt");
//字节流
InputStream is = new FileInputStream(file);
//转换流
InputStreamReader isr = new InputStreamReader(is);
//字符流
BufferedReader br = new BufferedReader(isr);
// 这里就是操作字符流了 详情见上
String str;
while((str = br.readLine())!=null) {
System.out.println(str);
}
OutputStreamWriter
// 文件
File file = new File("c:\\testIO\\name.txt");
//字节流 输出
OutputStream os = new FileOutputStream(file,true);
//转换流
OutputStreamWriter osw = new OutputStreamWriter(os);
//字符输出流
BufferedWriter bw = new BufferedWriter(osw);
bw.write("嘻嘻哈哈");
bw.close();
总结:
四大基类:都是抽象类
- InputStream
- OutputStream
- Writer
- Reader
前两个是字节流,后两个是字符流
按功能分:
-
节点流
例如:FileOutputStream,这些直接操作的就是节点流
-
处理流(包装流)
例如:BufferedReader 处理流的构造方法总是要带一个其他的流对象做参数,一个流对象经过其他流的多次包装,称为流的链接
规律:
- 带Buffered 开头的 都是带缓存区 的流 (速度快,效率高)
- 以OutPutStream/ InputStream 结尾的,都是字节流
- 以Writer / Reader 结尾的,都是字符流
- 构造方法里,要传入一个流对象的,都是包装流(缓存流,转换流,内存流,合并流 这些都是包装流)
- 关闭包装流时,只要关闭包装流即可