目录
非文本文件复制( FileInputStream、FileOutputStream)
非文本文件复制 BufferedInputStream、BufferedOutputStream
文本复制(BufferedReader、BufferedWriter)
File类
File类的使用
1、File类的一个对象,代表一个文件或一个文件目录(俗称文件夹)
2、 File类生命在java.io包下
3. File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,
并未涉及到写入或读取文件内容的操作。如果需要读取或写入文件内容,必须使用I0流来完成。
4.后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的”终点".
构造器
代码:输出文件路径,并没有创建文件
public static void main(String[] args) {
//构造器1:
File file1=new File("hello.txt"); //相对路径,相对于当前nodule
File file2=new File("D:\\IDEA项目\\hi.txt"); //绝对路径
System.out.println(file1);//hello.txt
System.out.println(file2);//D:\IDEA项目\hi.txt
//构造器2
File file3=new File("D:\\IDEA项目","1.txt");
System.out.println(file3);//D:\IDEA项目\1.txt
//构造器3
File file4=new File(file3,"2.txt");
System.out.println(file4);//D:\IDEA项目\1.txt\2.txt
}
常用方法
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 isDirectory():判断是否是文件目录
public boolean isFile() :判断是否是文件
public boolean exists():判断是否存在
public booLean canRead() :判断是否可读
public boolean canWrite():判断是否可写
public boolean isHidden() :判断是否隐藏
移动文件:
public boolean renameTo(File dest):把文件重命名为指定的文件路径
比如:file1.renameTo(file2)为例,将file1重命名为file2
要想保证返回true,需要file1在硬盘中是存在的,file2是不存在的
创建硬盘中对应的文件或文件目录
public boolean createNewFile() :创建文件。若文件存在,则不创速,返回false
public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。如果此文件目录的上层目录不存在,也不创建
public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建
删除磁盘中的文件或文件目录
public boolean delete(): 删除文件或者文件夹删除文件夹时必须先把文件夹内的文件删光才可以删除文件夹
删除注意事项:
Java中的删除不走回收站。
代码:
public static void main(String[] args) throws IOException {
File file1 = new File("hi.txt");
if (!file1.exists()) {
file1.createNewFile();
System.out.println("创建成功");
} else {//文件存在
file1.delete();
System.out.println("删除成功");
}
IO流
流的分类
按数据单位分为字节流和字符流
按照流向分为输入流和输出流
按照角色为节点流和处理流
IO流体系
文件流
访问文件的那行是节点流 (文件流)
FileInputStream 方法: ( read(byte[ ] buffer) )
FileOutputStream 方法: ( write(byte[ ] buffer,0,len) )
FileReader 方法: ( read(char[ ] cbuf) )
FileWrite 方法: ( write(char[ ] cbuf,0,len) )
案例一:FileReader
read():返回读入的一个字符,如果达到文件末尾返回-1
异常的处理,要用到try-catch-finally,否则流出异常会无法关闭,或者没有读取到文件时关闭时空指针异常。
读入的文件不存在会出现FileNotFoundException
FileReader fileReader = null;
try {
File file = new File("D:\\IDEA项目\\day106\\hello.txt");
//提供具体的流
fileReader = new FileReader(file);
//数据读入
//read():返回读入的一个字符,如果达到文件末尾返回-1
int data = fileReader.read();
while (data != -1) {
System.out.print((char) data);
data = fileReader.read();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、回收流
try {
if(fileReader!=null) //判断不为空才释放
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
read()的重载:read(char[] cbuf):返回每次读入cbuf数组中每个字符的个数,达到文件末尾,返回-1。
注意:cbuf [ 5 ] 数组每次从file中读取5个字符,如果文件中剩余字符不足五个,那就把从0开始读进数组中,但是数组后面的上次读取的数据不会清空。
例:helloworld123,输出的字符数组分别为hello world 123ld是
FileWriter
从内存中写出数据到硬盘的文件里
1、输出操作,对应的File可以不存在,并不会报异常
2、File对应的硬盘中文件如果不存在,在输出的过程中,会自动创建此文件
File对应的硬盘中文件如果存在:
如果构造器是FileWriter(file,false)/ FileWriter(file):对原有文件覆盖
如果流使用的构造器是FileWriter(file,true):不会对原文件覆盖,而是在原文件上追加
public static void main(String[] args) {
FileWriter fw = null;
try {
//1、提供File类对象,指明写出到的文件
File file = new File("hello1.txt");
//2、提供FileWriter对象,用于数据写出
fw = new FileWriter(file);
//3、写出操作
fw.write("hello!");
fw.write("hello!");
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、资源关闭
try {
if(fw!=null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件复制
例:从一个文件中读取内容放入另一个文件中
注:不能使用字符流处理字节文件(例如图片)
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
//1、提供File类对象,指明写出\读入的文件
File file1 = new File("hello.txt");
File file2 = new File("hello1.txt");
//2、提供FileWriter\FileReader对象,用于数据写出\读入
fr = new FileReader(file1);
fw = new FileWriter(file2);
//3、操作
char[] cbuf = new char[5];
int len; //记录每次读取到cbuf数组中的长度
while ((len = fr.read(cbuf)) != -1) {//判断没有读取到末尾
fw.write(cbuf, 0, len); //读取数组中 [0,len)的字符
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、关闭流
try {
if (fw != null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileInputStream
操作与字符流一致
读取文件,如果文件中有中文,可能会出现乱码,因为中文使用3个byte存储的(在UTF-8中),无法完整读出
总结:
文本文件(.txt | .java |.c |.cpp)用字符流处理
非文本文件(.jpg | .avi | .mp3 | .doc | .ppt ...)用字节流处理
public static void main(String[] args) {
FileInputStream fis= null;
try {
//1、造文件
File file=new File("hello.txt");
//2、造流
fis = new FileInputStream(file);
//3、读数据
byte[] buf=new byte[5];
int len;
while((len=fis.read(buf))!=-1){
String s=new String(buf,0,len);
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、关闭流
try {
if(fis!=null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
非文本文件复制( FileInputStream、FileOutputStream)
public class IOTest {
public static void main(String[] args) {
long start= System.currentTimeMillis();
String srcPath = "美女.jpg";
String destPath = "美女2.jpg";
copyFile(srcPath, destPath);
long end= System.currentTimeMillis();
System.out.println("复制共花费 "+(end-start)+" 毫秒"); //复制共花费 246 毫秒
}
public static void copyFile(String srcPath,String destPath){
FileInputStream fis= null;
FileOutputStream fos= null;
try {
//1、造文件
File srcfile=new File(srcPath);
File destfile=new File(destPath);
//2、造流
fis = new FileInputStream(srcfile);
fos = new FileOutputStream(destfile);
//3、读数据
byte[] buf=new byte[5];
int len;
while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、关闭流
try {
if(fis!=null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fos!=null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
缓冲流
处理流之一:套接在已有流上的流
BufferInputStream 方法:( read(byte[ ] buffer) )
BufferOutputStream 方法:( write(byte[ ] buffer,0,len) / flush())
BufferReader 方法:( read(byte[ ] cbuf) / readLine() )
BufferWriter 方法:( write(char[ ] cbuf,0,len) / flush() )
flush()方法:刷新缓冲区,先把缓冲区中的内容写出去
对比字节流,缓冲流的速度快很多,因为缓冲流内部提供了缓冲区 。
例如:
非文本文件复制 BufferedInputStream、BufferedOutputStream
public class IOTest {
public static void main(String[] args) {
long start= System.currentTimeMillis();
String srcPath = "美女.jpg";
String destPath = "美女2.jpg";
copyFile(srcPath, destPath);
long end= System.currentTimeMillis();
System.out.println("复制共花费 "+(end-start)+" 毫秒"); //复制共花费 44 毫秒
}
public static void copyFile(String srcPath, String destPath) {
FileInputStream fis = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
BufferedInputStream bis = null;
try {
//1、造文件
File srcfile = new File(srcPath);
File destfile = new File(destPath);
//2.1、造节点流
fis = new FileInputStream(srcfile);
fos = new FileOutputStream(destfile);
//2.2 造缓冲流
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//3、读数据
byte[] buf = new byte[10];
int len;
while ((len = bis.read(buf)) != -1) {
bos.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、关闭流,先关外层,再关内层
try {
if(bos!=null)
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(bis!=null)
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
//关闭外层流的同时内层流也会自动关闭,所以内层流关闭可省略
try {
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
文本复制(BufferedReader、BufferedWriter)
public class IOTest {
public static void main(String[] args) {
long start= System.currentTimeMillis();
String srcPath = "hello.txt";
String destPath = "hello1.txt";
copyFile(srcPath, destPath);
long end= System.currentTimeMillis();
System.out.println("复制共花费 "+(end-start)+" 毫秒"); //复制共花费 2 毫秒
}
public static void copyFile(String srcPath, String destPath) {
BufferedWriter bw = null;
BufferedReader br = null;
try {
//1、造文件 2.1、造节点流 2.2 造缓冲流
br = new BufferedReader(new FileReader(new File(srcPath)));
bw = new BufferedWriter(new FileWriter(new File(destPath)));
//3、读数据
//方式一:
// char[] buf = new char[10];
// int len;
// while ((len = br.read(buf)) != -1) {
// bw.write(buf, 0, len);
// }
//方式二:
String data;
while((data=br.readLine())!=null){
//方法一:
bw.write(data+"\n");//data不包含换行符,可以手动加入
//方法二:
bw.write(data);
bw.newLine(); //换行
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、关闭流,关外层,内层自动关闭
try {
if(bw!=null)
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(br!=null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
文件加密
在write写入之前,让读取的数据异或一个值,然后会读取到异或后的数据,相当于加密过程
解密时,将加密过的文件读取到的数据再次异或该值,就会变成加密前的数据。
例如:
public class IOTest {
public static void main(String[] args) {
long start= System.currentTimeMillis();
String srcPath = "hello.txt";
String destPath = "hello1.txt";
copyFile(srcPath, destPath);
long end= System.currentTimeMillis();
System.out.println("复制共花费 "+(end-start)+" 毫秒"); //复制共花费 1 毫秒
}
public static void copyFile(String srcPath, String destPath) {
BufferedWriter bw = null;
BufferedReader br = null;
try {
//1、造文件 2.1、造节点流 2.2 造缓冲流
br = new BufferedReader(new FileReader(new File(srcPath)));
bw = new BufferedWriter(new FileWriter(new File(destPath)));
// 3、读数据
char[] buf = new char[10];
int len;
while ((len = br.read(buf)) != -1) {
for(int i=0;i<len;i++)
buf[i]= (char) (buf[i]^5);
bw.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、关闭流,先关外层,再关内层
try {
if(bw!=null)
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(br!=null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
加密后变为
解密:只是将加密代码的文件名改了
public class IOTest {
public static void main(String[] args) {
long start= System.currentTimeMillis();
String srcPath = "hello1.txt";
String destPath = "hello2.txt";
copyFile(srcPath, destPath);
long end= System.currentTimeMillis();
System.out.println("复制共花费 "+(end-start)+" 毫秒"); //复制共花费 2 毫秒
}
public static void copyFile(String srcPath, String destPath) {
BufferedWriter bw = null;
BufferedReader br = null;
try {
//1、造文件 2.1、造节点流 2.2 造缓冲流
br = new BufferedReader(new FileReader(new File(srcPath)));
bw = new BufferedWriter(new FileWriter(new File(destPath)));
// 3、读数据
char[] buf = new char[10];
int len;
while ((len = br.read(buf)) != -1) {
for(int i=0;i<len;i++)
buf[i]= (char) (buf[i]^5);
bw.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、关闭流,先关外层,再关内层
try {
if(bw!=null)
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(br!=null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
解密后文件
转换流
1、属于字符流,处理流之二
2、InputStreamReader:将字节的输入流转换为字符的输入流
OutputStreamWriter:将字符的输出流转换为字节的输出流
3、解码:字节、字节数组 --> 字符数组、字符串
编码:字符数组、字符串 --> 字节、字节数组
4、字符集
例如:InputStreamReader利用字符集,实现字节输入流到字符输入流的转换
public static void main(String[] args) {
InputStreamReader isr= null;
try {
//1、造文件
FileInputStream fis=new FileInputStream("hello.txt");
//2、造流
//参数2指明了字符集,具体使用哪个字符集,取决于文件保存时使用的字符集
isr = new InputStreamReader(fis,"UTF-8");
//3、读取操作
char[] cbuf=new char[20];
int len;
while ((len=isr.read(cbuf))!=-1){
String s=new String(cbuf,0,len);
System.out.print(s);hello中国
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、关闭流
if(isr!=null) {
try {
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
综合测试:InputStreamReader、OutputStreamWriter
以UTF-8的字符集读取文件,以gbk的字符集写入数据(会出现乱码,读写字符集要保持相同才可以不乱码)
public static void main(String[] args) {
InputStreamReader isr= null;
OutputStreamWriter osw=null;
try {
FileInputStream fis=new FileInputStream("hello.txt");
FileOutputStream fos=new FileOutputStream("hello_gbk.txt");
//参数2指明了字符集,具体使用哪个字符集,取决于文件保存时使用的字符集
isr = new InputStreamReader(fis,"UTF-8");
osw = new OutputStreamWriter(fos,"gbk");
char[] cbuf=new char[20];
int len;
while ((len=isr.read(cbuf))!=-1){
osw.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(isr!=null) {
try {
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
if(osw!=null)
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符集
ASCII:美国标准信息交换码。(英文够用)
用一个字节的7位可以表示
ISO8859-1:拉丁码表。欧洲码表
用一个字节的8位表示。
GB2312: 中国的中文编码表。最多两个字节编码所有字符
GBK: 中国的中文编码表升级,融合了更多的中文文字符号(包含简体繁体)。最多两个字节编码
如何分辨两个字节存储的是一个字符还是两个字符?如果字节首位为0,表示该字节单独 存储一个字符,如果字节首位为1,表示两个字节存储一个字符
Unicode: 国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一 的字符码。所有文 字都可以用两个字节来完成。
问题:1、英文用一个字节就够了
2、如何分辨两个字节存储的是一个字符还是两个字符?
3、如果和GBK一样的处理方式,字节首位被占用,那么就会少很多值来表示字符。
互联网的出现解决了该问题:
UTF-8的编码方式(Unicode字符集只是定义了字符的集合和位移编号,是对UTF_8等具体 编码方案的统称,不是具体的编码方案)
UTF-8: 变长的编码方式,可用1- 6个字节来表示一个字符。
例:110xxxxx 10xxxxxxx,首位两个1代表要将两个个字节中的xxx拼凑到一起,然后按二进制方式拼成一个字符
11110xxx 10xxxxxxx 10xxxxxx 10xxxxxx ,首位四个1代表要将四个字节中的xxx拼凑到一起,然后按二进制方式拼成一个字符
ANSI编码,通常指的是平台默认编码,英文操作系统默认是ISO8859-1,中文默认是GBK
标准输入输出流 \打印流\数据流
输入输出流
System.out:默认从控制台输出
System.in :默认从键盘输入
修改输入输出默认设备
public static void setIn(InputStream in)
public static void setOut(OutputStream out)
打印流
PrintStream PrintWriter
提供了一系列重载的print、println等方法,用于多种数据类型的输出
不会抛IO异常
有自动flush功能
PrintStream打印的所有字符都使用平台的默认字符编码转换为字节,在需要写入字符的情况下,使用PrintWriter类
System.out返回的是类型
数据流
DataInputStream、DataOutputStream
用于读取或写出基本数据类型的变量或字符串
DatalnputStream 中的方法
boolean readBoolean()
byte readByte()
char readChar()
float readFloat()
double readDouble()
short readShort()
long readLong()
int readlnt()
String readUTF()
void readFully(byte[] b)
DataOutputStream中的方法,将上述方法read改为对应的write
将内存中的基本数据类型变量和字符串写入到文件
public static void main(String[] args) {
dataWrite(); //写入
dataread(); //读出
}
public static void dataWrite() {
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new FileOutputStream("hello.txt"));
dos.writeUTF("老王");
dos.flush();
dos.writeInt(23);
dos.flush();
dos.writeBoolean(true);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void dataread() {
DataInputStream dis = null;
try {
dis = new DataInputStream(new FileInputStream("hello.txt"));
//按存储的顺序读取
String name = dis.readUTF();
int age = dis.readInt();
boolean isMale = dis.readBoolean();
System.out.println(name + " " + age + " " + isMale);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
对象流
ObjectInputStream ObjectOutputStream
存储和读取基本数据类型数据或对象的处理流,强大之处:可以把java对象写入数据源,也能把对象从数据源中还原回来
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。//当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
反序列化:ObjectInputStream类读取基本类型数据或对象的机制
不能序列化static 和transient修饰的成员变量
NotSerializableException异常:对象不可序列化
序列化的对象需满足以下要求:
1、必须实现两个接口之一:Serializable、Externalizable
Serializable常用,且接口中没有方法,仅代表可序列化
2、必须声明一个全局常量public static final long seriaVersionUID=一个唯一的标识符
如果没有显示声明,运行时根据类的内部自动生成,如果类做了改变,seriaVersionUID值会 修改,然后可能导致出现错误
3、除了序列化的类需要实现Serializable接口之外,还必须保证内部所有属性也必须是可序列化的 (默认情况下,基本数据类型可序列化,包括String)
如果类内存在自定义类,则自定义类也需要实现Serializable接口和唯一标识符
对象的写入和读出
//序列化,将内存中的java对象写入文件中
public void objectOutputStreamTest() {
ObjectOutputStream oos = null;
try {
//1、造文件
FileOutputStream file = new FileOutputStream("java.dat");
//2、造流
oos = new ObjectOutputStream(file);
//3、操作
oos.writeObject(new String("我爱中国"));
oos.flush();
oos.writeObject(new Person("Tom", 22));
oos.flush();
oos.writeObject(new Person("Jerry", 22));
oos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、关闭流
try {
if (oos != null)
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void objectInputStreamTest() {
ObjectInputStream ois = null;
try {
//1、造文件
FileInputStream file = new FileInputStream("java.dat");
//2、造流
ois = new ObjectInputStream(file);
//3、操作,按写入的顺序读取
Object o1 = ois.readObject();
String s = (String) o1;
System.out.println(s);//我爱中国
Object o2 = ois.readObject();
Person p1 = (Person) o2;
System.out.println(p1);Person{name='Tom', age=22}
Object o3 = ois.readObject();
Person p2 = (Person) o3;
System.out.println(p2);Person{name='Jerry', age=22}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
//4、关闭流
try {
if (ois != null)
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
随机存取文件流
RandomAccessFile
java.io包下
1、实现了DataInput、DataOutput,两个接口,可以读也可以写,既可以作为输入流也可以作为输出流。
2、支持“随机访问”的方式,程序可以直接跳转到任意地方读写文件
支持只访问文件的部分内容
可以向已存在的文件后追加内容
写文件时如果文件不存在可以自动创建文件
如果文件已经存在,那么会从文件首部开始一个字符一个字符的覆盖
3、实例化需要制定一个mode参数,指定访问模式
r:以只读方式打开
rw:打开以便读取和写入
rwd:打开以便读取和写入,同步文件内容的更新
rws:打开以便读取和写入,同步文件内容和元数据的更新
4、内部存在指针,用来表示当前读写的位置,可以自由移动记录指针
long getFilePointer():获取文件记录指针的当前位置
void seek(long pos):将文件记录指针定位到pos位置
利用指针实现插入操作,先将指针移动到自己想插入数据的位置,再读取指针后面的内容存储到数组中,然后写入自己想插入的数据,再将保存在数组中的数据写入文件(比较费内存,因为要存储后面的内容)
public static void insertRandomAccessFileTest(){
RandomAccessFile raf= null;
try {
//造文件、造流
raf = new RandomAccessFile("hello.txt","rw");
//操作
//指针调整到索引为2的位置
raf.seek(2);
//指针后面的数据先保存在StringBuffer中
StringBuffer sb=new StringBuffer("hello.txt".length());
byte[] buf=new byte[20];
int len;
while((len=raf.read(buf))!=-1){
//StringBuffer的append不能添加byte类型,所以先用字符串封装
sb.append(new String(buf,0,len));
}
//指针再次移向2,开始写入
raf.seek(2);
raf.write("I love you".getBytes());
//StringBuffer没有getBytes方法,所以先转换为String
raf.write(sb.toString().getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
try {
if(raf!=null)
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
JDK9新特性
InputStream的新方法tranferTo()
把输入流中的说有数据直接自动复制到输出流中
也就是将这一段代码
//3、读数据
byte[] buf=new byte[5];
int len;
while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
替换为fis.transferTo(fos);
NIO.2中Path、Paths、Files类的使用
NIO.2在JDK1.7中发布,针对原有的文件IO操作进行了优化及封装,并支持Asynchronous IO。File类功能有限,大多数方法再出错时只返回失败但不提供异常信息
为了弥补这种不足,引入Path。
Paths包含两个返回Path的静态工厂方法
Path常用方法:
➢String toString():返回调用Path对象的字符串表示形式
➢boolean startsWith(String path) :判断是否以path路径开始
➢boolean endsWith(String path) :判断是否以path路径结束
➢boolean isAbsolute() :判断是否是绝对路径
➢Path getParent();返回Path对象包含整个路径,不包含Path对象指定的文件路径
➢Path getRoo():返回调用Path对象的根路径➢Path getFileName(:返回与调用Path对象关联的文件名
➢int getNameCount( :返回Path根目录后面元素的数量
➢Path getName(int idx):返回指定索引位置idx的路径名称
➢Path toAbsolutePath():作为绝对路径返回调用Path对象
➢Path resolve(Path p):合并两个路径,返回合并后的路径对应的Path对象
➢File toFile():将Path转化为File类的对象
Paths类提供的静态get()方法用来获取Path对象:
➢static Path get(String first, String ... more):用于将多个字符串串连成路径➢static Path get(URI uri);返回指定uri对应的Path路径
java.nio.file.Files用于操作文件或目录的工具类
Files常用方法:
➢Path copy(Path src, Path dest, CopyOption ... how):文件的复制
➢Path createDirectory(Path path, FileAttribute<?> ... attr): 创建-一个目录➢Path createFile(Path path, FileAtribute<?> ... arr):创建一个文件
➢void delete(Path path):删除个文件/目录, 如果不存在, 执行报错
➢void deletelfExists(Path path): Path对应的文件/目录如果存在,执行删除➢Path move(Path src, Path dest, CopyOption..how):将src移动到dest位置➢long size(Path path):返回path指定文件的大小