1. File类
- 理解:
* 》File类位于java.io包下,本章节中涉及到的相关流也都声明再java.io包下。
*
* 》File类的一个对象,对应与操作系统下的一个文件或一个文件目录(文件夹)
*
* 》File类中声明了新建、删除、获取文件名、重命名等方法,并没有出现对文件内容的
* 读写操作。要想实现文件内容的读写操作,就需要使用IO流
*
*
* 》File类的对象,通常是作为IO流操作的文件端点出现的。
* * 代码层面:将File类的对象作为参数传递到IO流相关类的构造器中。
- 常用构造器:
* 》public File(String pathname):以pathname为路径创建File对象,可以是绝对路
径 / 相对路径,
* 如果pathname是相对路径,则默认的当前路径在系统属性user.dir中储存
* * 绝对路径:以windows操作系统为例,包括盘符在内的文件或文件目录的完整路
径
* * 相对路径:相对于某一个文件目录来讲的相对位置
*
* 》public File(String parent , String child):以parent为父路径,child为子路径创建
File对象
*
* 》public File(File parent , String child):根据一个父类File对象和子文件路径创建
File对象
- 常用的方法:



》部分举例
package File_And_IO;
import java.io.File;
import java.io.IOException;
public class FileTest
{
public static void main(String[] args)
{
/**
* 利用createNewFile()方法创建文件,注意异常处理。
* */
File f2 = new File("D:\\File\\000.txt"); //声明一个文件的位置
try
{
System.out.println(f2.createNewFile()); //操作文件:创建新文件,因为会报异常,因此要try-catch一下
}
catch(IOException e)
{
e.printStackTrace();
}
/**
* 遍历指定的目录下的所有文件的名称
* */
File f = new File("D:\\File");
printFileName(f);
/**
* 删除指定的目录下的所有文件,但是不删除文件夹,注意:此删除不会在回收站找到
* */
File file = new File("D:\\File\\io");
remove(file);
}
//遍历指定文件夹里的文件的方法
public static void printFileName(File file)
{
//如果文件存在
if(file.isFile()) //如果是文件,直接打印
System.out.println(file.getName());
else if(file.isDirectory()) //如果是文件目录
{
File f1[] = file.listFiles();
for (File f2 : f1)
printFileName(f2);
}
}
//删除指定文件夹里的文件的方法,但不删除文件夹
public static void remove(File file)
{
if(file.isFile()) //如果是文件,直接删除
{
file.delete();
}
else if(file.isDirectory()) //如果是文件目录
{
File f1[] = file.listFiles();
for(File f2 :f1)
{
remove(f2);
}
}
}
}
2.IO流
- IO流的分类:
* 》流向的不同:输入流、输出流
*
* 》处理单位的不同:字节流、字符流(字符流:处理纯文本,字节流:处理图片,视
频,音频等)
*
* 》流的角色不同:节点流、处理流
*
*
* - 基础IO流的框架:
* 抽象基类 4个节点流(也称文件流) 4个缓冲流
* InputStream FileInputStream --->输入字节流 BufferedInputStream
* OutputStream FileOutputStream --->输出字节流 BufferedOutputStream
* Read FileRead --->输入字符流 BufferedRead
* Writer FileWriter --->输出字符流 BufferedWriter
- 4个节点流:
* 》 FileReader读入字符数据(详见FileReaderTest)
package File_And_IO;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReadTest
{
public static void main(String[] args)
{
/**
* FileReader(输入型字符流)的使用:主要是read方法的使用
* */
FileReader f =null; //这里必须赋值为null以确保finally中的f能用
try
{
//1.创建File类的对象,对应着hello.txt文件
File file = new File("D:\\File\\io\\hello.txt");
//2.创建输入型的字符流
f = new FileReader(file);
//3.读取数据显示在控制台上
//方式一:
// int data = f.read();
// while(data != -1)
// {
// System.out.print((char)data);
// data = f.read();
// }
//方式二(推荐):
char []cbuffer = new char[7]; //控制每次《!最大!》读入的字符的数量
int len;
while((len = f.read(cbuffer))!= -1) //当read的返回值是读入的元素个数,当读入的元素个数为0时,
//返回的是-1
{
for(int i = 0;i<len;i++) //不能使用.length 因为要读入几个输出几个,而len里面装的就是当前读入数据的个数
{
System.out.print(cbuffer[i]);
}
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
//流资源关闭操作(必须关闭,否则会有内存泄漏)
try
{
if(f != null) //防止空指针的情况出现
f.close(); //这里有可能出现异常,因此也要包起来
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
*
* 》 FileWriter输出字符数据(详见FileWriterTest)
* * 第一步:创建读取或写出的File类的对象
* * 第二步:创建输入流或输出流
* * 第三步:具体的读入或写出的过程
* / 读入:read(char[] cbuffer)【常用】
* / 写出:write(String str) \ write(char[] cbuffer ,0,len)【常用】
* * 第四步:关闭流资源,防止内存泄漏
package File_And_IO;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterTest
{
public static void main(String[] args)
{
/**
* FileWriter(字符型输入流)的使用
* 主要是:
* - 方法:
* writer(String str) / writer(char[] cdata)/ writer(char[] cdata,0,len)
* 【 writer(char[] cdata,0,len)详见FileReaderAndWriterTest】
* - 构造器:
* 覆盖文件使用的构造器:FileWriter fw = new FileWriter(file)
* FileWriter fw = new FileWriter(file,false)
* 在现有文件上追加文件内容构造器:FileWriter fw = new FileWriter(file,true)
*
* - 注意:当没有此文件时,会自动生成一个文件
* */
FileWriter fw = null;
try
{
//1.创建File类的对象指明要写出的文件名称
File file = new File("D:\\File\\io\\hello.txt");
//2.创建输出流
fw = new FileWriter(file,true);
//3.写出的具体过程
//输出方法:writer(String str) / writer(char[] cdata)
//覆盖文件使用的构造器:FileWriter fw = new FileWriter(file)\ FileWriter fw = new FileWriter(file,false)
//在现有文件上追加文件内容构造器:FileWriter fw = new FileWriter(file,true)
fw.write("你好,\n");
fw.write("中国!\n");
fw.write("你好,\n");
fw.write("独酌!");
System.out.println("创建成功");
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
//关闭资源
fw.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
*
* 》 FileIntputStream读入字节数据、FielOutputStream输出字节数据
(详见FileStreamTest)【套路与read、write一样,因此直接合起来写(方法也一样)】
*
package File_And_IO;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileStreamTest
{
public static void main(String[] args)
{
/**
* FileInputStream / FileOutputStream的使用
* */
FileInputStream fi = null;
FileOutputStream fo = null;
try
{
//1.创建File对象
File in = new File("D:\\File\\io\\雷神.jpg");
File out = new File("D:\\File\\io\\雷神_copy.jpg");
//2.创建输入输出字节流
fi = new FileInputStream(in);
fo = new FileOutputStream(out);
//3.读入读出操作
byte[] by = new byte[1024]; //(1kb)用“小车”装,快!只能用byte
int len;
while((len = fi.read(by))!=-1)
{
fo.write(by, 0, len);
}
System.out.println("图片复制成功");
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
//4.关闭流资源
try
{
if(fi != null)
fi.close();
} catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if(fo != null)
fo.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
- 4个缓冲流:
* 》 缓冲流的作用:提升文本的读写效率
*
* 》 4个缓冲流 使用的方法
* 处理非文本文件的字节流
* BufferedInputStream read(byte[] buffer)
* BufferedOutputStream write(byte[] buffer,0,len)
*
* 处理文本文件的字符流
* BufferedRead read(char[] cbuffer) / readLine() 读一行
* BufferedWriter write(char[] cbuffer,0,len)
*
* 》基本上一样,因此只有字节流的用法详写(详见BufferStreamTest)
package File_And_IO;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferStreamTest
{
/**
* 复制图片操作
*
* 为了整体布局的清晰,这里直接抛出了异常,正常应该用try-catch-finally来处理
* */
public static void main(String[] args) throws IOException
{
//1.创建File对象
File file01 = new File("D:\\File\\io\\QQ.jpg");
File file02 = new File("D:\\File\\io\\QQcopy.jpg");
//2.创建输入输出流
FileInputStream fi = new FileInputStream(file01);
FileOutputStream fo = new FileOutputStream(file02);
//2.1用buffer包装输入输出流
BufferedInputStream bfi = new BufferedInputStream(fi);
BufferedOutputStream bfo = new BufferedOutputStream(fo);
//3.操作出入输出流
byte[] by = new byte[1024];
int len;
while((len = bfi.read(by))!=-1)
{
bfo.write(by, 0, len);
}
System.out.println("复制成功");
//4.关闭流资源
//先关闭外层资源
//因为外层资源关闭后会自动关闭内层资源,因此可以省略
bfo.close();
bfi.close();
//关闭内层资源
// fi.close();
// fo.close();
}
}
- 2个转换流:
* 》字符编码:字符、字符串、字符数组 ---> 字节、字节数组(看的懂得--->看不懂的)
*
* 》字符解码:字节、字节数组 --->字符、字符串、字符数组(看不懂的 ---> 看得懂的)
*
* 》转换流:
* * 作用:实现字节与字符之间的转换
*
* * API:
* (详见InputStreamReader_and_Writer)
* + InputStreamReader:将一个输入型的字节流转换为输入型的字符流
* + OutputStreamWriter:将一个输出型的字符流转换为输出型的字节流
*
package File_And_IO;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class InputStreamReader_and_Writer
{
public static void main(String[] args) throws IOException
{
/**
* 将文件以utf-8的解码集进行解码
*
* 并将文件以gdk的编码集进行编码并储存在一个新文件中
* */
//1.创建文件对象
File file1 = new File("D:\\File\\123.txt");
File file2 = new File("D:\\File\\123-gdk.txt");
//2.创建流
//输入流
FileInputStream fr1 = new FileInputStream(file1);
//将输入流用转换流包裹(用utf-8解码)
InputStreamReader fi1 = new InputStreamReader(fr1,"utf-8");
//输出流
FileOutputStream fr2 = new FileOutputStream(file2);
//将输出流用转换流包装(用gdk编码生成新文件)
OutputStreamWriter fi2 = new OutputStreamWriter(fr2,"gbk");
//3.对文本的操作
char arr[] = new char[1024];
int len;
while((len = fi1.read(arr))!=-1)
{
fi2.write(arr,0,len);
}
System.out.println("创建成功");
//4.关闭资源
fi2.close();
fi1.close();
}
}
- 2个对象流(详见ObjectInputStream_OutputStream)
* 》对象流的作用:
* 可以读写基本数据类型、引用数据类型。
*
* 》AIP:ObjectInputStream / ObjectOutStream (构造器的括号值为:
FileInputStream / FileOutputStream型)
*
* 》对象序列化机制:
* 对象序列化机制允许把内存中的java对象转化成与平台无关的二进制流,从而允许把
这种流之久的保留 在磁盘上,或通过网络将这种二进制流传输到另一个网络节
点。//当其他程序获得这种流时,就会可以恢 复成原来的java对象
*
*
*
* 》如下两个过程使用的流:(详见ObjectInputStream_OutputStream)
* 序列化过程:使用ObjectOutStream流实现。将内存中的java对象保存在文件中或通
过网络传输出去
* 反序列化过程:使用AIP:ObjectInputStream流实现。将文件中的数据还原为内存
中的java对象
* 注意:在序列化自定义的类时,应满足:
* ① 自定义的类需要实现接口:Serializable
* ② 要求自定义的类声明一个全局常量:static final long serialVersionUID =
1564851563L;
* ③ 如果不声明全局常量,系统会自动生成一个针对于当前类的一个全局常量,但
是一旦修改自定义的类
* 就会导致又重新生成一个全局常量,导致两次的全局常量不一样,进而导致反
序列化失败
* ④ 要求自定义的各个属性也必须是可序列化的。
* / 对于基本数据类型的属性:默认是可序列化的
* / 对于引用数据类型的属性:要求实现Serialiazble接口
* ⑤ 类中的属性如果声明为transient / static 就不会被序列化,而是被还原为默认
值,但是其他的正常被序列化
* 例如:transient int age; / static String name;
package File_And_IO;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class ObjectInputStream_OutputStream
{
public static void main(String[] args) throws IOException, ClassNotFoundException
{
/**
* 1.序列化过程
* */
//指明写入的文件
File file = new File("D:\\File\\对象流测试.txt");
//创建流(创建一根字节性的管子,插入到file文件中)
FileOutputStream fo = new FileOutputStream(file);
//创建对象流
ObjectOutputStream o = new ObjectOutputStream(fo);
//装数据
o.writeUTF("你好,中国!"); //writeUTF()用来装字符串的方法
o.writeObject("你好,独酌!"); //writeObject()用来装Object类的方法
o.writeObject(new person(12,"张三")); //传对象
//关闭资源
o.close();
/**
* 反序列化过程
* */
//1.指明写入的文件
File file2 = new File("D:\\File\\对象流测试.txt");
//2.创建流
FileInputStream f1 = new FileInputStream(file);
//3.创建对象流
ObjectInputStream o1 = new ObjectInputStream(f1);
//4.打印数据
String s = o1.readUTF(); //readUTF()用来读取用writeUTF()方法来写的字符串
System.out.println(s);
String s1 = (String)o1.readObject(); //readObject()来读取用writeObject()方法写入的内容
System.out.println(s1);
System.out.println(o1.readObject()); //打印对象
//5.关闭资源
o1.close();
}
}
class person implements Serializable
{
private static final long serialVersionUID = 128L; //唯一标识,必须有
int age;
String name;
public person()
{
super();
}
public person(int age, String name)
{
super();
this.age = age;
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
@Override
public String toString()
{
return "person [年龄:" + age + ",姓名:" + name + "]";
}
}
- 其他流:
* / 标准的输入,输出流
* System.in:标准的输入流,默认从键盘上输入
* System.out:标准的输出流,默认从显示器上输出(理解为控制台上)
* * 通过:setIn(InputStream is) 修改输入的位置
* setOut(PrintStream ps) 修改输出的位置(把内容输入到哪个文件中)