文件类概述和构造方法
File:它是文件和目录路径名的抽象示
- 文件和目录是可以通过File封装成对象的
- 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已.它可以是存在的,也可以是不存在的.
- 将来是要通过具体的操作把这个路径的内容转换为具体存在的
public boolean createNewFile():
如果文件不存在,就创建文件,并返回true
如果文件存在,就不创建文件,并返回false
public boolean mkdir():
如果目录不存在,就创建目录,并返回true
如果目录存在,就不创建目录,并返回false
(creatNewFile和mkdir的区别是一个是创建文件,一个是创建目录)
public boolean mkdirs():
如果目录不存在,就创建目录,并返回true
如果目录存在,就不创建目录,并返回false
(mkdir和mkdirs的区别是一个是创建单个目录,一个可以创建多级目录)
比如如果我们这样子
得到的不是txt文件 而是名为“javase.txt”的目录
所以我们要看方法来判断创建的是文件还是目录
再次总结:creatNewFile()是创建文件,mkdir()和mkdirs()是创建目录。
绝对路径和相对路径的区别
●绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件。例如: E:\itcast\Vjava.txt
●相对路径:必须使用取自其他路径名的信息进行解释。例如: myFile\Vjava.txt
的删除目录时的注意事项:
●如果一个目录中有内容(目录, 文件),不能直接删除。应该先删除目录中的内容,最后才能删除目录
import java.io.File;
import java.io.IOException;
public class FileDemo4 {
public static void main(String[] args) throws IOException {
//创建一个File对象
File f = new File("File\\java.txt");
//f.createNewFile();
// public boolean isDirectory(): 测试此抽象路径名表示的File是否为目录
// public boolean isFile(): 测试此抽象路径名表示的File是否为文件
// public boolean exists(): 测试此抽象路径名表示的File是否存在
System.out.println(f.isDirectory());
System.out.println(f.isFile());
System.out.println(f.exists());
System.out.println("--------");
// public String getAbSplutePath(): 返回此抽象路径名的绝对路径名字符串
// public String getPath(): 将此抽象路径名转换为路径名字符串
// public String getName():返回由此抽象路径名表示的文件或目录的名称
System.out.println(f.getAbsolutePath());
System.out.println(f.getPath());
System.out.println(f.getName());
System.out.println("--------");
// public String[] list(): 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
// public File[] listFiles(): 返回此抽象路径名表示的目录中的文件和目录的File对象数组
File f2 = new File("E:\\itcast");
String[] strArray = f2.list();
for(String str : strArray)
{
System.out.println(str);
}
System.out.println("--------");
File[] fileArray = f2.listFiles();
for(File file : fileArray)
{
System.out.println(file);
}
System.out.println("--------");
//得到绝对路径的意义是可以调用File方法进行操作
for(File file : fileArray)
{
if(file.isFile())
System.out.println(file);
}
}
}
得到结果
false
true
true
--------
E:\untitled2\File\java.txt
File\java.txt
java.txt
--------
java.txt
JavaSE
javase.txt
JavaWEB
--------
E:\itcast\java.txt
E:\itcast\JavaSE
E:\itcast\javase.txt
E:\itcast\JavaWEB
--------
E:\itcast\java.txt
I0流分类:
按照数据的流向
输入流:读数据
输出流:写数据按照数据类型来分
字节流
字节输入流,字节输出流
字符流
字符输入流,字符输出流
一般来说, 我们说IO流的分类是按照数据类型来分的
如果数据通过Window自带的记事本软件打开,我们还可以读懂里面的内容,就使用字符流,
否则使用字节流。如果你不知道该使用哪种类型的流,就使用字节流。
一个利用getBytes实现的输入字符串的简便方法:
文件输出流对象.write("我是要输入的字符串".getBytes());
1:字节流写数据如何实现换行呢?
写完数据后加换行符号(不同系统换行符不同)
window: \r\n
Linux: \n
mac: \r
2:字节流写数据如何实现追加写入呢?public FileOutputStream (String. name, boolean append)
在创建文件输出流时用该方法指定追加写入
如果第二个参数为true,则字节将写入文件的末尾而不是开头
finally :在异常处理时提供finally块来执行所有清除操作。比如说IO流中的释放资源
特点:被finally控制的语句一定会执行,除非JVM退出
格式:
如果文件路径不存在为null,则无需close。
用循环输出文件数据直至末尾读完文件
首次用read函数读数据返回的是字符所对应的ascall码,所以是int类型,我们如果想原样输出,就在输出时加一个char强转。
另外,注意输出System.out.print()不要加ln哦,要换行的地方循环会识别到,无需手动换行。
当文件都到末尾时,读到空返回的是null。
所以代码是这样子的
int by;
while(by=file.read()!=-1){
System.out.print((char)by);
}
思路:
①根据数据源创建字节输入流对象
②根据目的地创建字节输出流对象
③读写数据,复制图片(一次读取一个字节数组,一次写入一个字节数组)
④释放资源
●BufferOutputStream: 该类实现缓冲输出流。通过设置这样的输出流, 应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
●BufferedInputStream: 创建BufferedInputStream将创建一 个内部缓冲区数组。 当从流中读取或跳过字节时, 内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节
构造方法:(注意:参数类型为字节流哦)
●字节缓冲输出流: BufferedOutputStream(OutputStream out)
●字节缓冲输入流: BufferedInputStream(InputStreamin)
为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?●字节缓冲流仅仅提供缓冲区, 而真正的读写数据还得依靠基本的字节流对象进行操作
ps:不要因为字节缓冲流中有个缓字就以为它比普通字节流慢!!因为字节缓冲流可以一次内部缓冲很多内容,所以它是更快的!!faster!!在后面的传输视频处就可以体现字节缓存流的优越性
通过实操体现字节缓存流的优越性
测试得到的结果
四种方式实现复制视频,并记录每种方式复制视频的时间
1:基本字节流一次读写-一个字节 共耗时:285557毫秒
2:基本字节流一次读写一个字节数组 共耗时:413毫秒
3:字节缓冲流一次读写一 个字节 共耗时:2693毫秒
4:字节缓冲流一次读写一 个字节数组 共耗时:124毫秒
import java.io.*;
/*
//待复制视频地址:C:\Users\静砸今天开心了嘛\Desktop\CodeShortFilm.mp4
思路:
1.根据数据源创建字节输入流对象
2.根据目的地创建字节输出流对象
3.读写数据,复制视频
4.释放资源
四种方式实现复制视频,并记录每种方式复制视频的时间
1:基本字节流一次读写-一个字节 共耗时:285557毫秒
2:基本字节流一次读写一个字节数组 共耗时:413毫秒
3:字节缓冲流一次读写一 个字节 共耗时:2693毫秒
4:字节缓冲流一次读写一 个字节数组 共耗时:124毫秒
*/
public class FileDemo6 {
public static void main(String[] args) throws IOException {
//记录开始时间
long startTime = System.currentTimeMillis();
//复制视频
// method1();
// method2();
// method3();
method4();
//记录结束时间
long endTime = System.currentTimeMillis();
System.out.println("共耗时:"+(endTime-startTime)+"毫秒");
}
//基本字节流一次读写-一个字节
public static void method1() throws IOException {
//C:\Users\静砸今天开心了嘛\Desktop\CodeShortFilm.mp4
FileInputStream fis = new FileInputStream("C:\\Users\\静砸今天开心了嘛\\Desktop\\CodeShortFilm.mp4");
FileOutputStream fos = new FileOutputStream("E:\\untitled2\\视频.mp4");
int by;
while((by=fis.read())!=-1){
fos.write(by);
}
fos.close();
fis.close();
}
//基本字节流一次读写一个字节数组
public static void method2() throws IOException {
//C:\Users\静砸今天开心了嘛\Desktop\CodeShortFilm.mp4
FileInputStream fis = new FileInputStream("C:\\Users\\静砸今天开心了嘛\\Desktop\\CodeShortFilm.mp4");
FileOutputStream fos = new FileOutputStream("E:\\untitled2\\视频.mp4");
byte[] bys = new byte[1024];
int len;
while((len=fis.read(bys))!=-1){
fos.write(bys,0,len);
}
fos.close();
fis.close();
}
//字节缓冲流一次读写一个字节
public static void method3() throws IOException {
//C:\Users\静砸今天开心了嘛\Desktop\CodeShortFilm.mp4
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\静砸今天开心了嘛\\Desktop\\CodeShortFilm.mp4"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\untitled2\\视频.mp4"));
int by;
while((by=bis.read())!=-1){
bos.write(by);
}
bos.close();
bis.close();
}
//字节缓冲流一次读写一 个字节数组
public static void method4() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\静砸今天开心了嘛\\Desktop\\CodeShortFilm.mp4"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\untitled2\\视频.mp4"));
byte[] bys = new byte[1024];
int len;
while((len= bis.read(bys))!=-1){
bos.write(bys,0,len);
}
bis.close();
bos.close();
}
}
编码表
按照某种规则,将字符存储到计算机中,称为编码。
反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码。
ps:按照A编码存储,必须按照A编码解析,才能显示正确的文本符号,否则就会导致乱码现象
常见字符集:ASCll字符集,GBXXX字符集,Unicode字符集
常见编码表:GBK(最常用中文码表),GB18030(最新中文码表),UTF-8编码
【这里与字节流的区别就是字节流是读写字节(byte或byte[ ])数据,而字符流是读写字符(char或char[ ])数据 】
字符流中的编码解码
注意:InputStreamReader和OutputStreamWrite所传的参数是FileInputStream和FileOutputStream哦!
import java.io.*;
public class FileDemo7 {
public static void main(String[] args) throws IOException {
//默认字符集写入,”中国“
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\untitled2\\ows.txt"));
//指定GBK字符集写入 ,”�й�“
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\untitled2\\ows.txt"),"GBK");
osw.write("中国");
osw.close();
//默认字符集读出
// InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\untitled2\\ows.txt"));
//指定GBK字符集读出
InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\untitled2\\ows.txt"),"GBK");
//一次读取一个字符数据
int ch;
while((ch=isr.read())!=-1){
System.out.print((char)ch);
}
isr.close();//不要忘了关闭噢
}
}
void flush():刷新流,让数据从缓冲区出来
void close():关闭流,先刷新
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
public class FileDemo8 {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\untitled2\\File\\src\\aba.txt"));
/*
//一次读一个字符数据
int ch;
while((ch=isr.read())!=-1){
System.out.print((char)ch);
}
*/
//一次读一个字符数组数据
char[] chs = new char[1024];
int len;
while((len=isr.read(chs))!=-1){
System.out.print(new String(chs,0,len));
}
isr.close();
}
}
注意,一次输入一个字符数组数据的方法是
char[] chs = new char[1024];
int len;
while((len=isr.read(chs))!=-1){
System.out.print(new String(chs,0,len));
}
先设置一个字符数组,令其容量为1024,再设置一个整型变量len,
输出的地方,要将读出的数据用String函数转为字符型输出。
在上面实操中会发现,转换流的名字很长很不方便,所以转化流提供了对应便捷子类,它们继承了 转换流,也就是继承了他们的读写方法。
字符流对应的也有字符缓冲流
它的使用方法和字节缓冲流差不多,但是也有它的特有功能哦!
标准输入输出流
被序列化的对象必须实现Serializeble接口!!,但无需重写任何方法。
import java.io.*;
public class FileDemo9 {
public static void main(String[] args) throws IOException {
//ObjectOutputStream(OutputStream):创建一个写入指定的OutputStream的ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\untitled2\\oos.txt"));
//创建对象
Student s = new Student("AK刘璋","20");
//void writeObject(Object obj):将指定的对象写入ObjectOutputStream
oos.writeObject(s);
//释放资源
oos.close();
}
}
import java.io.*;
public class FileDemo10 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\untitled2\\oos.txt"));
//object readObject():从ObjectInputStream读取一个对象
Object obj = ois.readObject();
Student s= (Student) obj;
System.out.println(s.getName()+","+s.getAge());
ois.close();
}
}
对象序列化流的三个问题!
用对象序列化流序列化了-一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
会!抛出InvalidClassExpection异常
如果出问题了,如何解决呢?
给对象所属的类加一个serialVersionUID
private static final long serialVersionUID = 42L;
如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
Properties