先修
- 文件分割符:
Linux操作系统,文件分隔符号是"/"
windows操作系统,文件分隔符号是" \ ",路径分隔符在代码中的体现必须是 "\\",windows还支持 "/"
- 相对路径和绝对路径:
绝对路径是从盘符开始的一个路径 :"C:\Demo1\test.txt"
相对路径:不从盘符开始的路径 :"\test.txt" (必须有一个参考路径,多用于工程项目中)
File
在 java 程序中,对磁盘文件进行描述的类。文件和目录路径名的抽象表示形式
- File 基本方法练习:
package practice.io;
import java.io.File;
import java.io.IOException;
/**
* prudence
* 2020/5/7 9:30 上午
*/
public class IOTest {
public static void main(String[] args) throws IOException {
//分号 与系统有关的路径分隔符
System.out.println(File.pathSeparator);
System.out.println(File.pathSeparatorChar);
// 反斜杠 与系统有关的默认名称分隔符
System.out.println(File.separator);
System.out.println(File.separatorChar);
System.out.println("===================================================");
//创建一个文件对象,表示桌面的的abc.txt文件
File file = new File(File.separatorChar + "Users" + File.separatorChar + "prudence" + File.separatorChar + "Desktop" + File.separatorChar + "abc.txt");
System.out.println(file.getPath());// /Users/prudence/Desktop/abc.txt
file.createNewFile();
System.out.println(file.canExecute());//false
System.out.println(file.canWrite());//true
System.out.println(file.canRead());//true
System.out.println(file.isHidden());//false
System.out.println("===================================================");
File file2 = new File("/Users/prudence/Desktop/a.txt");
System.out.println(file.compareTo(file2));
//exists方法:判断文件抽象路径表示的文件或目录是否存在
System.out.println(file2.exists());
// createNewFile方法:创建一个新的空文件(若存在则创建失败)
System.out.println(file2.createNewFile());
// delete方法:只能删除文件和空文件夹,非空文件夹不能使用delete方法删除
System.out.println(file2.delete());
System.out.println(file.delete());
}
}
运行结果:
- 在相同路径下新建文件:
public static void main(String[] args) throws IOException {
//在hello.txt相同的目录下创建出一个world.txt文件
File f1 = new File("/Users/prudence/Desktop/hello.txt");
System.out.println(f1.getPath());// /Users/prudence/Desktop/hello.txt
System.out.println(f1.getParent());// /Users/prudence/Desktop
System.out.println(f1.getName());// hello.txt
System.out.println(f1.toPath());// /Users/prudence/Desktop/hello.txt
System.out.println(f1.toURI());// file:/Users/prudence/Desktop/hello.txt
// fun(f1);
}
public static void fun(File file) throws IOException {
//获取父路径
String parent = file.getParent();
// 创建File对象
File f = new File(parent, "新建文本文档.txt");
// 创建新文件
f.createNewFile();
}
- 文件和文件夹:
public static void main(String[] args) throws IOException {
// File file = new File("/Users/prudence/Desktop/333");
File file = new File("/Users/prudence/Desktop/test");
System.out.println(file.exists());
//判断一个File对象是否是文件夹
System.out.println(file.isDirectory());
// 判断一个File对象是否是文件
System.out.println(file.isFile());
// 获取文件夹中所有子文件夹和文件的名称(字符串形式)
String[] files = file.list();
System.out.println("===================================================");
System.out.println(files.length);
for (String s : files) {
System.out.println(s);
}
System.out.println("===================================================");
File[] fs = file.listFiles();
// 获取文件件中所有子文件夹和文件的抽象路径(File对象)
System.out.println(fs.length);
for (File f : fs) {
System.out.println(f);
}
}
运行结果:
- 创建文件与重命名:
public static void main(String[] args) throws IOException {
File file = new File("/Users/prudence/Desktop/test/a.txt");
// //在创建一个文件时,需要先判断父目录是否存在,若不存在则创建父目录
File parent = file.getParentFile();
if (!parent.exists()) {
System.out.println(parent.mkdirs());//创建一个新的空文件夹
}
System.out.println(file.createNewFile());
//对文件重命名
File file1 = new File("/Users/prudence/Desktop/333");
File file2 = new File("/Users/prudence/Desktop/test/444.txt");
System.out.println(file1.renameTo(file2));// 将file表示文件重命名为f时,必须保证file是存在的文件
}
- 文件遍历与查找:
public static void main(String[] args) throws IOException {
String string = "/Users/prudence/Desktop/test";
method1(string);
System.out.println("===================================================");
method2(string);
System.out.println("===================================================");
method3(string);
}
//列出指定目录下所有子文件夹以及子文件
public static void method1(String path) {
File file = new File(path);
// 子文件或者子文件夹的名称
String[] arr = file.list();
for (String str : arr) {
System.out.println(str);
}
}
//列出指定目录下所有子文件夹以及子文件
public static void method2(String path) {
File file = new File(path);
//获取指定路径下所有File对象
File[] files = file.listFiles();
for (File f : files) {
if (f.isFile()) {
System.out.println("子文件:");
// 获取每个文件的名字
System.out.println(f.getName());
} else if (f.isDirectory()) {
System.out.println("子文件夹:");
System.out.println(f.getName());
}
}
}
//列出指定目录下所有后缀为.java的文件
public static void method3(String path){
File file = new File(path); String[] arr = file.list(); for(String str:arr) {
if (str.endsWith(".java")) {
System.out.println(str);
}
}
}
运行结果:
IO流
- 什么是IO流:
操作磁盘上资源时需要实现数据的输入和输出操作,磁盘上的文件和内存之间进行交互,数据的交互需要有一个媒介或者管道,把这个媒介或者管道称为IO流,也称为输入输出流。
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
- 分类:
按照流向分:
输入流:表示将数据读取到java程序(内存)中使用的流
输出流:表示从java程序(内存)向外传输使用的流
按照数据单位分:
字节流:一次性传输一个字节数据,将数据以字节的形式传输
字符流:一次性传输一个字符数据,将数据以字符的形式传输
按照层次分:
节点流:可以从或向一个特定的地方(节点)读写数据
处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写
字节流
- 字节输入流
InputStream --> FileInputStream
public static void main(String[] args) {
//创建被操作文件:此文件必须存在,否则读取时,抛出文件找不到异常
File file = new File("/Users/prudence/Desktop/abc.txt");
//声明流,不初始化
FileInputStream fis = null;
try {
// 初始化流
fis = new FileInputStream(file);
// 准备数组用来存储数据
byte[] b = new byte[3];
// 先定义一个变量,初始值是‐1
int i = -1;
// 定义一个计数循环的变量
int count = 0;
// while循环读取
while ((i = fis.read(b)) != -1) {
count++;
for (int j = 0; j < i; j++) {
System.out.print((char) b[j]);//读中文乱码
}
}
//计算循环读取的次数
System.out.println("count:" + count);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果:
- 字节输出流:
OutputStream --> FileOutputStream
public static void main(String[] args) {
//向文件中写入数据
//在工程中创建一个test文件夹,向test\\hello.txt中写入hello world
//第一步:创建被操作文件对象(当向一个文件中写入数据时,若文件不存在,程序会自动创建)
File file = new File("/Users/prudence/Desktop/test/ccc.txt");
FileOutputStream fos = null;
try {
// 第二步:创建流对象
fos = new FileOutputStream(file, true);
// 第三步:准备数据
String str = "hello world!";
byte[] b = str.getBytes();
System.out.println(b.length);//12
// 第四步:使用流写入
fos.write(b);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
// 第五步:刷新流,关闭流
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符流
- 字符输入流:
Reader --> InputStreamReader --> FileReader
FileReader:便利类,使用系统默认编码格式(Mac:utf-8),若要指定使用InputStreamReader
public static void main(String[] args) {
//1.将文件的路径转换为File对象
File file = new File("/Users/prudence/Desktop/abc.txt");
Reader reader = null;
try {
//2.实例化一个FileReader的对象
reader = new FileReader(file);
//3.定义一个数组
char[] arr = new char[8];//GBK乱码,Utf-8不乱码
//4.定义一个int的变量
int hasRead = 0;
//5.循环读取
while ((hasRead = reader.read(arr)) != -1) {
String result = new String(arr, 0, hasRead);
System.out.print(result);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果:
- 字符输出流:
Writter --> OutputStreamWritter --> FileWritter
FileWritter:便利类,使用系统默认编码格式(Mac:utf-8),若要指定使用OutputStreamWritter
public static void main(String[] args) throws IOException {
File file = new File("/Users/prudence/Desktop/test/ccc.txt");
Writer writer = new FileWriter(file);
//区别于字节流,可以直接传字符串
writer.write("从前有座山,山上有座庙");
writer.flush();
writer.close();
}
转换流
1、实现字节流到字符流的转换
2、解决中文乱码的问题:GBK、UTF-8
3、只有转换流可指定读取和写入的字符集
- 字节字符转换输入流:
InputStreamReader,将字节输入流转换为字符输入流
public static void main(String[] args) throws IOException {
//1.实例化File的对象
File file = new File("/Users/prudence/Desktop/aaa");
// 2.实例化输入流和转换输入流的对象
// 注意:当一个流的存在的意义是为了实例化另外一个流,则这个流不需要手动进行关闭
InputStream input = new FileInputStream(file);
InputStreamReader reader = new InputStreamReader(input);
// 使用默认的字符集【UTF-8】进行实例化转换流
//注:eclipse默认gbk,idea默认utf-8
// InputStreamReader reader = new InputStreamReader(new FileInputStream(new File("/Users/prudence/Desktop/aaa")));
// 使用指定字符集进行实例化转换流
// 字符集一般使用字符串直接传参,不区分大小写,如果字符集书写有误:java.io.UnsupportedEncodingException
// InputStreamReader reader = new InputStreamReader(new FileInputStream(new File("/Users/prudence/Desktop/aaa")),"GBK");//文件为utf-8编码则中文乱码
// 3.读取
char[] arr = new char[16];
int len = 0;
while ((len = reader.read(arr)) != -1) {
String string = new String(arr, 0, len);
System.out.print(string);
}
reader.close();
}
- 字节字符转换输出流:
OutputStreamWritter,将字节输出流转换为字符输出流
public static void main(String[] args) throws IOException {
//需求:将一段文本以utf-8的格式写入到文件中【注,文件格式为默认格式】
// 1.实例化File对象
// 注意:对于所有的输出流而言,文件可以不存在,在进行写入的过程中可以自动进行创建
// 但是,对于所有的输入流而言,文件必须先存在,然后才能操作,否则,会抛出 FileNotFoundException
File file = new File("/Users/prudence/Desktop/test/ccc.txt");
// 2.实例化转换输出流
// 如果不想覆盖源文件中的内容时,则在传参的时候,设置一个参数为true
//OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file,true));//idea默认"utf-8"
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file,true), "utf-8");
// 3.写入
writer.write("从前有座山,山上有座庙,庙里有个老和尚,老和尚对小和尚讲。。。");
// 4.刷新
writer.flush();
// 5.关闭
writer.close();
}
缓冲流
如果“字节流 - 转换流 - 字符流”主要是解决编码问题,缓冲流主要解决的就是流的速度问题,同时也增强了功能
Java flush()作用及适用场景 FileOutputStream BufferedOutputStream区别 缓冲区与字节数组的理解_myisam丶的博客-优快云博客
- 字节输入缓冲流:
InputStream --> BufferInputStream
主要是为了增强基础流的功能而存在的,提高了流的工作效率(读写效率)
public static void main(String[] args) throws IOException {
//实例化一个File对象
File file = new File("/Users/prudence/Desktop/test/ccc.txt");
// 实例化一个缓冲字节输入流的对象
BufferedInputStream input = new BufferedInputStream(new FileInputStream(file));
//读取
// byte[] arr = new byte[2 << 10];
// int len = 0;
// while ((len = input.read(arr)) != -1) {
// String string = new String(arr, 0, len);
// System.out.print(string);
// }
byte[] arr = new byte[6];
int len = input.read(arr);
String string = new String(arr, 0, len);
System.out.println(string);
input.mark(66);
len = input.read(arr);
string = new String(arr, 0, len);
System.out.println(string);
//实现了效果:覆水可收
input.reset();
len = input.read(arr);
string = new String(arr, 0, len);
System.out.println(string);
input.close();
}
运行结果:
- 字节输出缓冲流:
OutpuStream --> BufferedOutputStream
public static void main(String[] args) throws IOException {
// 实例化File对象
File file = new File("/Users/prudence/Desktop/test/ccc.txt");
// 实例化转换字节输出流
BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file, true));
// 写
output.write("有因必有果,你的报应就是我".getBytes());
// 刷新
output.flush();
// 关闭
output.close();
}
- 字符输入缓冲流:
Reader --> BufferedReader
public static void main(String[] args) throws IOException {
//实例化File对象
File file = new File("/Users/prudence/Desktop/test/ccc.txt");
// 实例化缓冲字符流的对象
BufferedReader reader = new BufferedReader(new FileReader(file));
// 方式一:read循环读取
// char[] arr = new char[8];
// int len = 0;
// while ((len = reader.read(arr)) != -1) {
// String string = new String(arr, 0, len);
// System.out.print(string);
// }
// 方式二:readLine循环读取
// String result1 = reader.readLine();
// System.out.println(result1);
// String result2 = reader.readLine();
// System.out.println(result2);
//reader.mark(666);
String result = "";
while ((result = reader.readLine()) != null){
System.out.println(result);
}
reader.close();
}
- 字符输出缓冲流:
Writter --> BufferedWritter
public static void main(String[] args) throws IOException {
// 实例化FIle对象
File file = new File("/Users/prudence/Desktop/test/ccc.txt");
// 实例化缓冲字符输出流
BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
// 换行
writer.newLine();
// 写
writer.write("奔涌吧,后浪!");
// 刷新
writer.flush();
// 关闭
writer.close();
}
字节流、转换流、缓冲流结合使用
BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(
new File("/Users/prudence/Desktop/test")), "GBK"));
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(
new File("/Users/prudence/Desktop/test"), true), "GBK"));
内存流
输入和输出都是从文件中来的,当然,也可将输出的位置设置在内存上,这就需需要ByteArrayInputStream和 ByteArrayOutputStream
InputStream --> ByteArrayInputStream:将内容写入到内存中
OutPutStream --> ByteArrayOutputStream:将内存中数据输出
public static void main(String[] args) throws IOException {
//定义一个字符串,全部由大写字母组成
String string = "HELLOWORLD";
// 内存输入流:向内存中输入内容,注意:跟文件读取不一样,不设置文件路径
//InputStream bis = new ByteArrayInputStream(string.getBytes());
ByteArrayInputStream bis = new ByteArrayInputStream(string.getBytes());
// 内存输出流:准备从内存中读取内容,注意:跟文件读取不一样,不设置文件路径
//OutputStream bos = new ByteArrayOutputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int temp = 0;
// read()方法每次只读取一个字符
while ((temp = bis.read()) != -1) {
// 将读取的数字转为字符
char c = (char) temp;
// 将字符变为小写
bos.write(Character.toLowerCase(c));
}
// 循环结束之后,所有的数据都在ByteArrayOutputStream中
// 取出内容,将缓冲区内容转换为字符串
String newString = bos.toString();
//关闭流
bis.close();
bos.close();
System.out.println(newString);//helloworld
}
以上的操作很好地体现了对象的多态。通过实例化其子类不同,完成的功能也不同,也就相当于输出的位置不同,如果是输入输出文件,则使用FileXxx,是内存则使用ByteArrayXxx
1、内存操作流的操作对象,一定是以内存为准,不要以程序为准
2、实际上此时可以通过向上转型,转换为OutputStream或InputStream
3、内存输出流在开发中经常使用到,一定要重点掌握
标准输入输出流
流的位置可以为“文件”、“内存”,也可以为“系统的 键盘&显示器”
Java的标准输入/输出分别通过 System.in 和 System.out 实现,默认情况下分别代表是键盘和显示器
- 标准输入流:
System.in ,默认情况下代表键盘
public static void main(String[] args) throws IOException {
FileInputStream inputStream = new FileInputStream(new File("/Users/prudence/Desktop/abc.txt"));
System.setIn(inputStream);
System.out.println("请输入内容:");
// 默认情况下是从控制台获取内容
// 但是如果使用setIn方法设置了重定向之后,将从指定文件中获取内容
Scanner sc = new Scanner(System.in);
String s1 = sc.next();
System.out.println(s1);
String s2 = sc.next();
System.out.println(s2);
// 功能上同 Scanner sc = new Scanner(inputStream);
// Scanner sc2 = new Scanner(inputStream);
// String s = sc2.next();
// System.out.println(s);
}
- 标准输出流:
System.out ,默认情况下代表显示器
public static void main(String[] args) throws IOException {
System.out.println("输出到控制台:hello world");
//创建打印流的对象
// 注意:默认打印到控制台,但是,如果采用setOut方法进行重定向之后,将输出到指定的文件中
PrintStream print = new PrintStream(new FileOutputStream(new File("/Users/prudence/Desktop/abc.txt")));
/** static void setErr(PrintStream err)
* 重新分配“标准”错误输出流。
* static void setIn(InputStream in)
* 重新分配“标准”输入流。
* static void setOut(PrintStream out)
* 重新分配“标准”输出流。
*/
//将标准输出重定向到print的输出流
System.setOut(print);
System.out.println("输出到文件:hello world");//每次运行都是对文件中已有内容的覆盖
}
流的基准与位置
普通流:以程序为准的输入输出
内存流:以内存为准的输入输出
系统(标准输入输出)流:以系统为准的输入输出,默认为键盘/显示器,可重定向
流的位置:文件、程序、内存、系统
- 将以内存为准的输入输出位置设为系统 System:
public static void main(String[] args) throws IOException {
System.out.println("请输入内容:");
Scanner scanner = new Scanner(System.in);
String next = scanner.next();
InputStream bis = new ByteArrayInputStream(next.getBytes());
OutputStream bos = new ByteArrayOutputStream();
int temp = 0;
while ((temp = bis.read()) != -1) {
char c = (char) temp;
bos.write(Character.toLowerCase(c));
}
String newString = bos.toString();
//关闭流
bis.close();
bos.close();
System.out.println(newString);
}
对象流
流中流动的数据是对象(流的单位:字节、字符、对象)
如果将一个对象写入到本地文件中,被称为对象的序列化
如果将一个本地文本中的对象读取出来,被称为对象的反序列化
注:一个对象流只能操作一个对象,如果试图采用一个对象流操作多个对象的话,会出现Exception(文件意外达到了文件末尾)
如果想将多个对象序列化到本地,可以借助集合(将多个对象添加到集合中,将集合的对象写入到本地文件中,再次读出来,获取到的仍然是集合对象,遍历集合)
- 对象输入流:
InputStream --> ObjectInputStream
OutputStream --> ObjectOutputStream
public class IOTest {
public static void main(String[] args) {
// objOutputStreamUsage();
objInputStreamUsage();
}
//写:将对象进行序列化
public static void objOutputStreamUsage() {
// 写:将对象进行序列化
// 1.实例化一个Person的对象
Person person = new Person("张三", 10, 'B');
// 2.实例化一个对象输出流的对象
ObjectOutputStream output = null;
try {
output = new ObjectOutputStream(new FileOutputStream(new File("/Users/prudence/Desktop/abc.txt")));
// 3.将对象写入到流中
output.writeObject(person);
// 4.刷新
output.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//读:反序列化
public static void objInputStreamUsage() {
try {
//1.实例化对象输入流的对象
ObjectInputStream input = new ObjectInputStream(new FileInputStream(new File("/Users/prudence/Desktop/abc.txt")));
//2.读取
Object object = input.readObject();
//3.对象的向下转型
if (object instanceof Person) {
Person p = (Person) object;
System.out.println(p);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
@Data
@AllArgsConstructor
class Person implements Serializable {
private String name;
private int age;
private char score;
}
运行结果:
注意:在使用对象流的时候,用于初始化对象流的参数只能是字节流(将对象转换为二进制的形式,然后再把二进制写入文件)
RandomAccessFile
RandomAccessFile 是用来访问那些保存数据记录的文件的,你就可以用seek方法来访问记录,并进行读写。这些记录的大小不必相同,但是其大小和位置必须是可知的。但是该类仅限于操作文件
RandomAccessFile 不属于 InputStream 和 OutputStream 类系的,实际上除了实现 DataInput 和 DataOutput 接口之外(DataInputStream 和 DataOutputStream 也实现了这两个接口),他和这两个类系毫不相干,甚至不使用 InputStream 和 OutputStream 类中已经存在的任何功能;
它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写的。这可能是因为 RandomAccessFile 能在文件里面前后移动,所以它的行为与其他的 I/O 类有些根本性的不同。总而言之,它是一个直接继承Object 的,独立的类
- 基本方法:
public static void main(String[] args) throws IOException {
RandomAccessFile file = new RandomAccessFile("/Users/prudence/Desktop/test/bbb.txt", "rw");
// 以下向file文件中写数据
file.writeInt(20);// 占4个字节
file.writeDouble(8.236598);// 占8个字节
// 这个长度写在当前文件指针的前两个字节处,可用readShort()读取
file.writeUTF("这是一个UTF字符串");
file.writeBoolean(true);// 占1个字节
file.writeShort(395);// 占2个字节
file.writeLong(2325451L);// 占8个字节
file.writeUTF("又是一个UTF字符串");
file.writeFloat(35.5f);// 占4个字节
file.writeChar('a');// 占2个字节
// 把文件指针位置设置到文件起始处
file.seek(0);
// 以下从file文件中读数据,要注意文件指针的位置
System.out.println("——————从file文件指定位置读数据——————");
System.out.println(file.readInt());
System.out.println(file.readDouble());
System.out.println(file.readUTF());
//将文件指针跳过3个字节,本例中即跳过了一个boolean值和short值。
file.skipBytes(3);
System.out.println(file.readLong());
//跳过文件中"又是一个UTF字符串"所占字符
//注意readShort()方法会移动文件指针,所以不用写具体字节数
file.skipBytes(file.readShort());
System.out.println(file.readFloat());
//以下演示文件复制操作
System.out.println("--------文件赋值(从file到copy)--------");
file.seek(0);
RandomAccessFile fileCopy = new RandomAccessFile("/Users/prudence/Desktop/test/ddd.txt", "rw");
int len = (int) file.length();//取得文件长度(字节数)
byte[] b = new byte[len];
//全部选取
file.readFully(b);
fileCopy.write(b);
System.out.println("复制完成!");
}
运行结果:
- 向指定位置插入数据:
public static void main(String[] args) throws IOException {
try {
insert(1, "java", "/Users/prudence/Desktop/test/bbb.txt");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param skip 跳过多少字节进行数据插入
* @param str 要插入的字符串
* @param fileName 文件路径
* @throws Exception
*/
public static void insert(long skip, String str, String fileName) throws Exception {
RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
if (skip < 0 || skip > raf.length()) {
System.out.println("跳过字节数无效");
return;
}
byte[] b = str.getBytes();
raf.setLength(raf.length() + b.length);
for (long i = raf.length() - 1; i > b.length + skip - 1; i--) {
raf.seek(i - b.length);
byte temp = raf.readByte();
raf.seek(i);
raf.writeByte(temp);
}
raf.seek(skip);
raf.write(b);
raf.close();
}
Properties
java.util 包中,Map 接口实现类,Hashtable<Object,Object> 子类
Properties文件中元素也是以键值对的形式存在的
1、注释内容由 # 或者! 开头, 如果# 或者!不在开头,则不作为注释
2、key,value之间用 = 或者 : 分隔
一行中既有 = 也有 : 时,第一个(或者=或者:)将作为key,value分隔符
3、key 不能换行,value可以换行,换行符是\ ,且换行后的\t、空格都会忽略
public static void main(String[] args) throws IOException {
//1.实例化一个Properties的对象
Properties pro = new Properties();
System.out.println(pro);
// 2.把文件userlist.properties中的键值对同步到集合中
// 实质:读取
/**
* void load(InputStream inStream)
* 从输入流中读取属性列表(键和元素对)。
*/
pro.load(new BufferedInputStream(new FileInputStream(new File("/Users/prudence/Desktop/test/test.properties"))));
System.out.println(pro);
//3.向集合中添加一对键值对
/**
* Object setProperty(String key, String value)
* 调用 Hashtable 的方法 put。
*/
pro.setProperty("address1", "china");
System.out.println(pro);
//4、store
//实质:写入
//comments:工作日志
pro.store(new BufferedOutputStream(new FileOutputStream(new File("/Users/prudence/Desktop/test/test.properties"))), "add a pair of key and value");
}
运行结果: