File类(表示文件)
我们要在Java程序中操作硬盘上的文件,首先需要在程序中表示一个对应的文件。
一个File类的对象表示硬盘上的一个文件或目录(文件夹)
File类只能表示文件,不能对文件内容进行读写操作。
/*
一个file类的对象表示一个文件或目录
new File("String类型的文件名 可以是相对的路径也可以是绝对的路径")
File(父级,子集);
*/
File f1 = new File("D:\\ideaProjects\\javaIO/demo.txt");
System.out.println(f1.length());
String p = "D:/";
File f2 = new File(p,"demo.text");
File f3 = new File(p,"demo1.txt");
File类中常用的方法:
-
判断功能方法
File f1 = new File("D:\\ideaProjects\\javaIO/demo.txt"); System.out.println(f1.canWrite()); //是否可以写 System.out.println(f1.canRead()); //是否可以读 System.out.println(f1.exists()); //文件是否存在 System.out.println(f1.isFile()); //是不是文件 System.out.println(f1.isHidden()); //是否隐藏 System.out.println(f1.isAbsolute()); //是不是绝对路径 System.out.println(f1.isDirectory()); //是不是文件夹
-
获取功能方法
File f = new File("D:\\ideaProjects\\javaIO/demo.txt"); System.out.println(f.length()); //文件长度(以字节为单位的) System.out.println(f.lastModified()); //最后修改的时间差 System.out.println(new Date(164456727960L)); System.out.println(f.getParent()); System.out.println(f.getName()); System.out.println(f.getAbsolutePath()); File f1 = new File("IO"); //相对路径 System.out.println(f1.getAbsolutePath()); //获取文件的绝对路径 File f2 = new File("D:\\ideaProjects\\javaApi"); //这表示的是一个文件夹 //获取此目录下所有的文件和文件夹,返回的都是文件名的字符串形式 /*String[] fs = f2.list(); for(String fn:fs){ System.out.println(fn); }*/ //获取此目录下所有的文件和文件夹,返回的都是文件对象 /*File[] fs = f2.listFiles(); for(File fn:fs){ // fn.delete();删除 System.out.println(fn); }*/ //文件筛选 筛选出文件后缀名为chm的文件 File[] fs = f2.listFiles((dir, name) -> {return name.endsWith("chm");}); for(File fn:fs){ System.out.println(fn); }
-
创建、删除方法
//创建文件 File f1 = new File("D:\\ideaProjects\\javaIO/demo2.txt"); //避免创建文件的位置不存在 try { f1.createNewFile(); //创建一个新的文件,前提是文件不存在 } catch (IOException e) { e.printStackTrace(); } f1.delete(); // 删除此文件 //创建文件夹 /* File f = new File("D:\\ideaProjects\\javaIO/a"); f.mkdir(); //创建文件夹,只能创建一级*/ File f = new File("D:\\ideaProjects\\javaIO/a/b"); // f.mkdirs(); //创建文件夹,可以创建多级目录 f.delete(); //只会删除b delete在删除文件夹时,一次只能删除一级目录,且目录中为空
IO
读写文件:I(input)O(output) 输入输出
按照读写的单位分为:
-
字节流:一次读写一个字节。 使用的多,图片、视频、音频、exe……
- 字节输入流:从硬盘向程序中读数据 InputStream
- 字节输出流:从程序中向硬盘上写数据 OutStream
-
字符流:一次读写一个字符。 只读纯文本文件,txt、java、C……
注:Word不是纯文本文件
- 字符输入流
- 字符输出流
字节流
public class StreamDemo1 {
public static void main(String[] args) throws IOException {
//需求,把D:/demo.txt ---> E: /demo.txt
//创建一个输入流管道,为其制定输入的文件,输入流要求文件存在,否则会报错
FileInputStream in = new FileInputStream("D:/demo.txt");
// int b = in.read(); //从文件中读数据,一次读一个字节,文件内容读完后返回-1.
/* int b = 0;
while ((b = in.read())!= -1){
System.out.println(b);
}*/
//创建一个输出流管道,为其制定输出的文件,输出文件可以不存在,会自动创建
FileOutputStream out = new FileOutputStream("E:/demo.txt");
int b = 0;
while ((b = in.read())!= -1){
out.write(b);
}
in.close(); //关闭流通道,释放文件
out.close();
}
}
//标准写法,引入异常机制
public class StreamDemo2 {
public static void main(String[] args) {
try {
testIO();
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("文件找不到");
}catch (IOException ioe){
System.out.println("读写异常");
}
}
//模拟文件读写操作
public static void testIO() throws FileNotFoundException, IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(new File("D:/demo.txt"));
out = new FileOutputStream(new File("E:/demo.txt"));
int b = 0;
while ((b = in.read()) != -1){
out.write(b);
}
}finally {
if(in != null){
in.close();
}
if(out != null){
out.close();
}
}
}
}
read() :一次只读取一个字节,并返回结果,a-97,读完返回-1,效率低。
read(byte[] b):一次读取一个byte数组个字节内容,返回数组中实际装入内容的长度,读完返回-1。
public class StreamDemo3 {
public static void main(String[] args) throws IOException {
//创建一个输入流管道,为其制定输入的文件,输入流要求文件存在,否则会报错
FileInputStream in = new FileInputStream("D:/demo.txt");
//创建一个输出流管道,为其制定输出的文件,输出文件可以不存在,会自动创建
FileOutputStream out = new FileOutputStream("E:/demo.txt");
// read() 一次只读取一个字节,并返回结果,a-97,读完返回-1,效率低
// read(byte[] b) 一次读取一个byte数组个字节内容,返回数组中实际装入内容的长度,读完返回-1
//44个字节,数组长度为10 读5次
byte[] b = new byte[10]; //50 44
int size = 0; //实际向数组中读到的内容长度,主要是最后一次的实际数量
while ((size = in.read(b)) != -1){
System.out.println(size);
// out.write(b); //写出会有50个字节
//write(装内容的数组,数组的第0个位置开始,size实际写出的长度); 最后一次只有4个字节,向外只写4个即可
out.write(b, 0,size);
}
in.close();
out.close();
}
}
节点流和处理流
根据封装类型的不同:
-
节点流:流对象中流封装的是某种特定的数据源,直接用来读文件。
FileInputStream、FileOutSteam
-
处理流:流对象中包含的是其他流对象,可以提供一些其他操作。(即流封装的是其他流对象)提供内部缓冲区功能。
BufferedInputStream、BufferedOutputStream、ObjectInputStream、ObjectOutputStream
public class StreamDemo4 {
public static void main(String[] args) throws IOException {
//需求,把D:/demo.exe ---> E: /demo.exe
//节点流
FileInputStream in = new FileInputStream("D:/demo1.exe");
//处理流
BufferedInputStream bin = new BufferedInputStream(in);
//节点流
FileOutputStream out = new FileOutputStream("E:/demo1.exe");
//处理流
BufferedOutputStream bout = new BufferedOutputStream(out);
byte[] b = new byte[1024]; //数组大小看具体情况,并非越大越好 数组是在内存中存储
int size = 0;
while ((size = bin.read()) != -1){
bout.write(b,0,size); //虽然每次调用了write方法,但是不一定每次都会真正写出
}
bin.close();
bout.flush(); //刷新缓冲区
bout.flush();
}
}
缓冲区源代码:
//write()
public synchronized void write(byte b[], int off, int len) throws IOException {
if (len >= buf.length) { //我们的数组长度大于等于内部的缓冲数组,直接写出
/* If the request length exceeds the size of the output buffer,
flush the output buffer and then write the data directly.
In this way buffered streams will cascade harmlessly. */
flushBuffer();
out.write(b, off, len); //直接写出
return;
}
if (len > buf.length - count) { //当缓冲区不足以放得下新读到的内容时,写出数据
flushBuffer();
}
System.arraycopy(b, off, buf, count, len); //缓冲区可以放得下,发生数组复制,复制到缓冲区中
count += len; //缓冲区总数量增加
}
//flushBuffer()
private void flushBuffer() throws IOException {
if (count > 0) {
out.write(buf, 0, count);
count = 0;
}
}
字符流
字符输入流:Reader
InputStreamReader转换流:把原始的字节转换为字符。将1个中文的3个字节转为一个字符编码。
FileReader
字符输出流:Writer
OutputStreamWriter
FileWriter
字符处理流:BufferedReader、BufferedWriter提供对数据的缓冲功能。
public class CharDemo1 {
public static void main(String[] args) throws IOException {
/*
字符流可以一次直接读取到一个字符内容
1个汉字3个字节组成,直接可以读到
*/
FileReader reader = new FileReader(new File("D:/demo.txt"));
/* System.out.println((char)reader.read());
System.out.println((char)reader.read());
System.out.println((char)reader.read());
System.out.println((char)reader.read());
System.out.println((char)reader.read());*/
FileWriter writer = new FileWriter(new File("E:/demo.txt"));
int c = 0;
while ((c = reader.read()) != -1){
writer.write(c);
}
reader.close();
writer.close();
}
}
public class CharDemo2 {
public static void main(String[] args) throws IOException {
/*
字符流可以一次直接读取到一个字符内容
1个汉字3个字节组成,直接可以读到
*/
FileReader reader = new FileReader(new File("D:/demo.txt"));
FileWriter writer = new FileWriter(new File("E:/demo.txt"));
char[] c = new char[10];
int size = 0;
while ((size = reader.read(c)) != -1){
writer.write(c,0,size);
}
reader.close();
writer.close()
}
}
public class CharDemo3 {
public static void main(String[] args) throws IOException {
/*
字符流可以一次直接读取到一个字符内容
1个汉字3个字节组成,直接可以读到
*/
FileReader reader = new FileReader(new File("D:/demo.txt"));
BufferedReader breader = new BufferedReader(reader);
FileWriter writer = new FileWriter(new File("E:/demo.txt"));
BufferedWriter bwriter = new BufferedWriter(writer);
// breader.readLine(); //一次读一行数据。数据读完后,如果没有数据,则返回null
String line = null;
while ((line = breader.readLine()) != null){
// System.out.println(line);
bwriter.write(line); //一次写出衣蛾字符串
bwriter.newLine(); //写出一个换行符
}
breader.close();
bwriter.flush();
bwriter.close();
}
}
Print流
Print流:没有输入,只是从程序中向外输出。
-
PrintStream:打印字节流
-
PrintWriter:打印字符流
百度搜索,输入信息,点击百度按钮,向服务器端发送搜索,将搜索到的内容响应到浏览器。
public class PrintDemo { public static void main(String[] args) throws FileNotFoundException { /* 打印字符流,单向从服务器端向客户端响应处理。 JavaEE时需要使用。 */ PrintWriter p = new PrintWriter("D:/demo.html"); p.println("<h1>你好世界</h1>"); p.println("<h1>你好世界</h1>"); p.println("<h1>你好世界</h1>"); p.println("<h1>你好世界</h1>"); p.close(); } }
对象输入、输出流(对象序列化和对象反序列化)
主要作用是用于写入对象信息与读取对象信息。
对象输入、输出流:就是把程序运行时所产生的对象信息(内存中存储),输出到一个文件中(实现对象信息的持久化保存),称为对象序列化。
例如系统升级,停止服务器,可以将一些对象保存到硬盘当中,服务器启动,从文件中读取信息。
反序列化:将对象信息读取到内存中,称为反序列化(重新创建一个对象)。(也是java中创建对象的一种方式)
public class ObjectStreamDemo1 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//程序运行时,产生两个对象
String s = new String("abc");
Date date = new Date();
//使用对象输出流,将对象的信息输出到文件中,称为对象序列化
FileOutputStream out = new FileOutputStream(new File("E:/object.txt"));
ObjectOutputStream objout = new ObjectOutputStream(out);
objout.writeObject(s);
objout.writeObject(date);
objout.flush();
objout.close();
//对象输入流读取文件中的对象信息,也称为反序列化
FileInputStream in = new FileInputStream(new File("E:/object.txt"));
ObjectInputStream objin = new ObjectInputStream(in);
String s = (String)objin.readObject();
Date date = (Date)objin.readObject();
System.out.println(s);
System.out.println(date);
objin.close();
}
}
import java.io.Serializable;
public class User implements Serializable {
//显示为类生成一个版本号
private static final long serialVersionUID = 4172444525933987413L;
private int no;
private String name;
public User(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
public class ObjectStreamDemo2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
User user = new User(100,"zhang");
//程序运行时,产生两个对象
String s = new String("abc");
Date date = new Date();
//使用对象输出流,将对象的信息输出到文件中,称为对象序列化
FileOutputStream out = new FileOutputStream(new File("E:/object.txt"));
ObjectOutputStream objout = new ObjectOutputStream(out);
objout.writeObject(user);
objout.flush();
objout.close();
//对象输入流读取文件中的对象信息,也称为反序列化
FileInputStream in = new FileInputStream(new File("E:/object.txt"));
ObjectInputStream objin = new ObjectInputStream(in);
User user1 = (User)objin.readObject();
System.out.println(user1);
objin.close();
}
}