目录
1.File类
- java.io.File类: 文件和文件目录路径的抽象表示形式,与平台无关
- File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。
- 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对象。
- 构造函数:
public File(String pathname)
以pathname为路径创建File对象。- public File(String parent,String child) 以parent为父路径, child为子路径创建File对象。
- public File(File parent,String child) 根据一个父File对象和子文件路径创建File对象
- 路径中的每级目录之间用一个路径分隔符隔开。windows和DOS系统默认使用“\”来表示,UNIX和URL使用“/”来表示
- 为了解决这个隐患分隔符的不同, File类提供了一个常量:
public static final String separator
。根据操作系统,动态的提供分隔符。
File file1 = new File("d:\\Wzx\\info.txt");
File file2 = new File("d:" + File.separator + "Wzx" + File.separator + "info.txt");
File file3 = new File("d:/Wzx");
1.1 常用的方法
- File类的获取功能
public String getAbsolutePath()
: 获取绝对路径public String getPath()
: 获取路径public String getName()
: 获取名称- public String getParent(): 获取上层文件目录路径。 若无, 返回null
public long length()
: 获取文件字节数 。不能获取目录的长度。- public long lastModified() : 获取最后一次的修改时间, 毫秒值
public String[] list()
: 获取指定目录下的所有文件或者文件目录的名称数组public File[] listFiles()
: 获取指定目录下的所有文件或者文件目录的File数组- public boolean renameTo(File dest):把文件重命名为指定的文件路径
- File类的判断功能
public boolean isDirectory()
: 判断是否是文件目录public boolean isFile()
: 判断是否是文件public boolean exists()
: 判断是否存在- public boolean canRead() : 判断是否可读
- public boolean canWrite() : 判断是否可写
- public boolean isHidden() : 判断是否隐藏
- File类的创建功能
public boolean createNewFile()
: 创建文件。 若文件存在, 则不创建, 返回false- public boolean mkdir() : 创建文件目录。 如果此文件目录存在, 就不创建。如果此文件目录的上层目录不存在, 也不创建。
public boolean mkdirs()
: 创建文件目录。 如果上层文件目录不存在, 一并创建public boolean delete()
: 删除文件或者文件夹
public class FileDemo {
public static void main(String[] args) throws IOException {
//产生对象
File filePath = new File("E:\\wu\\FileDemo");
File file = new File(filePath, "a.txt");//仅在内存中创建了一个 File 对象,并没有在文件系统中创建文件。
filePath.mkdirs();//目录不存在创建,存在不创建
file.createNewFile();//创建文件,存在不创建
File file1 = new File("readme.txt");//当前位置创建文件
file1.createNewFile();
// file1.delete();//删除文件
System.out.println(file.getAbsoluteFile());//获取绝对路径
System.out.println(file.getPath());//创建对象时传递的参数
System.out.println(file.getName());//获取文件名
System.out.println(file.length());//获取文件字节数,不能获取目录的长度。
String[] str = filePath.list();//返回所有文件或目录的名称数组
for (String s : str) {
System.out.println(s);
}
}
@Test
public void test2() {//递归打印所有文件
File filePath = new File("E:\\wu\\FileDemo");
showFile(filePath.getAbsolutePath());
}
public static void showFile(String filPath) {
//创建对象
File file = new File(filPath);
//查看当前目录下文件
File[] str = file.listFiles();
for (File file1 : str) {
if (file1.isDirectory()) {
showFile(file1.getAbsolutePath());
}
System.out.println(file1.getPath());
}
System.out.println("=========");
}
}
2. IO流原理及流的分类
2.1按照流向分
- 输入流: 只能从中读取数据,而不能向其写入数据。
- 输出流:只能向其写入数据,而不能向其读取数据。
输入Input:读取外部数据到程序
输出Output:将程序数据输出到磁盘,光盘等设备中
抽象基类 | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
2.2按照操作单元划分
- 字节流:是一个字节一个字节的读取或写入
- 字符流:是一个字符一个字符的读取或写入,一个字符就是两个字节,主要用来处理字符。
2.3按照角色分
- 节点流:直接从/向一个特定的IO设备(如磁盘,网络)读/写数据的流,称为节点流。
- 处理流:“连接”在已存在的流(节点流或处理流)之上通过对数据的处理为程序提供更为强大的读写功能的流
3. 输入流和输出流
3.1 输入流
InputStream 和 Reader 是所有输入流的基类
-
InputStream
int read()
读取数据的下一个字节。 没有字节时返回-1。int read(byte[] b)
夺取 b.length 个字节数据到 byte 数组中。没有字节时返回 -1。 否则返回实际读取的字节数。int read(byte[] b, int off,int len)
将 len个数据字节读入byte数组。 尝试读取 len 个字节,可能小于该值。以整数形式返回实际读取的字节数。 没有字节时返回 -1。public void close() throws IOException
关闭流并释放资源。
-
Reader
int read()
同上int read(char[] cbuf)
将字符读入字符数组。没有字符时返回-1。 否则返回字符数。int read(char[] cbuf,int off,int len)
同上public void close() throws IOException
同上
3.2 输出流
OutputStream & Writer是所有输出流的基类
- OutputStream
void write(int b)
将指定的字节写入此输出流。向输出流写入一个字节。void write(byte[] b)
将 b.length 个字节从指定的 byte 数组写入此输出流。void write(byte[] b,int off,int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。public void flush()throws IOException
刷新该流的缓冲, 则立即将它们写入预期目标public void close() throws IOException
同上
- Writer
void write(int c)
写入单个字符。void write(char[] cbuf)
写入字符数组。void write(char[] cbuf,int off,int len)
写入字符数组的某一部分。 从off开始, 写入len个字符void write(String str)
写入字符串。void flush()
同上public void close() throws IOException
同上
3.3 案例
public class IOStream {
public static void main(String[] args) throws IOException {//字符流单个读操作
FileReader reader = null;
try {
reader = new FileReader("readme.txt");
// 循环读取
int charInt;
while ((charInt = reader.read()) != -1) {
System.out.println((char) charInt);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
reader.close();
}
}
@Test
public void readerDemo() throws IOException {//字符流数组读操作
FileReader reader = null;
try {
reader = new FileReader("readme.txt");
int length;
char[] buffer = new char[5];
while ((length = reader.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, length));
}
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
reader.close();
}
}
@Test
public void writerDemo() throws IOException {//字符流写单个字符操作
FileWriter out = null;
try {
out = new FileWriter("a.txt");
out.write(100);//写入一个字符 d
out.write("别看我只是一只羊");
out.flush();//立即执行
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
out.close();
}
}
@Test
public void copyDoc() throws IOException {//字符流拷贝文件
FileReader in = null;
FileWriter out = null;
int length;
try {
in = new FileReader("readme.txt");
out = new FileWriter("readme2.txt");
char[] c = new char[5];//写入数组类型为char
while ((length = in.read(c)) != -1) {
out.write(c, 0, length);
}
out.flush();//立即执行
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
in.close();
out.close();
}
}
@Test
public void copyImg() throws IOException {//字符流拷贝图片
FileReader in = null;//图片无法打开,原因图片中没有字符,用字符流拷贝会报错
FileWriter out = null;
int length;
try {
in = new FileReader("j8.png");
out = new FileWriter("j9.png");
char[] c = new char[5];//写入数组类型为char
while ((length = in.read(c)) != -1) {
out.write(c, 0, length);
}
out.flush();//立即执行
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
in.close();
out.close();
}
}
@Test
public void inputStream() throws Exception {//字节流读取文件
FileInputStream in = new FileInputStream("readme.txt");
int i;
//循环读取
while ((i = in.read()) != -1) {
System.out.println((char) i);
}
in.close();
}
@Test
public void copyDoc2() throws IOException {//使用字节流拷贝文件,一个一个拷贝
FileInputStream in = new FileInputStream("readme.txt");
FileOutputStream out = new FileOutputStream("readme3.txt");
int i;
while ((i = in.read()) != -1) {
out.write(i);
}
in.close();
out.close();
}
@Test
public void copyArray() throws IOException {//字节流拷贝文件1024K一次
FileInputStream in = new FileInputStream("readme.txt");
FileOutputStream out = new FileOutputStream("readme3.txt");
int i;
byte[] buffer = new byte[1024];
while ((i = in.read(buffer)) != -1) {
out.write(buffer, 0, i);
}
in.close();
out.close();
}
4. 缓冲流
- 缓冲流(Buffered Stream)是在输入和输出流之上提供了缓冲功能的流。它通过使用内部缓冲区数组(8kB)来减少与底层资源的直接交互次数,从而提高数据读取和写入的效率。
- 缓冲流通过预先将数据读取到内存缓冲区或将数据从内存缓冲区写入到目标流中,以块的方式进行读取和写入操作。
- 常见的缓冲流有
- BufferedInputStream 和 BufferedOutputStream
- BufferedReader 和 BufferedWriter
- 当使用BufferedInputStream读取字节文件时, BufferedInputStream会一次性从文件中读取8192个(8Kb), 存在缓冲区中, 直到缓冲区装满了, 才重新从文件中读取下一个8192个字节数组。
- 使用方法flush()可以强制将缓冲区的内容全部写入输出流
- 关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可, 关闭最外层流也会相应关闭内层节点流
public class BufferDemo {
public void copyNoBuffer(String from, String to) throws IOException {//拷贝文件不使用缓冲流
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(from);
out = new FileOutputStream(to);
int length;
byte[] buffer = new byte[1024];
while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length);
}
out.flush();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
in.close();
out.close();
}
}
public void copyWithBuffer(String from, String to) throws IOException {//拷贝文件使用缓冲流
BufferedInputStream in = null;
BufferedOutputStream out = null;
try {
in = new BufferedInputStream(new FileInputStream(from));
out = new BufferedOutputStream(new FileOutputStream(to));
int length;
byte[] buffer = new byte[1024];
while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length);
}
out.flush();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
in.close();
out.close();
}
}
@Test
public void controltable() throws IOException {
long start = System.currentTimeMillis();
// copyNoBuffer("D:\\下载网盘\\xiazai\\Video\\MuteFun.mp4","d:\\下载网盘\\xiazai\\MuteFun.mp4");//3705ms
copyWithBuffer("D:\\下载网盘\\xiazai\\Video\\MuteFun.mp4", "d:\\下载网盘\\xiazai\\MuteFun.mp4");//1132ms
long end = System.currentTimeMillis();
System.out.println(end - start);
}
@Test
public void test() throws IOException {
BufferedReader in = new BufferedReader(new FileReader("D:\\下载网盘\\xiazai\\options.txt"));
BufferedWriter out = new BufferedWriter(new FileWriter("options.txt"));
String line;
while ((line = in.readLine()) != null) {
out.write(line);//写line的内容
// out.newLine();自动换行
}
in.close();
out.close();
}
}
5.转换流
块文件:由字节流组成的文件不可直接阅读,例如图像、音频、视频、压缩文件等。
文本文件:它包含的是可读的文本,例如纯文本文档、代码文件、配置文件等。
- 转换流提供了在字节流和字符流之间的转换
- 在处理文本数据时,需要将字符按照特定的编码方式转换为字节进行传输或存储,或者将字节按照特定的编码方式解码为字符进行处理或展示。转换流在这两种表示方式之间起到了桥梁的作用。
- 很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能
- 提供字符流的功能:转换流提供了字符流的操作和方法,例如按行读取文本数据等
- InputStreamReader( 字节流转换为字符流)
- 需要和InputStream“套接”。
- 构造器
public InputSreamReader(InputStream in,String charsetName)
如: Reader isr = new InputStreamReader(System.in,”gbk”);
- OutputStreamWriter
- 实现将字符的输出流按指定字符集转换为字节的输出流。
- 需要和OutputStream“套接”。
- 构造器
public OutputSreamWriter(OutputStream out,String charsetName)
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream("a.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in,"utf-8"));//字节流转字符流
System.out.println(reader.readLine());
6. 字符编码
- ASCII: 美国标准信息交换码。
- ISO8859-1: 拉丁码表。欧洲码表
- GB2312: 中国的中文编码表。最多两个字节编码所有字符
- GBK: 中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
- Unicode: 国际标准码, 融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。
- UTF-8: 变长的编码方式,可用1-4个字节来表示一个字符。