目录
(1)BufferedReader和BufferedWriter类
1.摘要:什么是OI
OI是input和output的简称,很明显它就是代表输入和输出。程序在运行期间,需要从外部程序,存储媒介中读入数据,即从源中输入数据到程序,需要使用输入流。程序在得到数据并处理后,需要向外输出至存储媒介或者应用程序,需要使用输出流。Java.io包里面提供了很多IO有关的类和接口。
2.File类
Java中可以通过File类创建对象,让程序能够在磁盘上获取文件相关信息,创建文件或者删除文件。下面是文件的创建与删除,以及获取文件属性的相关操作。
1)文件的创建与删除
创建一个File对象的构造方法有三种:
File(String PathName);
File(String directoryPath, String fileName);
File(File dir,String fileName);
文件删除只需要用方法file.delete()即可
package com.bluemsun.QQmian;
import java.io.*;
import java.io.File;
public class NewJavaFile {
public static void main(String[] args) {
//方法一,new File(String Pathname)
String filep = "D:\\javacode\\news.txt";
File file = new File(filep);
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
if (file.exists()) {
System.out.println("创建好了文件,删了你吧");
file.delete();
}
if (!file.exists()) {
System.out.println("可恶,把我创建好的文件给删了");
}
}
}
package com.bluemsun.QQmian;
import java.io.File;
import java.io.IOException;
public class NewJavaFile02 {
//方法二,File(File parent, String filename)
public static void main(String[] args) {
File fileparent = new File("D:\\javacode");
String filename = "news2.txt";
File file = new File(fileparent, filename);
try{
file.createNewFile();//当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
System.out.println("想不到吧,我又创建了个文件哈哈哈哈哈");
}catch(IOException e){
e.printStackTrace();
}
}
}
package com.bluemsun.QQmian;
import java.io.File;
import java.io.IOException;
public class NewJavaFile03 {
public static void main(String[] args) {
//方法三,File(String directoryPath, String filename);
String directoryPath = "D:\\javacode";
String fileName = "news3.txt";
File file = new File(directoryPath, fileName);
try{
file.createNewFile();
System.out.println("我总是创建文件,这是最后一次了,钱桑");
}catch(IOException e){
e.printStackTrace();
}
}
}
上述是用三个不同的构造方法创建文件,当然 重点不在这三个构造方法而在try{...}catch{...}语句和file.createNewFile()方法。
file.createNewFile()是来创建文件的方法,如果创建失败那么会抛出IOException类异常对象,然后catch它。注意:上述的三个File构造方法是不会创建文件的,只有file.createNewFile()会创建文件。
2)文件属性
获取文件属性的一些方法:
file.getName(); 获取文件名字
file.getAbsoluteFile(); 获取文件绝对路径
file.getParent(); 获取文件父目录
file.length(); 获取文件长度(单位是字节)
file.exists(); 判断文件是否存在,返回值为boolean类型
file.isFile(); 判断文件是否是一个普通文件,不是目录
file.isDirectory() 判断文件是否是一个目录
package com.bluemsun.QQmian;
import java.io.File;
public class FileInformation {
public static void main(String[] args) {
File file = new File("D:\\javacode");
System.out.println("文件名字:" + file.getName());
System.out.println("文件的绝对路径:" + file.getAbsoluteFile());
System.out.println("文件父目录:" + file.getParent());
System.out.println("文件大小(字节):" + file.length());
System.out.println("文件是否存在:" + file.exists());
System.out.println("文件是否是一个文件:" + file.isFile());
System.out.println("文件是否是一个目录:" + file.isDirectory());
}
}
3)目录操作
目录的创建方法:mkdir()和mkdirs(),一个是创建一级目录一个是创建多级目录,同时注意这两种方法的返回值为boolean类型。
package com.bluemsun.QQmian;
import java.io.File;
//文件夹就是目录但不是文件
public class FileDir {
public static void main(String[] args) {
File file = new File("D:\\javacode\\dir\\dir1");
if(file.exists()){
if(file.delete()){
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
}else{
//mkdir()是创建一级目录
//mkdirs()是创建多级目录
if(file.mkdirs()){
System.out.println("该目录创建成功");
}else{
System.out.println("该目录创建成功");
}
}
}
}
3.OI流
1)字符输入、输出流
这里的Reader和Writer类是抽象类,没办法直接定义对象,提供一个接口,让FileReader和FileWriter这两个实现类定义对象,实现相关操作。可以看看Reader和Writer类的继承关系,和类体定义:
Reader是一个抽象类,用关键字implements接上接口Readable和Closeable。下面的Writer是类似的:
这里的abstract和implements关键字很明显,不多说了。正在狂飙博客容我水一会儿
FileReader 和FileWriter
方法及构造方法:
FileReader(String filename);
FileReader(File filename);
FileWriter(String filename);
FileWriter(File filename);
FileWriter(String filename, boolean append);
FileWriter(File filename, boolean append);
//这里的构造方法的用法和前面的字节流是一样的,只是输入输出数据的大小不一样。
注意:使用FileWriter后必须要关闭(close)或者刷新(flush),否则将要写入的数据会留在缓冲区,不会写入不到指定文件。
2)字节输入、输出流
1.FileInputStream
方法及构造方法:
构造方法:
FileInputStream(String name);
FileInputStream(File file);
用read方法读取字节:
int read();输入流调用该方法从源中读取单个字节的数据,该方法返回字节值(0 ~ 255之间的一个整数),如果未读出字节就返回-1。
int read(byte b[]);输入流调用该方法从源中试图读取b.length个字节到字节数组b中,返回实际读取的字节数目。如果到达该文件的末尾则返回-1。
int read(byte b[], int startposition, int len);输入流调用该方法从源中试图读取len个字节到字节数组b中,并返回实际读取的字节数目。如果到达文件的末尾,则返回-1。参数从字节数组中startposition的位置开始存放读入的顺序。
用close()方法关闭输入流:
注意:FileInputStream流顺序地读取文件,只要不关闭流,每次调用read方法就顺序地读取源中其余内容,指导源地末尾或流被关闭。
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputstream {
//FileInputStream有两种构造方法指向文件的输入流
//1.FileInputStream(String name)2.FileInputStream(File file);
//文件 ————> 程序
public static void main(String[] args) {
String filePath = "D:\\javacode\\hello.txt";
int readData = 0;
FileInputStream fileInput = null;
try{
fileInput = new FileInputStream(filePath);
while((readData = fileInput.read()) != -1) {
System.out.println((char)readData);
}
}catch (IOException e){
e.printStackTrace();
}finally {
try {
fileInput.close();
}catch(IOException ee){
ee.printStackTrace();
}
}
}
}
就这个程序分析下:我首先在D盘的javacode目录下创建了一个hello.txt文档,并且在里面写了“hello world”,然后用read读txt文档里面的数据,返回int值,所以如果要输出char值需要类型转换。个人理解:在IO流的一些方法中它会像一个boolean一样判断是否操作成功,比如createNewFIle方法,FileInputStream方法,前者如果创建失败了文件是会抛出异常的,后者如果找不到输入流的源也会抛出异常,对于这些能够抛出异常的方法,都要try{...}catch{...}一下以防程序莫名终止。出问题你还找不到是哪儿有问题。
2.FileOutStream
方法及构造方法:
FileOutputStream(String name);
FileOutputStream(File file);
也可以使用FileOutputStream类的下列能选择是否具有刷新功能的构造方法创建指向文件的输出流。
FileOutputStream(String name, boolean append);
FileOutputStream(File file, boolean append);
当构造方法创建指向一个文件的输出流的时候,如果append值为true那么输出流不会刷新所指向的文件。否则输出流会刷新所指向的文件。(前提条件:该文件已存在)
输出流是为程序提供一个通道程序可以通过该通道将程序中的数据写入到目的存储媒介,或其他程序。
write方法以字节为单位向目的写入数据。
void write(int n)向目的写入单个字节数据。
void write(byte b[])输出流调用该方法向目的地写入单个字节。
void write(byte b[], int off, int len)输出流调用该方法向目的地写入一个字节数组。从下标off开始长度为len。
void close()关闭输出流。
import java.io.*;
public class FileInputstream {
public static void main(String[] args) {
String str = "QQmian是帅气的";
String str1 = "QQmian不是帅气的";
byte[] a = str.getBytes();
byte[] b = str1.getBytes();
File file = new File("D:\\javacode\\hello.txt");
try{
OutputStream out = new FileOutputStream(file);
//假设目的文档中有东西那么会直接覆写,直接清空目的文档里的东西。
System.out.println(file.getName() + "大小为:" + file.length() + "字节");
//这里创建的时候已经覆盖目的文档内容了,所以文档大小为0
out.write(a);
out.close();
out = new FileOutputStream(file, true);
//通过这个操作能够不覆盖之前的内容,append为true说明能够不覆盖而是追加到末尾写入
//如果append为false那么还是会覆盖文件内容
out.write(b, 0, b.length);
System.out.println(file.getName() + "大小为:" + file.length() + "字节");
out.close();
}catch(IOException e){
System.out.println("error" + e);
}
}
}
注释里面已经解释得很清楚了,不再多说了(能水一点是一点不然写不完博客了!!!)
3.文件拷贝
学会了文件的输入、输出流后就能实现文件拷贝了,代码如下:
import java.io.*;
//文件拷贝
//创建输入流,读取数据
//创建输出流,将读取到的文件数据,写入到指定文件
public class FileIcopy {
public static void main(String[] args) {
String srcFilePath = "D:\\javacode\\hello.txt";
String desFilePath = "D:\\javacode\\hello1.txt";
FileInputStream srcFile = null;
FileOutputStream desFile = null;
try{
srcFile = new FileInputStream(srcFilePath);
desFile = new FileOutputStream(desFilePath);
byte[] buf = new byte[1024];
int readlen = 0;
//一边读取一边写入
while((readlen = srcFile.read(buf)) != -1){
desFile.write(buf, 0, readlen);
}
System.out.println("拷贝ok~");
}catch(IOException e){
e.printStackTrace();
}finally {
try{//关闭输出流和输入流
if(srcFile != null){
srcFile.close();
}
if(desFile != null){
desFile.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
不单单是文档的拷贝,图片也能实现拷贝。暂时没有找到图片就先拷贝文档了。方法是一样的。
3)处理流(包装流)
前面讲的字节字符IO流都是节点流,是低级的流,能直接从特定的数据源读写数据,灵活性不强功能不够强大。接下来将讲讲处理流,它也称包装流,能够对节点流进行包装使输入输出流的功能更强大。比如BufferedReader和BufferedWriter,它们其实分别是Reader、Writer的子类。举个例子,看看BufferedRead源码:
可以看到BufferedRead中包含了一个Reader类创建的对象,所以BufferedRead可以封装任意一个节点流,只要该节点流是Reader的子类就行。BufferedWriter设计理念也是相同的。
补充:节点流与处理流的区别与联系
区别:
节点流是直接与数据源进行交互的底层流,比如FileInputStream和FileOutputStream。节点流提供了读取和写入数据的基本方法,但通常不会对数据进行任何处理。处理流是基于节点流构建的高级流,也称为包装流。它们可以对数据进行处理和转换,比如BufferedInputStream和BufferedOutputStream。处理流通过将数据包装在内部缓冲区中来优化性能,并提供许多方便的功能,例如按行读取文本文件等。
节点流和处理流的主要区别在于它们所处理的数据类型和操作方式。节点流只能处理原始的字节或字符数据,而处理流可以处理更高层次的数据,例如对象、字符串和数组。同时,节点流提供了基本的读写操作,而处理流则提供了更丰富的工具和操作,以便对数据进行更高效、更灵活的处理。
联系:
处理流必须依赖节点流,因为它们不能直接与数据源进行交互。处理流通常使用节点流作为其构造函数参数,以便构建处理流对象。
(1)BufferedReader和BufferedWriter类
方法及构造方法:
构造方法:
BufferedReader(Reader in);这里的Reader是BufferedReader的父类。
BufferedWriter(Writer out);这里的Writer是BufferedWriter的父类。
方法:
readLine();用BufferedReader中的方法readLine()读取文本行。
newLine();BufferedWriter特有的向文件中写入一个回行符的方法。
下面敲一个例子:
import java.io.*;
import java.util.StringTokenizer;
public class FileIOp {
public static void main(String[] args) {
File fileReader = new File("D:\\javacode\\hello.txt");
File fileWriter = new File("D:\\javacode\\hello2.txt");
try{
Writer out = new FileWriter(fileWriter);
BufferedWriter Wout = new BufferedWriter(out);
Reader in = new FileReader(fileReader);
BufferedReader Rin = new BufferedReader(in);
String s = null;
while((s = Rin.readLine()) != null){
Wout.write(s);
Wout.newLine();
}
Wout.close();
out.close();
//注意先关底层,再关上层
Rin.close();
in.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
这里我把hello.txt中的内容读到了hello.txt2中!!!!!神奇不神奇?【狗头】这里需要注意的是,我注释写错了。关闭输出流的时候首先关闭缓冲输出流,然后关闭缓冲输出流指向的流,即先关闭上层流再关闭底层流。在编写代码的时候只需要关闭上层流,那么上层流的底层流会自动关闭。
(2)RandomAccessFile类
这个类创建的流叫随机流,比较强,既能读取文件也写文件。当准备对一个文件进行读写操作的时,创建一个指向该文件的随机流即可。注意:RandomAccessFile流指向文件时,不刷新文件。
方法及构造方法:
构造方法:
- RandomAccessFile(File file, String mode): 创建RandomAccessFile对象,mode参数为“r”表示只读,“rw”表示可读写。
- RandomAccessFile(String filename, String mode): 创建RandomAccessFile对象,filename参数为文件名,mode参数同上。
常用方法:
- seek(long pos):设置文件指针的位置。
- getFilePointer():获取当前文件指针的位置。
- read():从文件中读取一个字节并返回。
- read(byte[] b):从文件中读取若干个字节到字节数组b中。
- write(int b):向文件中写入一个字节。
- write(byte[] b):向文件中写入字节数组b中的数据。
当时间太晚时,不想写时,为什么不问问chatGPT呢?
import java.io.RandomAccessFile;
import java.io.IOException;
public class RandomAccessFileExample {
public static void main(String[] args) throws IOException {
// 创建RandomAccessFile对象,文件名为example.txt,模式为可读写
RandomAccessFile raf = new RandomAccessFile("example.txt", "rw");
// 写入数据到文件
raf.write("Hello World!".getBytes());
// 设置文件指针的位置为5
raf.seek(5);
// 从文件中读取一个字节并输出
System.out.println((char)raf.read());
// 设置文件指针的位置为0
raf.seek(0);
// 读取文件中所有数据并输出
byte[] buffer = new byte[(int)raf.length()];
raf.read(buffer);
System.out.println(new String(buffer));
// 关闭文件流
raf.close();
}
}
之后还有其他的一些流,具体在Java预习...(下)中介绍,实在没时间了,得交博客了