IO流
1、什么是IO流?
通过IO流可以完成硬盘文件的读和写
2、IO流的分类?
-
(1)、按照流的方向进行分类:
【以内存作为参照物】 往内存中去,叫做输入。或者叫做读。 从内存中出来,叫做输出。或者叫做写。
-
(2)、按读取数据方式不同进行分类:
-
字节流:
按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位,这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频等。
假设文件file。TXT,采用字节流的方式:
a中国bc张三f
第一次读:一个字节,正好读到‘a’
第二次读:一个字节,正好读到‘中’字符的一半
第三次读:一个字节,正好读到‘中’字符的另一半。 -
字符流:
按照字符的方式读取数据,一次读取一个字符,这种流是为了方便读取普通文本而存在的,这种流不能读取:图片、声音、视频等文件。只能读取纯文本文件,连Word文件都无法读取
假设文件file。TXT,采用字节流的方式:
a中国bc张三fe
第一次读:‘a’字符(‘a’字符在Windows系统中占用1个字节)
第二次读:‘中’字符(‘中’字符在Windows系统中占用2个字节)
综上所述:流的分类:
输入流、输出流 字节流、字符流
3、java中的IO流都已经写好,程序员不需要关心,最主要的还是掌握,在java中已经提供了哪些流,每个流的特点是什么?每个流对象上的常用方法有哪些?
java中所有的流都是在java.io.*;下
java中主要研究:
怎么new对象
调用流对象的哪个方法是读,哪个方法是写。
4、java IO流有四大家族:
四大家族首领:【都是抽象类】
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流java.io.Reader 字符输入流
java.io.Writer 字符输出流
注意:在java中只要“类名”以Stream结尾的都是字节流,以“Reader/Writer”结尾的都是字符流。
**所有的流都实现了:
java.io.Closeable接口,都是可关闭的,都有close方法**。
流是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭,
不然会耗费(占用)很多资源。一定养成用完流就关闭的习惯。
*所有的输出流都实现了:
java.io.Flushable接口,都是可刷新的,都有flush()方法。
养成这样一个习惯:
输出流在最终输出之后,一定要记得flush()方法刷新一下,这个刷新表示
将通道/管道当中剩余未输出的数据强行输出完(清空管道!)刷新的作用就是
清空管道。
注意:如果没有flush可能会导致数据丢失。
5、java.io包下需要掌握的流有16个:
-
文件专属:
java.io.FileInputStream java.io.FileOutputStream java.io.FileReader java.io.FileWriter
-
转换流:(将字节流转换成字符流)
java.io.InputStreamReader java.io.OutputStreamWriter
-
缓冲流专属:
java.io.BufferedReader java.io.BufferedWriter java.io.BufferedInputStream java.io.BufferedOutputStream
-
数据流专属:
java.io.DataInputStream java.io.DataOutputStream
-
标准输出流:
java.io.PrintWriter java.io.PrintStream
-
对象专属流:
java.io.ObjectInputStream java.io.ObjectOutputStream
(1).FileInputStream
package javaCoreTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* java.io.FileInputStream
* 1.文件字节输入流,万能的,任何类型的文件都可以采用这个流来读。
* 2.字节的方式,完成输入的操作,完成读的操作(硬盘-->内存)
*/
public class FileInputStreamTest01 {
public static void main(String [] args) {
FileInputStream fis = null;
try {
//创建文件字节输入流对象
//文件路径:D:\Java核心技术\java核心技术\src\javaCoreTest\Wim(IDE会自动把\变成\\,因为java中\表示转义)
//以下都是采用了绝对路径的方式。
FileInputStream fis1 = new FileInputStream("D:\\Java核心技术\\java核心技术\\src\\javaCoreTest\\Wim.txt");
//写成/也是可以的
//fis = new FileInputStream("D:/Java核心技术/java核心技术\\src/javaCoreTest/Wim.txt");
//开始读
int readData = fis1.read();//这个方法返回值是:读取到的“字节”本身
System.out.println(readData);//97
readData = fis1.read();
System.out.println(readData);//98
readData = fis1.read();
System.out.println(readData);//99
readData = fis1.read();
System.out.println(readData);//100
readData = fis1.read();
System.out.println(readData);//101
readData = fis1.read();
System.out.println(readData);//102
//已经读到文件的末尾,再读的时候读取不到任何数据,返回-1
readData = fis1.read();
System.out.println(readData);//-1
readData = fis1.read();
System.out.println(readData);//-1
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//在finally语句块中确保流一定关闭
if(fis != null) {
//关闭流的前提是:流不是空,流是null的时候没必要关闭。
try {
fis.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
}
package javaCoreTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* 对第一个程序进行改进。循环方式
*
* 缺点:
* 一次只能读取一个字节,内存和硬盘之间交互频繁
*/
public class FileInputStreamTest02 {
public static void main(String [] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("D:/Java核心技术/java核心技术\\src/javaCoreTest/Wim.txt");
/*while(true) {
int readData = fis.read();
if(readData == -1) {
break;
}
System.out.println(readData);
}*/
//改造while循环
int readData = 0;
while((readData = fis.read()) != -1 ) {
System.out.println(readData);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
package javaCoreTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* int read(byte [] b) 这个方法返回的是读取到的字节数量(不是字节本身)
* 一次最多读取b.length个字节
* 减少硬盘和内存的交互,提高程序的执行效率
* 往byte[]数组当中读
*/
public class FileInputStreamTest03 {
public static void main(String [] args) {
FileInputStream fis = null;
try {
//相对路径:从当前所在的位置作为起点开始找(不用加文件后缀)
//IDE默认的当前路径是:工程的根(与src同一地位)
//fis = new FileInputStream("D:/Java核心技术/java核心技术\\src/javaCoreTest/Wim.txt");
fis = new FileInputStream("tsv");//tsv为一个文件,里面的内容为abcdef
//开始读,采用byte数组,一次读取多个字节,最多读取“数组.length"个字节
byte[] bytes = new byte[4];
int readCount = fis.read(bytes);//第一次读到了四个字节
System.out.println(readCount);//4
//将字节数组全部转换成字符串
//System.out.println(new String(bytes));//abcd
//但是不应该全部转换,应该是取了多少个字节就转换多少个
System.out.println(new String(bytes, 0, readCount));//abcd
readCount = fis.read(bytes);//第二次只能读取到两个字节
System.out.println(readCount);//2
System.out.println(new String(bytes, 0, readCount));//ef
readCount = fis.read(bytes);//一个字节都没有读取到返回-1
System.out.println(readCount);//-1
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
package javaCoreTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* 继续改进以上程序
*/
public class FileInputStreamTest04 {
public static void main(String [] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("tsv");//tsv为一个文件,里面的内容为abcdef
//准备一个byte数组
byte[] bytes = new byte[4];
/*while(true) {
int readCount = fis.read(bytes);
if(readCount == -1) {
break;
}
System.out.print(new String(bytes, 0, readCount));
}*/
//循环改进版
int readCount = 0;
while((readCount = fis.read(bytes)) != -1) {
System.out.print(new String(bytes, 0, readCount));
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
package javaCoreTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* FileInputStream类的其他常用方法:
* int available():返回流当中剩余的没有读到的字节数量
* long skip(long n):跳过几个字节不读。
*/
public class FileInputStreamTest05 {
public static void main(String [] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("tsv");//tsv为一个文件,里面的内容为abcdef
//1、int available():返回流当中剩余的没有读到的字节数量
/*int readCount = fis.read();
//读出还剩下的字节数量
System.out.println("剩下多少个字节没有读:" + fis.available());*/
//byte [] bytes = new byte[fis.available()];//这种读的方式不适合太大的文件,因为byte数组不能太大
//int readCount = fis.read(bytes);
//System.out.println(new String(bytes));
//2、long skip(long n):跳过几个字节不读。
fis.skip(3);
System.out.println(fis.read());//100
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
(2)、FileOutputStream
package javaCoreTest;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 写
* 从内存 --> 硬盘
*/
public class FileOutputStreamTest01 {
public static void main(String [] args) {
FileOutputStream fos = null;
try {
//这种方法谨慎使用!因为他会先将源文件清空然后重新写入
//可以以追加的方式在文件末尾写入,不会清空原文件内容
//当文件不存在的时候回自动新建
//fos = new FileOutputStream("tsv");
fos = new FileOutputStream("tsv", true);
//开始写
byte [] bytes = {97, 98, 99};
//将byte数组全部写出
fos.write(bytes);
//将数组的一部分写出
fos.write(bytes, 0, 2);
//字符串
String s = "I am a Chinese.";
//将一个字符串转换成一个byte数组
byte[] by = s.getBytes();
//写入
fos.write(by);
//写完之后一定要刷新
fos.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
(3)、FileReader
package javaCoreTest;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*
* FileReader:
* 文件字符输入流,只能读取普通文本
* 读取文本内容时,比较方便快捷。
*/
public class FileReaderTest01 {
public static void main(String [] args) {
FileReader reader = null;
try {
//创建文件字符输入流
reader = new FileReader("tsv");
//开始读
char [] chars = new char[4];
int readCount = 0;
while((readCount = reader.read(chars)) != -1) {
System.out.print(new String(chars, 0, readCount));
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(reader != null) {
try {
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
(4)、FileWriter
package javaCoreTest;
import java.io.FileWriter;
import java.io.IOException;
/*
* FileWriter:
* 文件字符输出流,写
* 只能输出普通文本
*/
public class FileWriterTest01 {
public static void main(String [] args) {
FileWriter out = null;
try {
//这种会使文件先清空,然后重写
//out = new FileWriter("tsv");
//这种写法不会是文件清空
out = new FileWriter("tsv", true);
char[] chars = {'l', 'o', 'v', 'e'};
out.write(chars);
//换行
out.write("\n");
out.write(chars, 0, 2);
//刷新
out.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(out != null) {
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
(5)、BufferedReader
package javaCoreTest;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*
* BufferedReader:
* 带有缓冲区的字符输入流
* 使用这个流的时候不需要自定义char 数组,或者说不需要自定义byte数组,自带缓冲
*/
public class BufferedReaderTest01 {
public static void main(String [] args) throws IOException {
FileReader reader = new FileReader("tsv");
//当一个构造方法中需要一个流的时候,这个被传进来的流叫做:节点流。
//外部负责包装的这个流叫做:包装流,还有一个名字叫做:处理流。
//像当前这个程序来说:FileReader就是一个节点流,BufferedReader就是处理流/包装流
BufferedReader br = new BufferedReader(reader);
//readLine() 读一行
//读取一个文本行,但不带换行符
/*String line1 = br.readLine();
System.out.println(line1);
String line2 = br.readLine();
System.out.println(line2);*/
String s = null;
while((s = br.readLine()) != null) {
System.out.println(s);
}
//关闭流
//对于包装流来说,只需要关闭最外层流就行,里面的节点流会自动关闭(看源代码可以得出)
br.close();
}
}
package javaCoreTest;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
/*
* 字节流转换为字符流
*/
public class BufferedReaderTest02 {
public static void main(String [] args) throws IOException {
/*//字节流
FileInputStream in = new FileInputStream("tsv");
//通过转换流转换【InputStreamReader将字节流转换成字符流】
//在此处in是节点流,reader是包装流
InputStreamReader reader = new InputStreamReader(in);
//这个构造方法只能传一个字符流,不能传字节流
//reader是节点流,br是包装流
BufferedReader br = new BufferedReader(reader);*/
//合并
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("tsv")));
String s = null;
while((s = br.readLine()) != null) {
System.out.println(s);
}
}
}
(6)、BufferedWriter
package javaCoreTest;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
/*
* BufferedWriter:带有缓冲的字符输出流
*/
public class BufferedWriterTest01 {
public static void main(String [] args) throws IOException {
//带有缓冲区的字符输出流
//BufferedWriter out = new BufferedWriter(new FileWriter("tsv"));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("tsv", true)));
//开始写
out.write("hello");
out.write("\n");
out.write("money");
//刷新
out.flush();
//关闭最外层
out.close();
}
}
(7)、DataOutputStream
package javaCoreTest;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* java.io.DataOutputStream:数据专属的流
* 这个流可以将数据连同数据的类型一并写入文件。
* 注意:这个文件不是普通文本文档。(这个文件用记事本打不开)
*/
public class DataOutputStreamTest01 {
public static void main(String [] args) {
//创建数据专属的字节输出流
DataOutputStream data = null;
try {
data = new DataOutputStream(new FileOutputStream("tsv"));
//写数据
byte b = 100;
short s = 12;
int i = 13;
long l = 78L;
float f = 3.14f;
double d = 6.28;
boolean bb = true;
char c = 'a';
//写入
data.writeByte(b);//把数据以及数据的类型一并写入文件中
data.writeShort(s);
data.writeInt(i);
data.writeLong(l);
data.writeFloat(f);
data.writeDouble(d);
data.writeBoolean(bb);
data.writeChar(c);
//刷新
data.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(data != null) {
try {
data.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
(8)、DataInputStream
package javaCoreTest;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* DataInputStream:数据字节输入流
* DataOutputStream写的文件,只能使用DataInputStream去读。并且读的时候需要提前知道写入的顺序,
* 读的顺序需要和写的顺序一致,才可以正常取出数据。
*/
public class DataInputStreamTest01 {
public static void main(String [] args) {
DataInputStream data = null;
try {
data = new DataInputStream(new FileInputStream("tsv"));
//开始读
byte b = data.readByte();
short s = data.readShort();
int i = data.readInt();
long l = data.readLong();
float f = data.readFloat();
double d = data.readDouble();
boolean bb = data.readBoolean();
char c = data.readChar();
System.out.println(b);
System.out.println(s);
System.out.println(i);
System.out.println(l);
System.out.println(f);
System.out.println(d);
System.out.println(bb);
System.out.println(c);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(data != null) {
try {
data.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
(9)、PrintStream
package javaCoreTest;
import java.io.FileNotFoundException;
import java.io.PrintStream;
/*
* java.io.PrintStream:标准的字节输出流。默认输出到控制台。
*/
public class PrintStreamTest01 {
public static void main(String [] args) throws FileNotFoundException {
//联合起来写
System.out.println("hello world");
//分开写
PrintStream ps = System.out;
ps.println("hello zhangsan");
ps.println("hello lisi");
ps.println("hello wangwu");
//标准输出流不需要手动close()关闭
//标准输出流不再指向控制台,指向tsv文件
PrintStream print = new PrintStream("tsv");
//修改输出方向,将输出方向修改到tsv文件
System.setOut(print);
//再输出
System.out.println("hello world");
System.out.println("hello king");
System.out.println("hello wangtiechui");
}
}
6.java.io.File类
常用方法
package javaCoreTest;
import java.io.File;
import java.io.IOException;
/*
* File
* 1、File类和四大家族没有关系,所以File类不能完成文件的读和写
* 2、File对象代表什么?
* 文件和目录路径名的抽象表示形式
* 一个File对象有可能对应的是目录,也有可能是文件。
* 3、需要掌握File类中常用的方法
*/
public class FileTest01 {
public static void main(String [] args) {
//创建一个File对象
File f1 = new File("E:\\file");
//1、boolean exists();判断文件是否存在
System.out.println(f1.exists());//false
//如果不存在,则以文件的形式创建出来
/*if(!f1.exists()) {
//2、createNewFile() 以文件的形式新建
try {
f1.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
//如果不存在,以目录的形式创建出来
/*if(!f1.exists()) {
//3、mkdir() 以目录的形式新建
f1.mkdir();
}*/
//创建多重目录
File f2 = new File("E:\\file\\a\\ba\\c\\d");
if(!f2.exists()) {
//4、mkdirs() 创建多重目录
f2.mkdirs();
}
File f3 = new File("E:\\计算机组成原理\\file");
//5、String getParent() 获取文件的父路径,返回类型为String
String parentPath = f3.getParent();
System.out.println(parentPath);//E:\计算机组成原理
//6、File getParentFile() 获取文件的父路径,返回类型为File
File parentFile = f3.getParentFile();
System.out.println(parentFile);
//7、File getAbsoluteFile() 获取文件的绝对路径
File f4 = new File("tsv");
File abso = f4.getAbsoluteFile();
System.out.println(abso);
//8、String getAbsolutePath() 获取文件的绝对路径
String s = f4.getAbsolutePath();
System.out.println(s);
}
}
package javaCoreTest;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* File类的常用方法
*/
public class FileTest02 {
public static void main(String [] args) {
File f1 = new File("E:\\计算机组成原理\\file");
//1、String getName() 获取文件名
System.out.println(f1.getName());//file
//2、boolean isDirectory() 判断是否是一个目录
System.out.println(f1.isDirectory());//false
//3、boolean isFile() 判断是否是一个文件
System.out.println(f1.isFile());//false
//4、long lastModified() 获取文件最后一次修改时间
long haoMiao = f1.lastModified();//这个毫秒是从1970年到现在的总毫秒数
//将总毫秒数转换成日期
Date time = new Date(haoMiao);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss SSS");
String s = sdf.format(time);
System.out.println(s);
//5、long length() 获取文件大小
System.out.println(f1.length());
//6、File[] listFiles() 获取当前目录下所有的子文件
File f = new File("E:\\计算机组成原理");
File [] files = f.listFiles();
for(File file : files) {
System.out.println(file.getAbsolutePath());
}
}
}
7.序列化 反序列化
(1)和(2)的例1和例2读写相互对应
(1)、序列化【ObjectOutputStream】
package javaCoreTest;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/*
* ObjectOutputStream:
*
* 1、参与序列化和反序列化的对象,必须实现Serializable接口
*
* 2、注意:通过源代码发现,Serializable接口只是一个标志接口:
* public interface Serializable{
* }
* 这个接口当中什么代码都没有。
* 那么它起到一个什么作用?
* 起到标识的作用,标志的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇。
* Serializable这个标志接口是给java虚拟机参考的,java虚拟机看到这个接口之后,会为该类生成一个序列化版本号。
*
* 3、若源代码改动后,重新编译之后生成了全新的字节码文件,并且class文件再次运行的时候,java虚拟机生成的序列化版本号也会发生相应的改变
*
* 4、序列化版本号有什么用?
* java中采用什么机制来区分类的?
* 第一:首先通过类名进行比对,如果类名不一样,肯定不是同一个类
* 第二:如果类名一样,靠序列化版本号进行区分。
*
* 5、这种自动生成的序列化版本号有什么缺点?
* 一旦代码确定后,不能进行后续的修改,因为只要修改,必然会重新编译,
* 此时会生成全新的序列化版本号,这个时候java虚拟机会认为这是一个全新的类。
*
*/
public class ObjectOutputStreamTest01 {
public static void main(String [] args) {
//序列化
ObjectOutputStream oos = null;
try {
//创建java对象
Student01 s = new Student01(111, "zhangsan");
oos = new ObjectOutputStream(new FileOutputStream("tsv"));
//序列化对象
oos.writeObject(s);
//刷新
oos.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(oos!= null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
class Student01 implements Serializable{
//java虚拟机看到Serializable接口之后,会自动生成一个序列化版本号。
//这里没有手动写出来,java虚拟机会默认提供这个序列化版本号。
//建议将序列化版本号手动的写出来,不建议自动生成。
private static final long serialVersionUID = 8683452581122892189L;
int no;
String name;
public Student01() {
super();
// TODO Auto-generated constructor stub
}
public Student01(int no, String name) {
super();
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "Student01 [no=" + no + ", name=" + name + "]";
}
}
package javaCoreTest;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/*
* 一次可以序列化多个对象,可以将对象放到集合当中,序列化集合
* 提示:
* 参与序列化的ArrayList集合以及集合中的元素User都需要实现java.io.Serializable接口
*/
public class ObjectOutputStreamTest02 {
public static void main(String [] args) throws FileNotFoundException, Exception {
List<UserPerson> userList = new ArrayList<>();
userList.add(new UserPerson(2, "lidi"));
userList.add(new UserPerson(3, "wangwu"));
userList.add(new UserPerson(4, "zhaoliu"));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("tsv"));
oos.writeObject(userList);
oos.flush();
oos.close();
}
}
class UserPerson implements Serializable{
int no;
//transient关键字表示游离,不参与序列化
transient String name;//name不参与序列化操作!
public UserPerson(int no, String name) {
this.no = no;
this.name = name;
}
public UserPerson() {
}
public String toString() {
return "User [no=" + no + ", name=" + name + "]";
}
}
(2)、反序列化【ObjectInputStream】
package javaCoreTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
/*
* 反序列化
*/
public class ObjectInputStreamTest01 {
public static void main(String [] args) {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("tsv"));
//开始反序列化,读
System.out.println(ois.readObject());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(ois != null) {
try {
ois.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
package javaCoreTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.List;
/*
* 反序列化集合
*/
public class ObjectInputStreamTest02 {
public static void main(String [] args) {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("tsv"));
Object obj = ois.readObject();
//System.out.println(obj instanceof List);
List<UserPerson> uList = (List<UserPerson>)ois.readObject();
for(UserPerson user : uList) {
System.out.println(user);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
ois.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
8、IO和Properties联合使用
IO流:文件的读和写
Properties:是一个Map集合,key和value都是String类型
package javaCoreTest;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Properties;
/*
* IO + Properties的联合使用
* 设计理念:
* 以后经常改变的数据,可以单独写到一个文件中,使用程序动态读取。
* 将来只需要修改这个文件的内容,java代码不需要改动,不需要重新
* 编译,服务器也不需要重启,就可以拿到动态的信息。
*
* 类似于以上机制的这种文件被称为配置文件。
* 并且当配置文件中的内容格式是:
* key1 = value
* key2 = value
* 的时候,把这种配置文件叫做属性配置文件。
*
* 属性配置文件中key重复的话,value会自动覆盖
*
* java规范中有要求:属性配置文件建议以.properties结尾,但这不是必须的
*/
public class IoPropertiesTest01 {
public static void main(String [] args) throws Exception {
/*
* Properties是一个Map集合,key和value都是String类型
* 想将userinfo文件中的数据加载到Properties对象当中
*/
//新建一个输入流对象
FileReader reader = new FileReader("src/javaCoreTest/userinfo.properties");
//新建一个Map集合
Properties pro = new Properties();
//调用Properties对象的load方法将文件中的数据加载到Map集合中
pro.load(reader);//文件中的数据顺着管道加载到Map集合中,其中等号左边是key,右边是value
//通过key来获取value
String username = pro.getProperty("username");
System.out.println(username);
String password = pro.getProperty("password");
System.out.println(password);
}
}
9.文件拷贝
(1)、使用FileInputStream + FileOutputStream完成文件的拷贝
package javaCoreTest;
import java.io.*;
/*
* 文件复制:
* 使用FileInputStream + FileOutputStream完成文件的拷贝
* 拷贝的过程应该是一边读,一边写。
* 使用以上字节流拷贝文件的时候,文件类型随意,什么样的文件都能拷贝。
*/
public class CopyTest01 {
public static void main(String [] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//创建一个输入流对象
fis = new FileInputStream("tsv");
//创建一个输出流对象
fos = new FileOutputStream("D:\\搜狗高速下载\\zzbm_sqb_06191830\\sunqi\\新建文本文档.txt");
//最核心:一边读,一边写
byte[] bytes = new byte[1024 * 1024];
int readCount = 0;
while((readCount = fis.read(bytes)) != -1) {
fos.write(bytes, 0, readCount);
}
//刷新
fos.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if( fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
(2)、使用FileReader + FileWriter进行拷贝
package javaCoreTest;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 使用FileReader + FileWriter进行拷贝,只能拷贝普通文件
*/
public class CopyTest02 {
public static void main(String [] args) {
FileReader in = null;
FileWriter out = null;
try {
//读
in = new FileReader("tsv");
//写
out = new FileWriter("D:\\Java核心技术\\java核心技术\\课堂笔记(test).txt");
char[] chars = new char[1024 * 512];
int readerCount = 0;
while((readerCount = in.read(chars)) != -1) {
out.write(chars, 0, readerCount);
}
//刷新
out.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(in != null) {
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(out != null) {
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
10.记录日志
package javaCoreTest;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* 记录日志的方法
*/
public class Logger {
public static void log(String msg) {
try {
//指向一个日志文件
PrintStream ps = new PrintStream(new FileOutputStream("tsv", true));
//改变输出方向
System.setOut(ps);
//日期当前时间
Date nowTime = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss SSS");
String strTime = sdf.format(nowTime);
System.out.println(strTime + ":" + msg);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class LogTest {
public static void main(String [] args) {
Logger.log("用户尝试进行登录,验证失败!");
Logger.log("调用了UserService的doSome方法");
}
}
11、文件路径
package javaCoreTest;
/*
* 关于文件路径
* 怎么获取一个文件的绝对路径,以下的这种方式是通用的,但前提是:文件需要在类路径下,才能用这种方式
*/
public class AboutPath {
public static void main(String [] args) {
//使用以下方式的前提是:这个文件必须在类路径下
//什么是类路径下?
//在src下的都是类路径下
//src是类的根路径
/*
*解释:
* Thread.currentThread()当前线程对象
* getContextClassLoader()是线程对象的方法,可以获取到当前线程的类加载对象
* getResource()【获取资源】这是类加载器对象的方法,当前线程的类加载器默认从类的根路径下加载资源。
*/
String pathString = Thread.currentThread().getContextClassLoader()
.getResource("txt").getPath();
//采用以上的代码可以拿到一个文件的绝对路径
System.out.println(pathString);
//从scr目录的下一个开始写,要带文件后缀(从类的根路径下作为起点开始)
String pathString2 = Thread.currentThread().getContextClassLoader()
.getResource("javaCoreTest/Wim.txt").getPath();
System.out.println(pathString2);
}
}
package javaCoreTest;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStream;
import java.util.Properties;
public class IoPropertiesTest {
public static void main(String [] args) throws Exception {
//获取一个文件的绝对路径
/*
* String pathString = Thread.currentThread().getContextClassLoader()
* .getResource("txt.txt").getPath();
*
* FileReader reader = new FileReader(pathString);
*/
//直接以流的形式返回
InputStream reader = Thread.currentThread()
.getContextClassLoader().getResourceAsStream("txt.txt");
Properties properties = new Properties();
properties.load(reader);
reader.close();
//通过key获取value
String classNameString = properties.getProperty("className");
System.out.println(classNameString);
}
}
package javaCoreTest;
import java.util.ResourceBundle;
//资源绑定器
/*
* java.util包下提供了一个资源绑定器,便于获取属性配置文件中的内容。
* 使用以下这种方法的时候,属性配置文件xxx.properties必须放到类路径下
*/
public class ResourceBundleTest {
public static void main(String [] args) {
//资源绑定器,只能绑定xxx.properties文件,并且这个文件必须在类路径下,文件扩展名也必须是properties
//并且在写路径的时候,路径后面的扩展名不能写
ResourceBundle bundle = ResourceBundle.getBundle("classinfo2");
ResourceBundle bundle2 = ResourceBundle.getBundle("javaCoreTest/userinfo");
String classNameString2 = bundle.getString("password");
System.out.println(classNameString2);
String classNameString = bundle.getString("classname");
System.out.println(classNameString);
}
}