10、IO流
11、IO流
File类
- File类的一个对象,代表一个文件或一个文件目录(文件夹);(用于io流中 内存 <-->目标对象)
- File类声明在java.io包下;
- File类中只涉及到文件的创建,删除,修改等方法,并未涉及 写入/读取文件操作 -->IO流
- File类的对象常会作为参数 传递到流的构造器中,指明 读取/写入 的"终点"
创建File类实例:
File(String filePath) //完整路径(目录/文件)
File(String parentPaht , String childPath) // 目录 + 子文件夹/文件
File(File parentFile , String childPath) //File目录 + 文件
路径
相对路径:当前 Project 或 当前 Module (非main())
绝对路径(包含盘符在内的路径)。
路径分隔符:
windows系统下: \ \d:\\wang\\info.txt
UNIX和URL: /d:/wang
Java通用常量: separator"d:" + File.separator + "wang" + File.separator + "infotxt"
常用方法:
File类 的获取功能:
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数组 File 类的重命名功能:
public boolean renameTo(File dest):把文件重命名为指定的文件路径file1 = new File("hello.txt"); file2 = new File("D//wang//hi.txt"); //把f1移动到f2目录下并改名为hi.txt finle1.renameTo(file2); //file1必须存在硬盘,file2必须不存在硬盘File 类的判断功能:
public boolean isDirectory():判断是否是文件目录
public boolean isFile() :判断是否是文件
public boolean exists() :判断是否存在
public boolean canRead() :判断是否可读
public boolean canWrite() :判断是否可写
public boolean isHidden() :判断是否隐藏
创建文件:
public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false
public boolean mkdir() :创建文件目录。如果此文件目录的上层目录不存在,也不创建。
public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建删除文件:
public boolean delete():删除文件或者文件夹 (删除目录时必须保证目录为空;不会进入回收站)
IO流
流的分类:
按操作 数据单位不同分为:字节流(8 bit) ,字符流(16 bit)
按数据流的 流向不同分为: 输入流,输出流
按流的 角色的不同分为: 节点流,处理流 (套管子,作用在节点流上)
流的体系结构:
抽象基类 字节流 字符流 输入流 InputStream Reader 输出流 OutputSteam Writer 节点流(文件流):
节点流 FileInputStream FileOutputStream FileReader FileWriter 处理流:
缓冲流,转换流,对象流; 其他(打印流, 输入输出流, 特殊流)
![]()
节点(文件)流
基本操作步骤:
- File类 实例化 【可以省略】
- 流的实例化
- 读入/写入 操作
- 关闭资源
字符流与字节流:
对于文本文件,使用字符流处理 (txt, java, c , cpp)
对于非文本文件 ,使用字节流处理 (jpg, mp3, mp4, avi, doc, ppt )
字符流 :(未进行异常处理)
public void reader(){
//1.创建File对象,指明要读入的文件(不能为空)
File f1 = new File("D:\\w.txt");
//2.创建 流对象
FileReader fr = new FileReader(f1);
//3.读入操作
int len; //fr.read() 默认读取方式,每次读取一个字符(int形式),若读取为空返回-1
char[] arr = new char[5]; //读取多个字符
while( (len=fr.read(arr)!=-1 ) {
//注意遍历arr时以len为基准-->实际读取到的是前len个数据
for (int i = 0; i < len; i++) {
System.out.print(arr[i]);
}
//方式二:
String str = new String(arr,0,len);
sout(srt);
}
//4.关闭流
fr.close();
}
public void writer(){
//1.创建File对象,指明要写出的文件(若不存在,会自动创建)
File f2 = new File("D:\\w.txt");
//2.创建 流对象
FileWriter fw = new FileWriter(f2,true); //默认fales 覆盖写入
//3.写出操作
fw.write("啦啦啦啦啦");
//4.关闭流
fw.close();
}
字节流:(在写出时可以通过 异或运算进行加密解密操作)
//实现文件赋值
public void copyFile(String srcPath,String destPath){
FileInputStream fis = null;
FileOutputStream fos = null;
try{
//1.创建File对象
File srcFile = new File(srcPath);
File destFile = new File(destPath);
//2.创建流对象
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destPath,true);
//3.读取,写出操作
byte[] buffer = new byte[1024]; //字节数组容器读取字节流
int len;
while ( (len=fis.read(buffer))!=-1 ){ //读入字节流
fos.write(buffer,0,len); //字节流写出
}
}catch (Exception e){
e.printStackTrace();
}finally {
//4.关闭流
try {
if (fos!=null)
fos.close();
if (fis!=null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
处理流
作用与节点流之上的流
缓冲流:Buffered
-
提高 流的读取,写入速度
(内部提供了一个缓冲区,先读取到缓冲区,再把缓冲区数据全部写出)
-
.fulsh() 刷新缓冲区提前将缓冲区的内容全部写入输出流 -
BuffereReader类新增
.readLine(), .newLine()方法,可以一次读取一行(不自动换行)//文件流 FileInputStream fis = null; FileOutputStream fos = null; //处理流 BufferedInputStream bis = null; BufferedOutputStream bos = null; //1.创建File对象,创建流对象 fis = new FileInputStream(new File(srcPath)); fos = new FileOutputStream(new File(destPath)); bis = new BufferedInputStream(fis); //套管子--缓冲流 bos = new BufferedOutputStream(fos); //2.读入,写出操作 byte[] buffer = new byte[1024]; int len; while ( (len=bis.read(buffer))!=-1){ //读入byte数组 bos.write(buffer,0,len); //从byte数组中写出 } //4.关闭资源 if (bis!=null) //在关(外层)处理流时,底层的文件流会自动关闭 bis.close(); if (bos!=null) bos.close();
转换流:
-
作用:提供 字节流与字符流之间的转换
-
属于字符流对象:
- InputStreamReader:将 字节输入流 转化为 字符输入流 --- 解码
- OutputSreamWriter:将 字符输出流 转化为 字节输出流 --- 编码
//1.造文件,造流 File f1 = new File("utf8.txt"); File f2 = new File("gbk.txt"); FileInputStream fis = new FileInputStream(f1); FileOutputStream fos = new FileOutputStream(f2); InputStreamReader isr = new InputStreamReader(fis,"utf-8");//转换流--编码 OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");//转换流---解码 //2.读入,写出操作 char[] cbuffer = new char[20]; int len; while ( (len=isr.read(cbuffer))!=-1 ){ //读 osw.write(cbuffer,0,len); //写 } //3.关闭资源 osw.close(); isr.close();
字符编码:
计算机识别的二进制字节 与 文字数字 一一对应 ---》 编码表
常见的编码表
ASCII:美国标准信息交换码。 用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表。用一个字节的8位表示。
GB2312:中国的中文编码表。最多两个字节编码所有字符
GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。(Unicode并不能用来实现编码,无法让计算机识别是 1个字节还是2个字节)
UTF-8:变长的编码方式,可用1-4个字节来表示一个字符![]()
对象流
-
用于存储和读取 基本数据类型数据 或 对象 的处理流。可以将Java中的对象写入,读出数据源
-
属于 字节流对象:
-
序列化:ObjectOutputSream类
writeObject对象/基本类型数据---> 二进制(字节)流; -
反序列化:ObjectInputSream类
readObject二进制流--->对象/基本类型数据;
-
-
ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
序列化对象的要求:
1.实现Serializable接口 --(标识接口)
2.提供一个全局常量 serialVersionUID -- (序列化版本号, 唯一标识序列化对象)
若未显示定义此UID,Java在序列化时会根据类自动生成一个UID;
但如果之后类发生修改,自动生成的UID也会变化,使得反序列化时,找不到该序列化对象。3.序列化对象类内部中的所有属性也必须是可序列化的 (即也实现了Serializeble接口)
class Person implements Serializable{ //提供全局常量 public static final long serialVersionUID = 5615656L; //类中的所有属性也必须可序列化 int age; //基本数据类型 默认可序列化 Dog gog; //自定义类,也需要实现序列化接口+serialVersionUID }
对象序列化机制:
允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。
当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
代码操作:
//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(“data.txt"));
Person p = new Person("韩梅梅", 18, "中华大街", new Pet());
oos.writeObject(p);
oos.flush();
oos.close()
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(“data.txt"));
Person p1 = (Person)ois.readObject();
System.out.println(p1.toString());
ois.close();
其他流(了解):
标准输入、输出流
System.in:标准输入流,默认从键盘输入
System.out:标准输出流,默认从控制台输出System类的 setIn(InputStream is) / setOut(PrintStream ps) 方式重新指定输入和输出的流。
System.out.println("请输入信息(退出输入e或exit):"); // 把"标准"输入流(键盘输入)这个字节流包装成字符流,再包装成缓冲流 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String s = null; while ((s = br.readLine()) != null) { // 读取用户输入的一行数据 --> 阻塞程序 if ("e".equalsIgnoreCase(s) || "exit".equalsIgnoreCase(s)) { System.out.println("安全退出!!"); break; } // 将读取到的整行字符串转成大写输出 System.out.println("-->:" + s.toUpperCase()); System.out.println("继续输入信息"); } br.close(); // 关闭过滤流时,会自动关闭它包装的底层节点流
打印流:
PrintStream 和 PrintWriter
提供了一系列重载的print()和println()方法,用于多种数据类型的输出
实现将 基本数据类型的数据格式转化为 字符串输出
数据流:
DataInputStream 和 DataOutputStream
用于 读取,写入 基本数据类型的变量或字符串
//写入 DataOutputSream dos = new DataOutputStream(new FileOutputSream("date.dat")); dos.writeUTF("我爱北京天安门"); // 写UTF字符串 dis.flush(); //刷新操作,将内存中的数据写入文件 dos.writeBoolean(false); // 写入布尔值 dis.flush(); dos.writeLong(1234567890L); // 写入长整数 dis.flush(); dos.close(); //读取(读取不同类型的数据时, 顺序必须与 写入时一致) DataInputSream dis = new DataInputStream(new FileInputStream("data.dat")); String info = dis.readUTF(); boolean flag = dis.readBoolean(); long time = dis.readLong(); dis.close();
随机存取文件流
- RandomAccessFile 类 直接继承于java.lang.Object类。实现了DataInput、DataOutput接口,也就意味着这个类 既可以读(输入流)也可以写(输出流)
- RandomAccessFile作为输出流时,若写出的文件不存在 则 自动创建;若存在 则对原有文件内容(默认从头开始)进行覆盖;
- RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。且可以自由移动记录指针:
long getFilePointer():获取文件记录指针的当前位置
void seek(long pos):将文件记录指针定位到 pos 位置 - 实例化:new RandomAccessFile(File file, String mode),mode参数指定访问模式:
r: 以只读方式打开
rw :打开以便读取和写入
rwd: 打开以便读取和 写入;同步文件内容的更新
rws: 打开以便读取和 写入;
//实现文件的文本插入功能
public void t6() throws Exception {
//1.创建流对象
RandomAccessFile raf = new RandomAccessFile("utf8.txt","rw");
//2.读写操作
raf.seek(3); //移动文件指针,从第4个位置开始覆盖写入
//a.将指针3后面的数据保存到 bao中
ByteArrayOutputStream bao = new ByteArrayOutputStream();
byte[] buffer = new byte[20];
int len;
while ( (len=raf.read(buffer))!=-1){
bao.write(buffer,0,len);
}//此时指针已经指向末尾了
//b.指针重新指向 指针3位置
raf.seek(3);
raf.write("呜呜".getBytes()); //插入数据
//c.写回后面保存的数据
raf.write(bao.toByteArray());
//3.关闭资源
raf.close();
bao.close();
}
文件多线程断点下载功能:
我们可以用RandomAccessFile这个类,来实现一个多线程断点下载的功能,用过下载工具的朋友们都知道,下载前都会建立 两个临时文件,一个是与被下载文件大小相同的空文件,另一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后断点下载的时候,会继续从上一次的地方下载,从而实现断点下载或上传的功能,有兴趣的朋友们可以自己实现下。
Java NIO
Java NIO 概述
Java NIO (New IO,Non-Blocking IO)是从Java 1.4版本开始引入的一套新的IO API,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的(IO是面向流的)、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。
Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。
|-----java.nio.channels.Channel
|-----FileChannel:处理本地文件
|-----SocketChannel:TCP网络编程的客户端的Channel
|-----ServerSocketChannel:TCP网络编程的服务器端的Channel
|-----DatagramChannel:UDP网络编程中发送端和接收端的Channel
JDK1.7发布 NIO.2:
原本的 java.io.File 升级未 java.nio.file包 :Path,Files,Paths核心API
Path可以看成是File类的升级版本,实际引用的资源也可以不存在。还提供了Files、Paths工具类
Path接口
Path 常用方法:
String toString() : 返回调用 Path 对象的字符串表示形式
boolean startsWith(String path) : 判断是否以 path 路径开始
boolean endsWith(String path) : 判断是否以 path 路径结束
boolean isAbsolute() : 判断是否是绝对路径
Path getParent() :返回Path对象包含整个路径,不包含 Path 对象指定的文件路径
Path getRoot() :返回调用 Path 对象的根路径
Path getFileName() : 返回与调用 Path 对象关联的文件名
int getNameCount() : 返回Path 根目录后面元素的数量
Path getName(int idx) : 返回指定索引位置 idx 的路径名称
Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象
Path resolve(Path p) :合并两个路径,返回合并后的路径对应的Path对象
File toFile(): 将Path转化为File类的对象
Files类
java.nio.file.Files 用于操作文件或目录的工具类。
Files 常用方法:
Path copy(Path src, Path dest, CopyOption … how) : 文件的复制
Path createDirectory(Path path, FileAttribute … attr) : 创建一个目录 Path createFile(Path path, FileAttribute … arr) : 创建一个文件
void delete(Path path) : 删除一个文件/目录,如果不存在,执行报错
void deleteIfExists(Path path) : Path对应的文件/目录如果存在,执行删除
Path move(Path src, Path dest, CopyOption…how) : 将 src 移动到 dest 位置
long size(Path path) : 返回 path 指定文件的大小Files 常用方法:用于判断
boolean exists(Path path, LinkOption … opts) : 判断文件是否存在
boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录
boolean isRegularFile(Path path, LinkOption … opts) : 判断是否是文件
boolean isHidden(Path path) : 判断是否是隐藏文件
boolean isReadable(Path path) : 判断文件是否可读
boolean isWritable(Path path) : 判断文件是否可写
boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在
Files 常用方法:用于操作内容
SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接, how 指定打开方式。
DirectoryStreamnewDirectoryStream(Path path) : 打开 path 指定的目录
InputStream newInputStream(Path path, OpenOption…how):获取 InputStream 对象
OutputStream newOutputStream(Path path, OpenOption…how) : 获取 OutputStream 对象

浙公网安备 33010602011771号