java io流相关的内容比较多,也比较杂,所以整理了这样一份笔记,供大家参考
File类
File类介绍
它是文件和目录路径名的抽象表示
文件和目录是可以通过File封装成对象的
对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。
它可以是存在的,也可以
是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的
绝对路径和相对路径的区别
绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件。例如:E:\itcast\java.txt
相对路径:必须使用取自其他路径名的信息进行解释。例如:myFile\java.txt
File类的构造方法
方法名 | 说明 |
---|---|
File(String pathname) | 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例 |
File(String parent, String child) | 从父路径名字符串和子路径名字符串创建新的 File实例 |
File(File parent, String child) | 从父抽象路径名和子路径名字符串创建新的 File实例 |
import java.io.File;
public class IO {
public static void main(String[] args) {
//File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
File file = new File("D:\\iotest\\java.txt");
System.out.println(file);
//File(String parent, String child):从父路径名字符串和子路径名字符串创建新的File实例
File file1 = new File("D:\\iotest","java.txt");
System.out.println(file1);
//File(File parent, String child):从父抽象路径名和子路径名字符串创建新的 File实例
File file2 = new File("D:\\iotest");
File file3 = new File(file2,"java.txt");
System.out.println(file3);
}
}
File类创建功能
方法名 | 说明 |
---|---|
public booleancreateNewFile() | 当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件 |
public boolean mkdir() | 创建由此抽象路径名命名的目录 |
public boolean mkdirs() | 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录 |
createNewFile()
当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件并返回true;
当文件已经存在时返回false
import java.io.File;
import java.io.IOException;
public class IO {
public static void main(String[] args) throws IOException {
// 当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件并返回true;
//当文件已经存在时返回false
File file = new File("D:\\iotest\\java.txt");
System.out.println(file.createNewFile());//true
System.out.println(file.createNewFile());//false
}
}
mkdir()
mkdir() 创建由此抽象路径名命名的目录
File file1 = new File("D:\\iotest\\javaSE");
System.out.println(file1.mkdir());//不存在则创建成功返回true;
mkdirs()
创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
File file2 = new File("D:\\iotest\\javaWEB\\HTML");
System.out.println(file2.mkdirs());
注意
创建文件还是需要使用createNewFile()
File file3 = new File("D:\\iotest\\javase.txt");
System.out.println(file3.mkdir());//会返回true并创建javase.txt的文件夹
// 创建文件还是需要用createNewFile()不然会生成.txt的文件夹
File类判断和获取功能
判断功能
方法名 | 说明 |
---|---|
public boolean isDirectory() | 测试此抽象路径名表示的File是否为目录 |
public boolean isFile() | 测试此抽象路径名表示的File是否为文件 |
public boolean exists() | 测试此抽象路径名表示的File是否存在 |
import java.io.File;
import java.io.IOException;
public class IO {
public static void main(String[] args) throws IOException {
File file = new File("D:\\iotest\\javaEE.txt");
System.out.println(file.isDirectory()); //false 不是文件夹
System.out.println(file.isFile()); //true 是文件
System.out.println(file.exists()); //true 文件存在
}
}
获取功能
方法名 | 说明 |
---|---|
public String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串 |
public String getPath() | 将此抽象路径名转换为路径名字符串 |
public String getName() | 返回由此抽象路径名表示的文件或目录的名称 |
public long length() | 获取文件的大小,返回字节长度 |
public long lastModified() | 获得最后一次修改的日期 |
public String[] list() | 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组 |
public File[] listFiles() | 返回此抽象路径名表示的目录中的文件和目录的File对象数组 |
import java.io.File;
import java.io.IOException;
public class IO {
public static void main(String[] args) throws IOException {
File file = new File("D:\\iotest\\javaEE.txt");
System.out.println(file.getAbsoluteFile()); //D:\iotest\javaEE.txt
System.out.println(file.getPath()); //D:\iotest\javaEE.txt
System.out.println(file.getName()); //javaEE.txt
}
}
list()
返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
import java.io.File;
import java.io.IOException;
public class IO {
public static void main(String[] args) throws IOException {
File file = new File("D:\\iotest");
// public String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
String[] list = file.list();
for(String s:list){
System.out.println(s);
}
}
}
listFiles()
返回此抽象路径名表示的目录中的文件和目录的File对象数组
import java.io.File;
import java.io.IOException;
public class IO {
public static void main(String[] args) throws IOException {
File file = new File("D:\\iotest");
// public String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
File[] files = file.listFiles();
for(File file1:files){
System.out.println(file1.getName());
}
}
}
listFiles()得到的是File对象数组,可以进行更多的操作如判断是文件还是文件夹等等
import java.io.File;
public class IO03 {
public static void main(String[] args) {
File srcfile = new File("D:\\iotest");
getallpaths(srcfile);
}
public static void getallpaths(File srcfile){
File[] files = srcfile.listFiles();
if(files!=null){
for (File f:files){
if (f.isDirectory()){
getallpaths(f);
}
else{
System.out.println(f.getAbsolutePath());
}
}
}
}
}
File类删除功能
方法名 | 说明 |
---|---|
public boolean delete() | 删除由此抽象路径名表示的文件或目录 |
import java.io.File;
import java.io.IOException;
public class IO {
public static void main(String[] args) throws IOException {
File file = new File("D:\\iotest\\javaSE");
if(file.exists())
{
System.out.println(file.delete());//删除文件夹 删除成功则返回true,同理可以删除文件等
}
}
}
注意,如果要删除文件夹时,如果文件夹里面有文件,则删除失败,返回false
IO流
IO:输入/输出(Input/Output)
流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传
输
IO流就是用来处理设备间数据传输问题的。常见的应用:文件复制;文件上传;文件下载
IO流的分类
按照数据的流向
输入流:读数据
输出流:写数据
按照数据类型来分
字节流 以InputStream或OutputStream结尾
字节输入流
字节输出流
字符流 以Reader或Writer结尾
字符输入流
字符输出流
IO流的使用场景
如果操作的是纯文本文件,优先使用字符流
如果操作的是图片、视频、音频等二进制文件。优先使用字节流
如果不确定文件类型,优先使用字节流。字节流是万能的流
字节流
字节流抽象基类
InputStream:这个抽象类是表示字节输入流的所有类的超类
OutputStream:这个抽象类是表示字节输出流的所有类的超类
子类名特点:子类名称都是以其父类名作为子类名的后缀
字节输出流
FileOutputStream(String name):创建文件输出流以指定的名称写入文件
使用字节输出流写数据的步骤
创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)
调用字节输出流对象的写数据方法
释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
构造方法
方法名 | 说明 |
---|---|
FileOutputStream(File file) | 创建文件输出流以写入由指定的 File对象表示的文件。 |
FileOutputStream(File file, boolean append) | 创建文件输出流以写入由指定的 File对象表示的文件。 |
FileOutputStream(String name) | 创建文件输出流以指定的名称写入文件。 |
FileOutputStream(String name, boolean append) | 创建文件输出流以指定的名称写入文件 |
当第二个参数为true是,则为追加写入
创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头
字节流写数据的三种方式
方法名 | 说明 |
---|---|
void write(int b) | 将指定的字节写入此文件输出流 一次写一个字节数据 |
void write(byte[] b) | 将 b.length字节从指定的字节数组写入此文件输出流 一次写一个字节数组数据 |
void write(byte[] b, intoff, int len) | 将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流 一次写一个字节数组的部分数据 |
一次写入一个字节数据
import java.io.FileOutputStream;
import java.io.IOException;
public class IO {
public static void main(String[] args) throws IOException {
FileOutputStream fos= new FileOutputStream("D:\\iotest\\javaSE");
/*
做了三件事情:
A:调用系统功能创建了文件
B:创建了字节输出流对象
C:让字节输出流对象指向创建好的文件
*/
fos.write(65);//:将指定的字节写入此文件输出流
//最后都要释放资源
fos.close();//关闭此文件输出流并释放与此流相关联的任何系统资源
}
}
一次写入一个字节数组
import java.io.FileOutputStream;
import java.io.IOException;
public class IO {
public static void main(String[] args) throws IOException {
FileOutputStream fos= new FileOutputStream("D:\\iotest\\javaSE");
String data="abcd";
fos.write(data.getBytes()); //abcd
fos.write(data.getBytes(),0,2);//ab
fos.close();//关闭字节流
}
}
字节流写数据如何实现换行
windows:\r\n
linux:\n
mac:\r
字节流写数据加异常处理
try-catch-finally
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}finally{
执行所有清除操作;
}
finally特点
被finally控制的语句一定会执行,除非JVM退出
import java.io.FileOutputStream;
import java.io.IOException;
public class IO {
public static void main(String[] args) {
//加入finally来实现释放资源
FileOutputStream fos = null;
try {
fos = new FileOutputStream("myByteStream\\fos.txt");
fos.write("hello".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
为简化关闭流的代码,Java1.7引入了try-with-resource语法,让资源在try-catch完毕后自动关闭
try(类 对象 = new 类()){
可能出现异常的代码
}catch(异常类型 对象){
处理异常的代码
}
注意:关闭的对象必须实现Closable接口,IO流都实现了该接口
字节输入流
FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream ,该文件由文件系统中的路径名name命名
字节输入流读取数据的步骤
创建字节输入流对象
调用字节输入流对象的读数据方法
释放资源
构造方法
方法名 | 说明 |
---|---|
FileInputStream(File file) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。 |
FileInputStream(String name) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名 |
读文件的方法
方法名 | 说明 |
---|---|
int read() | 从该输入流读取一个字节的数据 |
int read(byte[] b) | 从该输入流读取最多 b.length个字节的数据到一个字节数组 |
int read(byte[] b, int off, int len) | 从该输入流读取最多 len个字节的数据到字节数组 |
int read() 读取文件数据返回值是读取长度-1代表读取完毕
int read(byte[] buffer) 读取文件数据,保存到字节数组中,返回值是读取长度-1代表读取完毕,返回的是读入缓冲区的总字节数,也就是实际的读取字节个数
一次读一个字节数据
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class IO {
public static void main(String[] args) {
FileInputStream fis= null;
try {
fis = new FileInputStream("D:\\iotest\\dyk3.txt");
int by;
/*
fis.read():读数据
by=fis.read():把读取到的数据赋值给by
by != -1:判断读取到的数据是否是-1
*/
while((by=fis.read())!=-1)
{
System.out.print((char)by);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
一次读一个字节数组数据
write(byte[] buffer,int offset,int length) 写入文件,offset开始位置,length写入长度
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class IO {
public static void main(String[] args) {
FileInputStream fis= null;
try {
fis = new FileInputStream("D:\\iotest\\dyk3.txt");
byte[] bytes=new byte[1024];
int len;
while((len=fis.read(bytes))!=-1)
{
System.out.print(new String(bytes,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字节流复制文本文件
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class IO {
public static void main(String[] args) {
FileInputStream fis= null;
FileOutputStream fos=null;
try {
fis = new FileInputStream("D:\\iotest\\dyk3.txt");
fos=new FileOutputStream("D:\\iotest\\test1.txt");
byte[] bytes=new byte[1024];
int len;
while((len=fis.read(bytes))!=-1)
{
fos.write(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos!=null)
{
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字节缓冲流
字节缓冲流介绍
lBufferOutputStream:该类实现缓冲输出流。 通过设置这样的输出流,应用程序可
以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
lBufferedInputStream:创建BufferedInputStream将创建一个内部缓冲区数组。
当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,
一次很多字
如果没有缓冲,文件读写是直接从磁盘上进行的,速度比较慢;缓冲就是在内存建立一个空间,读写之前将一部分磁盘上的数据导入到缓冲内存中,后面读写就直接从缓冲中进行,减少了直接从磁盘读写的次数,从而提高读写效率。
缓冲流:在普通的IO流基础上,加入内存缓冲区,提高IO效率。
方法名 | 说明 |
---|---|
BufferedOutputStream(OutputStream out) | 创建字节缓冲输出流对象 |
BufferedInputStream(InputStream in) | 创建字节缓冲输入流对象 |
BufferedInputStream(InputStream in, int size) | 创建具有指定缓冲区大小的 BufferedInputStream ,并保存其参数,输入流 in供以后使用 |
BufferedOutputStream(OutputStream out, int size) | 创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流 |
如果不指定缓冲流大小默认是8192
字节缓冲流复制文件
import java.io.*;
import java.nio.Buffer;
public class IO {
public static void main(String[] args) {
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try {
bis= new BufferedInputStream(new FileInputStream("D:\\iotest\\dyk3.txt"));
bos=new BufferedOutputStream(new FileOutputStream("D:\\iotest\\test1.txt"));
byte[] bytes=new byte[1024];
int len;
while((len=bis.read(bytes))!=-1)
{
bos.write(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(bis!=null){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bos!=null)
{
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符流
字符流的介绍
由于字节流操作中文不是特别的方便,所以Java就提供字符流
字符流 = 字节流 + 编码表
以字符char为单位进行的流,适合操作文本数据
中文的字节存储方式
用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼接
成中文,如何识别是中文的呢?
汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数
常见的字符集
ASCII字符集:
lASCII:是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字
符(回车键、退格、
换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)
基本的ASCII字符集,使用7位表示一个字符,共128字符。ASCII的扩展字符集使用
8位表示一个字符,共256字符,方便支持欧洲常用字符。是一个系统支持的所有字符
的集合,包括各国家文字、标点符号、图形符号、数字等
GBXXX字符集:
GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方
案,共收录了
21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等
Unicode字符集:
UTF-8编码:可以用来表示Unicode标准中任意字符,它是电子邮件、网页及其他存储或传送文字的应用
中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。它使用
一至四个字节为每个字符编码
编码规则:
128个US-ASCII字符,只需一个字节编码
拉丁文等字符,需要二个字节编码
大部分常用字(含中文),使用三个字节编码
其他极少使用的Unicode辅助字符,使用四字节编码
字符串编码相关的方法
方法名 | 说明 |
---|---|
byte[] getBytes() | 使用平台的默认字符集将该 String编码为一系列字节 |
byte[] getBytes(String charsetName) | 使用指定的字符集将该 String编码为一系列字节 |
String(byte[] bytes) | 使用平台的默认字符集解码指定的字节数组来创建字符串 |
String(byte[] bytes, String charsetName) | 通过指定的字符集解码指定的字节数组来创建字符串 |
字符流中和编码解码问题相关的两个类
InputStreamReader:是从字节流到字符流的桥梁
它读取字节,并使用指定的编码将其解码为字符
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
OutputStreamWriter:是从字符流到字节流的桥梁
是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
构造方法
方法名 | 说明 |
---|---|
InputStreamReader(InputStream in) | 使用默认字符编码创建InputStreamReader对象 |
InputStreamReader(InputStream in,Stringchatset) | 使用指定的字符编码创InputStreamReader对象 |
OutputStreamWriter(OutputStream out) | 使用默认字符编码创建OutputStreamWriter对象 |
OutputStreamWriter(OutputStream out,Stringcharset) | 使用指定的字符编码创建OutputStreamWriter对象 |
字符流写数据的5种方式
方法名 | 说明 |
---|---|
void write(int c) | 写一个字符 |
void write(char[] cbuf) | 写入一个字符数组 |
void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
void write(String str) | 写一个字符串 |
void write(String str, int off, int len) | 写一个字符串的一部分 |
字符流读数据的2种方式
方法名 | 说明 |
---|---|
int read() | 一次读一个字符数据 |
int read(char[] cbuf) | 一次读一个字符数组数据 |
刷新和关闭的方法
和字节流不一样字符流必须要调用flush方法刷新才会显示出来,close方法会自动调用刷新方法
方法名 | 说明 |
---|---|
flush() | 刷新流,之后还可以继续写数据 |
close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
字符流指定gbk编码复制文件
import java.io.*;
import java.nio.Buffer;
public class IO {
public static void main(String[] args) {
InputStreamReader isr=null;
OutputStreamWriter osw=null;
try {
isr= new InputStreamReader(new FileInputStream("D:\\iotest\\dyk3.txt"),"GBK");
osw=new OutputStreamWriter(new FileOutputStream("D:\\iotest\\test1.txt"),"GBK");
char[] chars=new char[1024];
int len;
while((len=isr.read(chars))!=-1)
{
//osw.write(chars,0,len);
osw.write(new String(chars,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(isr!=null){
try {
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(osw!=null)
{
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
FileReader和FileWriter
public class FileReader extends InputStreamReader
FileReader用于读取字符流
public class FileWriter extends OutputStreamWriter
FileWriter用于写入字符流
可以直接通过路径和文件创建对应的字符流对象,而不需要先创建字节流对象
构造方法
方法名 | 说明 |
---|---|
FileReader(File file) | 创建一个新的 FileReader ,给出 File读取 |
FileReader(String fileName) | 创建一个新的 FileReader ,给定要读取的文件的名称 |
FileReader和FileWriter复制文件
import java.io.*;
import java.nio.Buffer;
public class IO {
public static void main(String[] args) {
FileReader fr=null;
FileWriter fw=null;
try {
fr=new FileReader("D:\\iotest\\dyk3.txt");
fw=new FileWriter("D:\\iotest\\test1.txt");
char[] chars=new char[1024];
int len;
while((len=fr.read(chars))!=-1)
{
//osw.write(chars,0,len);
fw.write(new String(chars,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fr!=null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fw!=null)
{
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符缓冲流
字符缓冲流介绍
BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符
串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用
于大多数用途
BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效
读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途
构造方法
方法名 | 说明 |
---|---|
BufferedWriter(Writer out) | 创建字符缓冲输出流对象 |
BufferedReader(Reader in) | 创建字符缓冲输入流对象 |
字符缓冲流复制文件
import java.io.*;
import java.nio.Buffer;
public class IO {
public static void main(String[] args) {
BufferedReader br=null;
BufferedWriter bw=null;
try {
br=new BufferedReader(new FileReader("D:\\iotest\\dyk3.txt"));
bw =new BufferedWriter(new FileWriter("D:\\iotest\\test1.txt"));
char[] chars=new char[1024];
int len;
while((len=br.read(chars))!=-1)
{
//osw.write(chars,0,len);
bw.write(new String(chars,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(br!=null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bw!=null)
{
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符缓冲流特有功能
BufferedWriter:
方法名 | 说明 |
---|---|
void newLine() | 写一行行分隔符,行分隔符字符串由系统属性定义 |
BufferedReader:
方法名 | 说明 |
---|---|
String | |
readLine() | 读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符如果流的结尾已经到达,则为null |
字符缓冲流特有功能复制文件
import java.io.*;
import java.nio.Buffer;
public class IO {
public static void main(String[] args) {
BufferedReader br=null;
BufferedWriter bw=null;
try {
br=new BufferedReader(new FileReader("D:\\iotest\\dyk3.txt"));
bw =new BufferedWriter(new FileWriter("D:\\iotest\\test1.txt"));
String line;
while((line=br.readLine())!=null)
{
bw.write(line);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(br!=null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bw!=null)
{
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
IO特殊操作流
标准输入流和标准输出流
System类中有两个静态的成员变量
public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标
字节打印流
打印流分类
字节打印流:PrintStream
字符打印流:PrintWriter
打印流的特点
只负责输出数据,不负责读取数据
永远不会抛出IOException
有自己的特有方法
字节打印流
PrintStream(String fileName):使用指定的文件名创建新的打印流
使用继承父类的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看的数据原样输出
可以改变输出语句的目的地
public static void setOut(PrintStream out):重新分配“标准”输出流
字符打印流构造方法
方法名 | 说明 |
---|---|
PrintWriter(StringfileName) | 使用指定的文件名创建一个新的PrintWriter,而不需要自执行刷新 |
PrintWriter(Writerout, booleanautoFlush) | 创建一个新的PrintWriter out:字符输出流 utoFlush: 一个布尔值,如果为真,则println , printf ,或format方法将刷新输出缓冲区 |
字符打印流复制文件
import java.io.*;
public class IO {
public static void main(String[] args) {
BufferedReader br=null;
PrintWriter pw=null;
try {
br=new BufferedReader(new FileReader("D:\\iotest\\dyk3.txt"));
pw =new PrintWriter(new FileWriter("D:\\iotest\\test1.txt"),true); //true自动刷新
String line;
while((line=br.readLine())!=null)
{
pw.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(br!=null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(pw!=null)
{
pw.close();
}
}
}
}
对象序列化流
对象序列化介绍
对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
对象序列化流: ObjectOutputStream
将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对
象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
构造方法
方法名 | 说明 |
---|---|
ObjectOutputStream(OutputStreamout) | 创建一个写入指定的OutputStreamObjectOutputStream |
序列化对象的方法
方法名 | 说明 |
---|---|
void writeObject(Object obj) | 将指定的对象写入ObjectOutputStream |
对象反序列化流: ObjectInputStream
ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
方法名 | 说明 |
---|---|
ObjectInputStream(InputStream in) | 创建从指定的InputStream读取的ObjectInputStream |
反序列化对象的方法
方法名 | 说明 |
---|---|
Object readObject() | 从ObjectInputStream读取一个对象 |
注意事项
一个对象要想被序列化,该对象所属的类必须必须实现Serializable 接口
Serializable是一个标记接口,实现该接口,不需要重写任何方法
只有实现了Serializable接口的对象,才能序列化,否则会抛出NotSerializableException
如果父类实现了Serializable接口,子类可以不实现该接口
类要序列化,类所有的属性也要序列化
声明为static和transient类型的属性不能被序列化
student类
import java.io.Serializable;
public class student implements Serializable {
private int age;
private String name;
public student() {
}
public student(int age, String name) {
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 "student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
当传入的是一个对象时
import java.io.*;
public class IO {
public static void main(String[] args) {
student stu = new student(18, "dyk");
ObjectInputStream ois= null;
ObjectOutputStream oos= null;
try {
oos = new ObjectOutputStream(new FileOutputStream("D:\\iotest\\dyk3.txt"));
ois=new ObjectInputStream(new FileInputStream("D:\\iotest\\dyk3.txt"));
oos.writeObject(stu);
Object o = ois.readObject();
stu=(student)o;
System.out.println(stu);//student{age=18, name='dyk'}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if(oos!=null) {
oos.close();
}
if(ois!=null)
{
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
当存入的是一个集合时
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class IO {
public static void main(String[] args) {
List<student> arr=new ArrayList<>();
student stu = new student(18, "dyk");
student stu1=new student(19,"cb");
student stu2=new student(20,"lfw");
arr.add(stu);
arr.add(stu1);
arr.add(stu2);
ObjectInputStream ois= null;
ObjectOutputStream oos= null;
try {
oos = new ObjectOutputStream(new FileOutputStream("D:\\iotest\\dyk3.txt"));
ois=new ObjectInputStream(new FileInputStream("D:\\iotest\\dyk3.txt"));
oos.writeObject(arr);
Object o = ois.readObject();
List<student> arr1=(List<student>)o;
for(int i=0;i<arr1.size();i++){
System.out.println(arr1.get(i));
// student{age=18, name='dyk'}
// student{age=19, name='cb'}
// student{age=20, name='lfw'}
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if(oos!=null) {
oos.close();
}
if(ois!=null)
{
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
无论是一个Java对象,或是一个Java集合都可以序列化到文件中,因为Java所有的集合也都实现了Serializable接口
serialVersionUID
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
会出问题,会抛出InvalidClassException异常
如果出问题了,如何解决呢?
重新序列化
给对象所属的类加一个serialVersionUID
private static final long serialVersionUID = 42L;
serialVersionUID是序列化类的版本号,
如果不手动添加,系统会自动添加版本号,序列化对象后,如果类的代码进行任意的修改,类版本号会改变,进行反序列化时,对象出现类型不兼容的问题InvalidClassException。
如果手动添加该常量,类修改后版本号不变,反序列化是就不会出现类型不兼容问题
transient
如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
Properties集合
Properties介绍
是一个Map体系的集合类
Properties可以保存到流中或从流中加载
属性列表中的每个键及其对应的值都是一个字符串
注意下Properties是没有泛型的
Properties基本使用
import java.util.Properties;
import java.util.Set;
public class IO {
public static void main(String[] args) {
Properties properties=new Properties();
properties.put("dyk",18);
properties.put("cb",19);
properties.put("lfw",20);
Set<Object> objects = properties.keySet();
for(Object o:objects)
{
Object o1 = properties.get(o);
System.out.println("姓名:"+o+"年龄:"+o1);
}
}
}
Properties作为Map集合的特有方法
方法名 | 说明 |
---|---|
Object setProperty(String key,String value) | 设置集合的键和值,都是String类型,底用 Hashtable方法 put |
String getProperty(String key) | 使用此属性列表中指定的键搜索属性 |
Set stringPropertyNames() | 从该属性列表中返回一个不可修改的键集,其中键及其对的值是字符串 |
import java.util.Properties;
import java.util.Set;
public class IO {
public static void main(String[] args) {
Properties properties=new Properties();
properties.setProperty("dyk","18");
properties.setProperty("cb","19");
properties.setProperty("lfw","20");
Set<String> strings = properties.stringPropertyNames();
for(String s:strings)
{
String property = properties.getProperty(s);
System.out.println("姓名:"+s+"年龄:"+property);
}
}
}
Properties和IO流相结合的方法
方法名 | 说明 |
---|---|
void load(InputStreaminStream) | 从输入字节流读取属性列表(键和元素对) |
void load(Reader reader) | 从输入字符流读取属性列表(键和元素对) |
void store(OutputStreamout, String comments) | 将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(InputStream)方法的格式写入输出字节流 |
void store(Writer writer,String comments) | 将此属性列表(键和元素对)写入此Properties表中,以适合使用load(Reader)方法的格式写入输出字符流 |
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
public class IO {
public static void main(String[] args) {
Properties properties = new Properties();
properties.setProperty("dyk","18");
properties.setProperty("cb","19");
properties.setProperty("lfw","20");
FileReader fr=null;
FileWriter fw=null;
try {
fw=new FileWriter("D:\\iotest\\dyk2.txt");
fr = new FileReader("D:\\iotest\\dyk2.txt");
properties.store(fw,null);
Properties properties1=new Properties();
properties1.load(fr);
Set<String> strings = properties1.stringPropertyNames();
for(String s:strings)
{
String property = properties1.getProperty(s);
System.out.println("姓名:"+s+"年龄:"+property);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fw!=null) {
fw.close();
}
if(fr!=null)
{
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}