IO
一、文件类
File
类被定义为文件和目录路径名的抽象表示形式,这是因为File
类既可以表示文件也可以表示目录,他们都通过对应的路径来描述。
通过构造函数创建一个File
类对象,则该对象就是指定文件的引用,可以通过该对象对文件操作
//创建一个File类对象f,可通过f对temp.txt进行操作
File f = new File("D:\\temp.txt");
路径分隔符:
- Windows下路径分隔符使用反斜线
\
,而Java程序中的反斜线表示转义字符,如果需要在Windows路径下使用反斜线,则应使用两条反斜线,如:C:\\mytest.txt
- 使用斜线
/
,Java程序支持将斜线当成平台无关的路径分隔符
File
类常见方法:
isHidden()
:判断是否是隐藏文件canRead()
:是否可读canWrite()
:是否可写getPath()
:获取文件的路径getAbsolutePath()
:获取文件的绝对路径getName()
:获取文件名isDirectory()
:是否是目录isFile()
:是否是文件mkdir()
:创建目录lastModified()
:最后修改时间length()
:文件长度listFiles()
:返回目录下的所有文件和目录
public class Demo {
/*
* |---File类---文件和目录(文件夹)的抽象表示形式---File类将文件当成一个整体,不能对文件的内容进行操作,如果对文件的内容操作,需要使用IO流
* 通过File类的对象和文件或目录建立关联,操作File类的对象,就是操作相应的文件或者目录
*
* */
public static void main(String[] args) {
//创建File类的对象 java.io....
/*
* 文件的路径有两种写法
* C:\\Users\\Raymond\\Desktop\\test\\a.txt
* C:/Users/Raymond/Desktop/test/a.txt
*
* \ 转义字符----和其后的第一个字符结合,表示特殊的含义 \n \t
* 如果要表示\,必须写两条\
*
* */
//File f = new File("C:\\Users\\Maxwell\\Desktop\\a.txt");
File f = new File("D:/a.txt");
//File类中常见的方法
//判断文件是否是隐藏文件
System.out.println("是否隐藏:" + f.isHidden());
//大小 Byte
System.out.println("文件的大小:" + f.length());
//文件名
System.out.println("文件名:" + f.getName());
//绝对路径
System.out.println("绝对路径:" + f.getAbsolutePath());
//是否可读
System.out.println("是否可读:" + f.canRead());
//是否可写
System.out.println("是否可写:" + f.canWrite());
/*
* 时间戳---->表示时间的字符串(xxxx年xx月xx日 xx:xx:xx)
*
* SimpleDateFormat
* |
* Date()
* |
* 时间戳
* 时间戳---->Date()
* */
//文件最后修改时间
long lastMdate = f.lastModified();
Date date = new Date(lastMdate);
//Date---String
SimpleDateFormat sft = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String dateStr = sft.format(date);
System.out.println("最后修改时间:" + dateStr);
//判断是否是文件夹
System.out.println("是否是文件夹:" + f.isDirectory());
File f1 = new File("D:/test123/");
//判断文件或文件夹是否存在
//System.out.println("是否存在:" + f1.exists());
if(!f1.exists()) { //不存在创建该文件夹
//创建文件夹 Linux mkdir
f1.mkdir();
}
File[] fArr = f1.listFiles();
for (File file : fArr) {
System.out.println(file.getName());
}
}
}
File类中没有提供对文件的读写操作,如果要实现对文件的读写,需要通过IO流来进行操作。
案例:列出一个目录下所有的文件和目录(包括子目录中的目录和文件)
public class Demo{
/*
* f表示需要被遍历的文件夹
* */
public static void listFiles(File f) {
File[] farr = f.listFiles();
for(File subf : farr) {
System.out.println(subf.getAbsolutePath());
if(subf.isDirectory()) {
listFiles(subf);
}
}
}
public static void main(String[] args) {
File file = new File("D:/test123/");
listFiles(file);
}
}
二、IO
流
1.1概念
I/O
是Input/Output
的缩写
- 流:数据在存储设备和内存之间的传输通道
- 数据借助流传输
2.2IO
流分类
按照数据流流向不同:
- 输入流:将存储设备中的内容读到内存当中
InputStream
、Reader
- 输出流:将内存中的内容写入到存储设备中
OutputStream
、Writer
按照处理的数据单元不同:
- 字节流:以字节为单位,可以读写所有数据,
InputStream
、OutputStream
- 字符流:以字符为单位,只能读写文本数据,
Reader
、Writer
按照功能不同:
- 节点流:具有实际传输数据的读写功能
- 处理流(过滤流):就是在节点流的基础上增强功能
三、字节流
3.1字节抽象类
-
字节输入流:
InputStream
-
主要方法:
read()
:从输入流中读取数据的下一个字节read(byte[] b)
:从此输入流中将最多b.length
个字节的数据读入一个byte
数组中read(byte[] b, int off,int len)
:将输入流中最多len
个数据字节读入byte
数组close()
:关闭此输入流并释放与该流关联的所有系统资源
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
public class Demo01 {
public static void main(String[] args) throws IOException {
//创建FileInputStream对象
FileInputStream fis = new FileInputStream("a.txt");
//使用read方法返回一个字节对应的Unicode码值
//如果读到文件末尾没有值就返回-1
//通过文件输入流进行操作
System.out.println(fis.read());
//read(byte[])一次读取缓冲区个字节,并将内容读入字节数组中,并返回读取长度
//自定义缓冲区
byte[] b = new byte[10];
int len = fis.read(b);
System.out.println(Arrays.toString(b));
System.out.println(len);
byte[] buf = new byte[50];
int len1;
len1=fis.read(buf,0,1024);
System.out.println(Arrays.toString(buf));
System.out.println(len1);
//关闭资源
fis.close();
}
}
字节输出流:OutputStream
主要方法:
write(int b)
:将指定的字节写入此输出流write(byte[] b)
:将b.length
个字节从指定的byte
数组写入此输出流write(byte[] b,int off,int len)
:将指定byte
数组中从偏移量off
开始的len
个字节写入此输出流flush()
:刷新此输出流并强制写出所有缓冲的输出字节,调用此方法指示应将这些字节立即写入它们预期的目标close()
:关闭此输出流并释放与该流关联的所有系统资源
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo01 {
public static void main(String[] args) throws IOException {
//创建OutputStream对象
FileOutputStream fos= new FileOutputStream("a.txt",true);
//通过输出流写内容
fos.write(65);
fos.write(65);
fos.write(65);
//write(byte[] );向文件中写入一个字节数组 有内容
//通过字节数组写内容
byte[] b = "hello ,java ".getBytes();
fos.write(b);
byte[] b2 = "HHHH".getBytes();
fos.write(b2,0,b2.length);
//关闭资源
fos.close();
}
}
总结:
- 使用输出流时如果文件不存在会自动创建,但是要保证父目录的存在
- 使用输出流写内容的时,在构造方法改为true,表示在原有内容上追加(默认会覆盖原有内容)
- 将io操作写在try中,释放资源卸载finally中
- 新语法
四、缓冲流
4.1字节缓冲流
-
根据数据操作单位可以把缓冲流分为:
BufferedInputStream
和BufferedOutputStream
-
提高IO效率,减少磁盘的访问次数
-
数据存储在缓冲区中,flush将缓冲区的内容写入文件中,也可以直接close
import java.io.*;
public class BufferStreamDemo {
public static void main(String[] args) throws IOException {
/*
//提高io效率,减少访问磁盘的次数
//通过文件输入流创建一个缓冲输入流
FileInputStream fis = new FileInputStream("a.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] b = new byte[1024];
int len;
while ((len=bis.read(b))!=-1){
String str = new String(b,0,len);
System.out.println(str);
}
bis.close();
*/
//通过文件输出流创建一个缓冲输出流
FileOutputStream fos = new FileOutputStream("c.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
//fos.write(); 这个是直接访问磁盘进行操作
bos.write("aaa".getBytes());//还在缓冲区中
bos.close();
}
}
文件拷贝案例
import java.io.*;
public class CopyFileDemo {
//文件拷贝案例
public static void main(String[] args) throws Exception {
//记录开始时间
long start = System.currentTimeMillis();
copy1();
//计算结束时间
long end = System.currentTimeMillis();
//输出运行时间
System.out.println(end-start);
}
public static void copy1() throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("b.txt");
byte[] buf = new byte[1024];
int len;
while ((len=fis.read(buf))!=-1){//当读到返回值
fos.write(buf,0,len);
}
fos.close();//后用的先关闭
fis.close();
}
public static void copy2() throws Exception{
//需要普通的流进行支持
FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("b.txt");
//创建缓冲流
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] buf = new byte[1024];
int len;
while ((len=bis.read(buf))!=-1){//当读到返回值
fos.write(buf,0,len);
}
bos.close();//后用的先关闭
bis.close();
fos.close();
fis.close();
}
}
4.2字符缓冲流
- 缓冲流
BufferedReader
和BufferedWriter
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class BufferedWriterDemo01 {
public static void main(String[] args) throws Exception{
/*
//创建字符缓冲输入对象
BufferedReader br = new BufferedReader(new FileReader("b.txt"));
//br.readLine() 一次读取一行内容返回字符串 读到流的末尾就是null
System.out.println(br.readLine());
//通过字符缓冲流循环读取文件内容
String line;
while ((line = br.readLine())!=null){
System.out.println(line);
}
//释放资源
br.close();
*/
//ch字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("e.txt"));
//通过字符流写出内容
bw.write("aaaaaa");
//释放资源
bw.close();
}
}
使用缓冲流实现文件拷贝
import java.io.*;
public class CopyBufferedDemo {
public static void main(String[] args) throws Exception {
BufferedReader fr = new BufferedReader(new FileReader("d.txt"));
BufferedWriter fw = new BufferedWriter(new FileWriter("e.txt"));
char[] ch = new char[1024];
int len = 0;
while ((len = rd.read(ch)) != -1) {
wr.write(ch, 0, len);
}
fw.close();
fr.close();
//只有纯文本才能使用字符流
}
}
五、对象流
ObjectOutputStream
、ObjectInputStream
- 增加了缓冲区功能
- 增加了读写八种基本数据类型和字符串功能
- 增加了读写对象的功能
readObject()
从流中读取一个对象writeObject()
向流中写入一个对象
import java.io.Serializable;
public class Student implements Serializable {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class ObjectDemo01 {
public static void main(String[] args) throws Exception{
/*
//创建文件输出流
FileOutputStream fos = new FileOutputStream("d.txt");
//创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(fos);
//创建学生对象
Student stu = new Student("aaa", 20);
//通过对象流讲对象写入到d.txt
//NotSerializableException 为序列化异常
oos.writeObject(stu);
//释放资源
oos.close();
fos.close();
*/
//创建对象输入流
FileInputStream fis = new FileInputStream("d.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
//通过对象流读取d.txt中的对象
Object stu = ois.readObject();
System.out.println(stu);
//释放资源
ois.close();
fis.close();
}
}
注意事项:
-
NotSerializableException
为序列化异常 -
序列化:讲对象编程可以读写的字节序列
-
反序列化:将字节序列变成java对象
-
如何解决这个问题:实现序列化接口 Serializable
-
对象流使用细节:
-
对象流读取完数据会抛出异常
EOFEException
-
序列化ID作用是:保证序列化安全
-
transient修饰的属性不会被序列化
-
对象流提供了一些直接读写的基本类型+String方法
-
案例(模拟注册):
package IODemo03;
public class User {
private String userName;
private String passWord;
public User() {
}
public User(String userName, String passWord) {
this.userName = userName;
this.passWord = passWord;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", passWord='" + passWord + '\'' +
'}';
}
}
import java.io.*;
import java.util.ArrayList;
public class ObjectDemo02 {
public static void main(String[] args) throws Exception {
//对象流读写集合
//注册
User user = new User("admin", "123");
ArrayList<User> userList = new ArrayList<>();
File file = new File("user.obj");
if(!file.exists()){//表示第一次注册
userList.add(user);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.obj"));
oos.writeObject(userList);
oos.close();
}else{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.obj"));
userList = (ArrayList<User>)ois.readObject();
//判断用户是否存在
if(true) {
//略 存在就返回出去
}
//不存在就返回
userList.add(user);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.obj"));
oos.writeObject(userList);
oos.close();
}
}
六、字符流
6.1字符抽象类
- 字符输入流:Reader
- 字符输出流:Writer
6.2字符输入流用法
import java.io.FileReader;
public class Demo01 {
public static void main(String[] args) throws Exception{
//创建字符文件输入流对象
FileReader fr = new FileReader("a.txt");
//通过字符输入流读取内容
//read() 一次读取一个字符返回这个字符对应的Unicode码
//读到流的末尾会返回-1
System.out.println(fr.read());
System.out.println(fr.read());
System.out.println(fr.read());
System.out.println(fr.read());
/*
//read(cbud,offset,count)一次读取缓冲区个字符读到字符数组中,并返回读取的长度
//读到末尾返回-1
char[] cbuf = new char[1024];
int len;
while ((len=fr.read(cbuf))!=-1){
String str = new String(cbuf,0,len);
System.out.println(str);
}
*/
//read(cbud,offset,count)一次读取缓冲区个字符读到字符数组中,并返回读取的长度
//读到末尾返回-1
//可以指定读到缓冲区数组下标指定的位置,指定读取字符个数
char[] cbuf = new char[1024];
fr.read(cbuf,2,2);
fr.close();
}
}
6.3字符输出流用法
import java.io.FileWriter;
public class Demo02 {
public static void main(String[] args) throws Exception {
//创建字符文件输出流对象
FileWriter fw = new FileWriter("b.txt",true);
//通过字符流写出内容
fw.write("hello,word");
//释放资源
fw.close();
}
}
七、转换流
import java.io.*;
public class Demo01 {
public static void main(String[] args) throws Exception{
/*
//将字节输入流转换成字符输出流
FileInputStream fis = new FileInputStream("a.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
isr.close();
fis.close();
*/
//zhi'd
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("e.txt"),"GBK"));
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
}
}