目录
5、FileInputStream和FileOutputStream
FileInputStream和FileOutputStream的API
7、BufferedInputStream和BufferedOutputStream
BufferedInputStream和BufferedOutputStream的API
10、BufferedReader和BufferedWriter
BufferedReader和BufferedWriter的API
11、InputStreamReader和OutputStreamWriter
InputStreamReader和OutputStreamWriter的API
一、File类
1、基本概念
文件信息
指文件名,类型,扩展名 ,修改时间等
相对路径
指相较于某个路径下,指明的路径
绝对路径
指包含盘符在内的文件及文件目录的路径
路径分隔符
路径中的每级目录之间用一个路径分隔符隔开
windows和DOS:“\”
UNIX和URL:“/”
因为Java程序支持跨平台运行,因此路径分隔符要慎用。
为了解决跨平台隐患,File类提供了一个常量:
public static final String separator:根据操作系统,动态的提供分隔符
2、File类的用处
- File类声明在java.io包下:java.io.File
- File类的一个对象,表示一个文件或一个文件目录
- File类能新建、删除、重命名文件和目录,但不能对文件内容进行访问
- File对象可以作为参数传递给流的构造器
3、File类的构造方法
- public File(String pathname) :以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果 pathname是相对路径,则默认的当前路径在系统属性user.dir中存储
- public File(String parent,String child) :以parent为父路径,child为子路径创建File对象
- public File(File parent,String child) :根据一个父File对象和子文件路径创建File对象
4、File类的API
- File(String pathname):根据路径的名字读取一个文件或一个文件目录信息,并在内存中创建一个File对象
- String getName():获取名称
- String getPath():获取路径
- String getAbsolutePath():获取绝对路径
- File getParentFile():获取上一级目录
- String getParent():获取上层文件目录的路径,若无,返回null
- long length():获取文件的长度即字节数,不能获取目录的长度。如果文件内容为空,或者文件不存在,返回0
- long lastModified():获取最后一次修改的时间,毫秒值
- boolean exists():判断当前文件或目录是否存在
- boolean isFile():判断是否是文件
- boolean isDirectory():判断是否是目录
- boolean createNewFile():用于创建一个空文件,如果文件存在,就不会创建文件
- boolean mkdir():用于创建目录,如果目录已经存在返回false ,只能创建最后一级目录
- boolean mkdirs():用于创建多级目录,就是一个完整的目录树
- boolean delete():用于删除文件或目录,只能删除文件或空目录
- String[] list():获取指定目录下的所有文件或文件目录的名称数组
- File[] listFiles():获取指定目录下的所有文件或文件目录的File数组
- File[] listFiles(FileFilter filter):获取根据指定过滤信息找到的满足条件的File数组
5、File类的练习
使用代码创建一个java工程目录
|-.settings目录
|-.classpath文件
|-.project文件
|-src目录
|-bin目录
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) throws IOException {
File f1 = new File("D:/javahomework");
Boolean isMk = f1.mkdirs();
System.out.println("主目录是否被创建:"+isMk);
File f2 = new File("D:/javahomework/settings");
File f3 = new File("D:/javahomework/.classpath");
File f4 = new File("D:/javahomework/.project");
File f5 = new File("D:/javahomework/src");
File f6 = new File("D:/javahomework/bin");
Boolean isMk2 = f2.mkdirs();
Boolean isCreate3 = f3.createNewFile();
Boolean isCreate4 = f4.createNewFile();
Boolean isMk5 = f5.mkdirs();
Boolean isMk6 = f6.mkdirs();
System.out.println("子目录是否被创建:"+isMk2);
System.out.println("文件classpath是否被创建:"+isCreate3);
System.out.println("文件project是否被创建:"+isCreate4);
System.out.println("子目录是否被创建:"+isMk5);
System.out.println("子目录是否被创建:"+isMk6);
}
}
二、RandomAccessFile类
1、RandomAccessFile类
RandomAccessFile类声明在java.io包下:java.io.RandomAccessFile。
2、RandomAccessFile类的实现原理
在文件内部使用一个游标指针,这个指针可以随意指向文件的任何位置,然后通过指针访问文件内容。
3、RandomAccessFile类的API
- RandomAccessFile(File file, String mode):File:文件对象信息,String mode:r读 w:写 rw:读写
- long length():文件的长度
- int read():从文件中读取一个字节的数据,返回值为int类型,读取的内容为一个字节,把字节无符号扩展为int
- void write(int b):将一个字节的数据写入到文件,只会取低八位保存到文件中
- int read(byte[] b):将读取的数据保存到数组中,并返回读取数据长度;
- void write(byte[] b,int off,int len):将数组中的数据 从 off开始,把长度为len的数据写入到文件
- byte[] b:读取的数据,int off:从off下标开始,int len:读取数据的长度,如果到了文件末尾返回-1,游标都会后移一个位置
- void close():关闭文件
- long getFilePointer():获取指针的位置
- void seek(long pos):设置指针的位置
4、RandomAccessFile类的练习
1、复制文件
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDome {
public static void main(String[] args) throws IOException{
copy();
}
private static void copy() throws IOException{
File f1 = new File("D:/0/0.txt");
RandomAccessFile f2 = new RandomAccessFile(f1,"rw");
File f3 = new File("D:/javahomework/0.text");
RandomAccessFile f4 = new RandomAccessFile(f3,"rw");
if(!f3.exists()){
f3.createNewFile();
}
while (true){
int data = f2.read();
if(data == -1){
break;
}
f4.write(data);
}
f2.close();
f4.close();
}
}
2、图片美白
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class PicDemo {
public static void main(String[] args) throws IOException {
File f = new File("D:/javahomework/1.bmp");
RandomAccessFile raf = new RandomAccessFile(f,"rw");
raf.seek(54);
while (true){
int data = raf.read();
long pointer = raf.getFilePointer();
if(data == -1)break;
data+=100;
if(data>255){
data = 255;
}
raf.seek(pointer-1);
raf.write(data);
}
raf.close();
}
}
三、IO流原理及分类
1、IO流
- I/O是Input/Output的缩写
- IO流用于处理设备之间的数据传输
- Java程序中,对数据的输入输出操作以“流(stream)”的方式进行
- IO流原理:以内存或内存中存在应用程序实例(进程)为参照物,向其输入数据(Input)或输出数据(Output)
- Input(输入):读取外部数据(磁盘,光盘,网络等)到程序(内存)中
- Output(输出):将程序(内存)中的数据输出到磁盘,光盘,网络等存储设备中
- java.io包下提供各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法对数据进行输入或输出
2、文件的分类
- 文本文件:字符(char),.txt,.java,.html,.xml
- 二进制文件:二进制(byte),.docx,视频,音频,图片
3、IO流的分类
- 按操作的数据单位分:字节流(byte 8bit),字符流(char 16bit)
- 按流的流向分:输入流,输出流
- 按流的角色分:节点流(能直接和介质相连的IO流,介质:文件、网络等),处理流(只能和IO流连接的IO流)
抽象基类 | 字节流 | 字符流 |
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
- 字节流:读取的最小单位是byte
- 字符流:读取的最小单位是char
- 注:Java的IO流虽然共涉及四十多个类,但实际上非常规则,因为四十多个类都是四个抽象基类派生的,由这四个抽象基类派生的子类都是以其父类名作为子类名的后缀
抽象基类 | 节点流(文件流) | 缓冲流(处理流的一种) |
InputStream | FileInputStream | BufferedInputStream |
OutputStream | FileOutputStream | BufferedOutputStream |
Reader | FileReader | BufferedReader |
Writer | FileWriter | BufferedWriter |
4、InputStream和OutputStream
- 最小单位:字节(byte)
- 字节流的抽象基类
InputStream和OutputStream的API
- int read():读取一个字节的数据,返回一个无符号的int
- int read(byte[] b):将读取的数据存储到数组中,并且返回读取数据数据的长度,如果到了文件末尾,返回-1
- void close():关闭IO流
- void write(byte[] b, int off, int len):将数组中从off开始,长度为len的数据写入到文件中
- void flush():将数据刷出
5、FileInputStream和FileOutputStream
- 文件字节流;
- 节点流
FileInputStream和FileOutputStream的API
- FileInputStream(File file):File file:文件对象
- FileInputStream(String name):String name:文件路径
- FileOutputStream(File file):File file:文件对象
- FileOutputStream(File file, boolean append):File file:文件对象;boolean:true:在原有的文件内容基础上追加;false:将源文件的内容给覆盖
- FileOutputStream(String name):String name:文件路径
- FileOutputStream(String name, boolean append):String name:文件路径;boolean:true:在原有的文件内容基础上追加;false:将源文件的内容给覆盖
6、练习
将0.txt和1.txt合并为一个3.txt文件
import java.io.*;
public class Merge {
public static void main(String[] args) throws IOException {
mergeByte();
}
private static void mergeByte() throws IOException{
BufferedInputStream bis0 = new BufferedInputStream(new FileInputStream(new File("D:/0/0.txt")));
BufferedInputStream bis1 = new BufferedInputStream(new FileInputStream(new File("D:/0/1.txt")));
BufferedOutputStream bos3 = new BufferedOutputStream(new FileOutputStream(new File("D:/0/3.txt"),true));
byte[] data = new byte[1024];
while (true){
int len = bis0.read(data);
if(len==-1)break;
bos3.write(data,0,len);
}
bis0.close();
while (true){
int len = bis1.read(data);
if(len==-1)break;
bos3.write(data,0,len);
}
bis1.close();
bos3.close();
}
}
7、BufferedInputStream和BufferedOutputStream
- 缓冲流,内部有缓存,缓冲区大小,默认8k
- 处理流
BufferedInputStream和BufferedOutputStream的API
- BufferedInputStream(InputStream in):InputStream in:字节节点流或字节处理流
- BufferedInputStream(InputStream in, int size):InputStream in:字节节点流或字节处理流;int size:可以手动设置缓冲区大小,默认:8k
- BufferedOutputStream(OutputStream out):OutputStream out:字节节点流或字节处理流
- BufferedOutputStream(OutputStream out, int size):OutputStream out:字节节点流或字节处理流;int size:可以手动设置缓冲区大小,默认:8k
8、Reader和Writer
- 最小单位:字符(char)
- 字符流的抽象基类
Reader和Writer的API
- int read():读取数据是一个字符,返回值也是经过了无符号扩展
- int read(char[] cbuf):读取的数据保存在char数组中,并且返回读取字符的长度,如果到达文件末尾返回-1
- void close():关闭管道流的方法
- void write(int c):写入一个字符,写数据的时候将高16位去掉
- void write(char[] cbuf, int off, int len):将数组中从off开始,len长度的字符写入到文件中
- void write(String str):将字符串写入到文件中
- Writer append(char c)将字符追加到文件中
- void flush():将数据刷出
9、FileReader和FileWriter
- 文件字符流
- 节点流
FileReader和FileWriter的API
- FileReader(File file):File file:文件对象
- FileReader(String fileName):String fileName:文件的路径
- FileWriter(File file):File file:文件对象
- FileWriter(File file, boolean append):File file:文件对象;boolean:true:在原有的文件内容基础上追加,false:将源文件的内容给覆盖
- FileWriter(String fileName):String fileName:文件的路径
- FileWriter(String fileName, boolean append):String fileName:文件的路径;boolean:true在原有的文件内容基础上追加,false将源文件的内容给覆盖
10、BufferedReader和BufferedWriter
- 缓冲流,内部有缓存,缓冲区大小,默认16k
- 处理流
BufferedReader和BufferedWriter的API
- BufferedReader(Reader in):Reader in:字符节点流或字符处理流
- String readLine():读取一个文本行,行尾有一个\n,返回值null
- BufferedWriter(Writer out):Writer out:字符节点流或字符处理流
- BufferedWriter(Writer out, int sz):Writer out:字符节点流或字符处理流;int sz:可以手动设置缓冲区大小,默认:16k
- void newLine():写入一个行分隔符
11、InputStreamReader和OutputStreamWriter
- 转换流,将字节流转换成字符流 (文本文件)
- 处理流
InputStreamReader和OutputStreamWriter的API
- InputStreamReader(InputStream in):InputStream in:节点流或处理流
- InputStreamReader(InputStream in, String charsetName):InputStream in:节点流或处理流;String charsetName:字符集 ,默认OS字符集
- OutputStreamWriter(OutputStream out):OutputStream out:节点流或处理流
- OutputStreamWriter(OutputStream out, String charsetName):OutputStream out:节点流或处理流;String charsetName:字符集 ,默认OS字符集
- 常用字符集:utf-8,GBK,GB2312,ISO8859-1
12、PrintStream和PrintWriter
- 打印流,既是节点流又是处理流
- 实现将基本数据类型的数据格式转化为字符串输出
- 提供了一系列重载的print()和println()方法,用于多种数据类型的输出
- PrintStream和PrintWriter的输出不会抛出IOException异常
- PrintStream和PrintWriter有自动flush功能
- PrintStream打印的所有字符都使用平台的默认字符编码转换为字节,在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类
- System.out返回的是PrintStream的实例
PrintWriter的API
- PrintWriter(File file):File file:文件对象
- PrintWriter(String fileName):String fileName:文件路径
- PrintWriter(OutputStream out):OutputStream out:字节输出流
- PrintWriter(Writer out):Writer out:字符输出流
- void print(String s):String s:输出字符串
- void println(String x):String x:输出字符串并且换行
- void print(Object obj):Object obj:输出对象
13、练习
下载网页
URL url = new URL("http://www.baidu.com");
InputStream in =url.openStream();
import java.io.*;
import java.net.URL;
public class Nett {
public static void main(String[] args) throws IOException {
myNett();
}
private static void myNett() throws IOException{
BufferedReader br1 = new BufferedReader(new InputStreamReader(
new URL("https://www.baidu.com/").openStream(),"utf-8"));
BufferedWriter bw1 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:/0/net.txt")));
char[] buf = new char[1024];
while(true){
int len = br1.read(buf);
if(len == -1)break;
String str = new String(buf,0,len);
bw1.write(str);
}
br1.close();
bw1.close();
}
}
14、总结
读写二进制文件
- new BufferedInputStream(new FileInputStream())
- new BufferedOutputStream(new FileOutputStream())
读写文本文件
- new BufferedReader(new FileReader())
- new BufferedWriter(new FileWriter())
将字节流转换成字符流
- new BufferedReader(new InputStreamReader(new FileInputStream(),"utf-8"))
- new BufferedWriter(new OutputStreamWriter(new FileOutputStream(),"utf-8"))
读取控制信息
- new Scanner(System.in)
- new BufferedInputStream(System.in)
打印各种格式信息
- new PrintWriter(new BufferedWriter(new FileWriter()))
读写对象(序列化和反序列化)
- new ObjectInputStream(new BufferedInputStream(new FileInputStream()))
- new ObjectOutputStream(new BufferdOutputStream(new FileOutputStream()))
序列化和反序列化
- 序列化:将内存中的对象转换成二进制的过程
- 反序列化:将二进制数据转换成内存中的对象
序列化和反序列化管道
- new ObjectInputStream(new BufferedInputStream(new FileInputStream()))
- new ObjectOutputStream(new BufferdOutputStream(new FileOutputStream()))
四、字符编码
常见的编码表
- ASCII:美国标准信息交换码,用一个字节的7位可以表示
- ISO8859-1:拉丁码表,欧洲码表,用一个字节的8位表示
- GB2312:中国的中文编码表,最多两个字节编码所有字符
- GBK:中国的中文编码表升级,融合了更多的中文文字符号,最多两个字节编码
- Unicode:国际标准码,融合了目前人类使用的所有字符,为每个字符分配唯一的 字符码,所有的文字都用两个字节来表示
- UTF-8:变长的编码方式,可用1~4个字节来表示一个字符
五、transient关键字
被关键字修饰的字段不参与序列化(密码等敏感字段,在序列化时,不允许写到文件,字段前加transient关键字进行修饰)
六、Serializable接口
- 标识接口
- 要序化的对象必须实现Serializable接口,以启动序列化的功能
- 静态是不能被序列化的(序列化只能对堆中的对象进行序列化,不能对方法区中的对象进行序列化)
七、浅拷贝和深拷贝
- 深拷贝:通过序列化和反序列实现对象完全拷贝
- 浅拷贝:JVM默认是的一种拷贝方式
八、NIO
早期的Java只提供了一个File类来访问文件系统,但File类的功能比较有限,提供的方法性能也不高,大多数方法在出错时仅返回失败,并不会提供异常信息。
NIO为了弥补不足,引入了Path接口,代表一个平台无关的平台路径,描述了目录结构中文件的位置。
Path可以看成是File类的升级,引用的资源可以不存在。
IO:
import java.io.File;
File file = new File("01.html");
NIO:
import java.nio.file.Path;
import java.nio.file.Paths;
Path path = Paths.get("01.html");