目录:
File类
文件和目录路径名的抽象表示形式。一个File对象可以代表一个文件或目录
可以实现获取文件和目录属性等功能
可以实现对文件和目录的创建、删除等功能
File不访问文件内容
流的原理
数据源
data source. 提供原始数据的原始媒介。常见的:数据库、文件、其他程序、内存、网络连接、IO设备。
数据源就像水箱,流就像水管中流着的水流,程序就是我们最终的用户。 流是一个抽象、动态的概念,是一连串连续动态的数据集合。
流的分类:
按照流的方向:
按照处理的数据单元:
按照功能不同:
节点流和处理流的关系
InputStream和OutputStream
Reader和Writer
FileInputStream/FileOutputStream
使用FileInputStream读取文件内容
abstract int read( );
int read( byte b[ ] );
int read( byte b[ ], int off, int len );
int available( );
close( );
使用FileOutputStream写内容到文件
abstract void write( int b );
void write( byte b[ ] );
void write( byte b[ ], int off, int len );
void flush( );
void close( );
缓冲字节流
BufferedInputStream和BufferedOutputStream
缓冲字符流
BufferedReader
BufferedWriter
使用缓冲字符流是复制文本文件常用的方式
String str = br.readLine();
while(str != null){
bw.write(str);
bw.newLine();
str = br.readLine();
}
转换流
InputStreamReader和OutputStreamWriter
只存在将字节流转换为字符流的转换流,不存在将字符流转换为字节流的转换流,因为没必要。
System.in代表标准输入,即键盘输入,是InputStream的实例
Reader reader = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(reader);
System.out.println("请输入用户名:");
String str = br.readLine();
System.out.println(str);
打印流
PrintStream
PrintWriter
字节/字符数组/字符串流
ByteArrayInputStream和ByteArrayOutputStream
CharArrayReader和CharArrayWriter
StringReader和StringWriter
DataInputStream和DataOutputStream
DataInputStream和DataOutputStream
输入流链和输出流链
注意:只要关闭上层流即可
对象序列化
对象序列化 (Serialization)
对象反序列化 (DeSerialization)
为什么序列化 ?
序列化以后的对象可以保存到磁盘上,也可以在网络上传输,使得不同的计算机可以共享对象.(序列化的字节序列是平台无关的)
对象序列化的条件
只有实现了Serializable接口的类的对象才可以被序列化。
Serializable接口中没有任何的方法,实现该接口的类不需要实现额外的方法。
如果对象的属性是对象,属性对应类也必须实现Serializable接口
如何实现序列化
创建ObjectOutputStream对象
调用writeObject()输出对象
OutputStream fos = new FileOutputStream(new File("d:/java6.txt"));
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(stu);
oos.close();
如何实现反序列化
创建ObjectInputStream对象
调用readObject()读取对象
InputStream fis = new FileInputStream(new File("d:/java6.txt"));
ObjectInputStream ois = new ObjectInputStream(fis);
Student stu = (Student)ois.readObject();
System.out.println(stu.getAge()+" "+stu.getScore());
序列化能保存的元素
使用对象流把一个对象写到文件时不仅保证该对象是序列化的,而且该对象的成员对象也必须是可序列化的。
如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,
并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。
同一个对象多次序列化的处理
如果不希望某些属性(敏感)序列化,或不希望出现递归序列
序列化版本不兼容
修改了实例属性后,会影响版本号,从而导致反序列化不成功
解决方案:为Java对象指定序列化版本号serialVersionUID
小结
IO基础
流的原理
对于数据的输入/输出操作以“流” (stream) 方式进行
数据源就像水箱,流就像水管中流着的水流,程序就是我们最终的用户
流的分类
输入流和输出流
字节流和字符流
节点流和处理流(包装流 装饰流)
流的体系
InputStream 字节输入流
OutputStream 字节输出流
Reader 字符输入流
Writer 字符输出流
具体IO介绍
文件流:节点流
FileInputStream和FileOutputStream
FileReader和FileWriter
缓冲流:包装流
BufferedInputStream和BufferedOutputStream
BufferedReader和BufferedWriter
转换流:包装流 字节流转换成字符流 System.in
InputStreamReader和OutputStreamWriter
打印流:包装流 只有输出流 System.out
PrintStream和PrintWriter
数据流:包装流 只有字节流 基本类型和String
DataInputStream和DataOutputStream
对象流:包装流 只有字节流 序列化 对象
ObjectInputStream和ObjectOutputStream
代码示例
1.使用流方式将C:\1\1.jpg复制到c:\2\girl.jpg
/**
* 使用流方式将C:\1\1.jpg复制到c:\2\girl.jpg
* @author Terry
*
*/
public class CopyDemo {
/**
* @param args
*/
public static void main(String[] args) {
String path1 = "c:\\1\\1.jpg";
String path2 = "c:\\2\\girl.jpg";
copyTo(path1, path2);
System.out.println("文件复制结束");
}
/**
* 将原文件复制到目标位置
* @param sourcePath :原文件所在路径
* @param destPath :复制后文件的目标位置
*/
static void copyTo(String sourcePath, String destPath){
//声明流对象
InputStream input = null;
OutputStream output = null;
try {
//创建流对象
//用于读取文件
input = new FileInputStream(sourcePath);
//用来写入文件
output = new FileOutputStream(destPath);
//开始读取文件
//临时缓冲区(将读取到的内容存放到数组b中)
byte[] b = new byte[1024];
//存储每次读取的长度
int len = 0;
int i=0;
while((len = input.read(b)) != -1){
//将刚刚读取到的内容写入到文件中
output.write(b);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
//建议分开使用try-catch语句
//这样可以有效避免上面input.close()方法出现异常造成下面的output.close()无法执行
try {
input.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2.
/**
* 使用InputStream读取文件
* 作用
* InputStream用于以流方式读取文件中内容(源——>程序)
*
* byte[]——>字符串
* 创建
* InputStream 对象名 = new FileInputStream(文件路径);
* InputStream 对象名 = new FileInputStream(File对象);
* 常用方法
* read() :每次读取一个字节 *
* close() :关闭当前流媒体对象
* available() :估计读取内容的剩余字节数
* @author Terry
*
*/
public class InputStreamDemo1 {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
String path = "c:\\1.txt";
//streamRead1(path);
streamRead2(path);
}
/**
* 使用Stream对象读取文件内容
* 使用byte数组作为缓存一次性读取多个字符内容(可以有效地提高读取的效率)
*
* 基本可以解决中文乱码问题
* @param path
* @throws IOException
*/
static void streamRead2(String path) throws IOException{
//创建Stream对象
InputStream stream = new FileInputStream(path);
//读取内容
//作为临时缓存存储流内容
byte[] b = new byte[24];
//一次性读取8个字节
//读取一次
//int len = stream.read(b);
//System.out.println(new String(b));
//使用循环的方式进行读取
int index = 0;
int len;
while((len = stream.read(b)) != -1){
System.out.println(new String(b));
System.out.println("读取次数:"+ (++index));
}
//关闭Strema对象
stream.close();
}
/**
* 每次读取一个字符
* 缺点:
* 1、无法正确读取中文内容
* 2、每次读取一个字节效率较低
* @param path
*/
static void streamRead1(String path){
InputStream stream = null;
try {
/*
//创建了FileInputStream对象并直接传递文件路径
InputStream stream = new FileInputStream(path);
//创建FileInputStream并传递一个File对象
//创建File对象(目的是为了给FileInputstream最为参数)
File file = new File(path);
//创建对象并将file对象最为参数进行使用
InputStream stream = new FileInputStream(file);
*/
//创建FileInputStream对象并以File类型对象为参数(合并了上面的1~2两步)
stream= new FileInputStream(new File(path));
/*
//读取一个字符内容
int content = stream.read();
//读取过程中,如果未读取到任何内容则返回-1
while(content !=-1){
//打印字符内容
System.out.print((char)content);
//继续读取下一个内容
content = stream.read();
}
*/
//上面代码的变形
int content = -1;
while((content = stream.read()) != -1){
System.out.print((char)content);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
//关闭Stream对象
stream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.
/**
* OutputStream
* 作用
* 以字节的形式将内容输出到物理文件中。输出时可以输出单个字节或数组
*
* 字符串——>byte[]
* 创建对象
* OutputStream 对象名 = new FileOutputStream(路径名 [,模式]);
* OutputStream 对象名 = new FileOutputStream(File对象 [,模式]);
*
* 模式 :布尔类型值。该值指示了文件的输出方式,如果值true则表示追加方式进行输出
* 相反,如果未false则表示覆盖模式进行输出(默认模式)
*
* 常用方法
* write() :将字节内容进行输出
* close() :关闭流对象
* @param args
*/
public static void main(String[] args) {
String path = "c:\\2.txt";
//streamWrite1(path);
//streamWrite2(path);
//streamWrite3(path);
streamWrite4(path);
}
static void streamWrite4(String path) {
//声明一个OutputStream对象
OutputStream stream = null;
//实例化Stream对象
try {
stream = new FileOutputStream(path,true);
//定义待输出字符串内容
String str= "我要下课";
//字符串转为byte[]
byte[] array =str.getBytes();
//输出字符串内容
stream.write(array);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
//关闭流对象
stream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 将一个字符串内容输出到物理文件中
* 将一个byte[]中的内容进行输出(效率高于单字符输出)
*
* @param path
*/
static void streamWrite3(String path){
//声明stream对象
OutputStream stream=null;
try {
//创建stream对象
stream = new FileOutputStream(path);
//定义待输出内容
String str = "Hello Wrold!这里是尚学堂";
//字符串——〉byte[]
byte[] array = str.getBytes();
//直接将byte[]进行输出
stream.write(array);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
//关闭对象
stream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 将一个字符串内容输出到物理文件中
* 每次输出一个字节,输出效率较低
*
* @param path
*/
static void streamWrite2(String path){
//声明一个OutputStream对象
OutputStream stream = null;
try {
//创建OutputStream对象
stream = new FileOutputStream(path);
//定义待输出字符串
String str = "Hello Wrold!这里是尚学堂";
//怎么把一个字符串转为byte数组呢?
//getBytes()方法可以获取一个字符串的byte数组
byte[] array = str.getBytes();
//将数组中的内容进行输出
for(byte b : array){
stream.write(b);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
//关闭输出流对象
stream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 通过OutputStream向物理文件中输出内容
* @param path
*/
static void streamWrite1(String path){
//声明了一个OutputStream对象
OutputStream stream = null;
try {
//创建对象
stream = new FileOutputStream(path);
//通过输出流向物理文件中输出内容
//通过write()方法向文件输出一个字节的内容(100——字符d)
stream.write(100);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
//关闭输出流对象
stream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4.
/**
* @param args
*/
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//提示用户键盘输入内容
System.out.print("请输入日志内容:");
String content = input.nextLine();
//将用户键盘输入的内容写入到文件中
writeToLog(content);
}
static void writeToLog(String content) {
OutputStream stream = null;
//获取文件名
String fileName = "c:" +File.separatorChar+ getFileName();
try {
//设置文件的创建方式
//true表示文件存在则进行追加操作,否则则进行创建新文件
stream = new FileOutputStream(fileName,true);
//将文件内容输出到文件中
stream.write(content.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
//关闭流对象
stream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 生成一个特定格式的文件名
* @return
*/
static String getFileName(){
//生成一个文件名
//log + "_" + 日期
//创建一个Date对象
Date date = new Date();
SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
//返回日期格式的文件名
return "log" + fmt.format(date) + ".log";
}
5.
/**
* FileReader类
* 一个工具类,内部提供了用于以字符方式读取文件内容的方法
*
* 方法
* read() :以字符为单位进行读取,每次读取一个字符
* close() :关闭当前对象
* skip() :跳过指定个个数的字符
*
*
* @author Terry
*
*/
public class FileReaderDemo {
/**
* @param args
*/
public static void main(String[] args) {
String path = "c:\\1.log";
//reader1(path);
//reader2(path);
//reader3(path);
reader4(path);
}
/**
* 以字符方式读取文件内容
* 定义一个与字符个数相符的缓冲区
* @param path
*/
static void reader4(String path){
//声明reader对象
Reader reader = null;
try {
File file = new File(path);
//创建reader对象
reader = new FileReader(file);
//声明了一个与文件字符个数相同的char型数组
//cbuf——char型数组。作为临时的缓冲区
char[] cbuf = new char[(int)file.length()];
reader.read(cbuf);
System.out.println(cbuf);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 读取字符型文本的内容,每次读取一组内容
* @param path
*/
static void reader3(String path) {
//声明reader对象
Reader reader = null;
try {
//创建reader对象
reader = new FileReader(path);
char[] array = new char[10];
/*
//读取了部分数据
int len = reader.read(array);
System.out.println(array);
*/
//将字符内容缓存到数组中
while(reader.read(array) != -1){
System.out.print(array);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 循环遍历,每次读取一个字符
* 缺点:效率低
* 优点:有效的解决了中文读取错误的问题(InputStream)
* @param path
*/
static void reader2(String path){
//声明reader对象
Reader reader = null;
try {
//实例化一个reader对象
reader =new FileReader(path);
int v;
//如果read()的返回结果为-1则表示读取失败
while((v=reader.read())!= -1){
System.out.print((char)v);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 利用Reader读取文件内容中的第一个字符
* @param path
*/
static void reader1(String path){
//声明Reader对象
Reader reader = null;
try {
/*
//以File对象作为参数进行文件读取
File file = new File(path);
reader = new FileReader(file);
*/
//以字符串型的路径作为参数进行对象创建
reader = new FileReader(path);
//读取单个字符(读取一个完整的字符,即使是中文字符也不会出现半个字符的情况)
int v = reader.read();
System.out.println((char)v);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
//关闭reader对象
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
6.
/**
* FileWriter 概述 将字符流写入到文件中
* 方法
* writ()
* flush() :刷新缓冲区
*
* flush
* 以字符方式写文件内容时,writer对象临时将内容存储到了缓冲区中。为了提高效率,只有当
* 调用close()方法时才对内容进行输出。
* flush()方法可以刷新缓冲区,在刷新过程中会强制将内容输出到文件中
*
* 缓冲区
* 缓冲区就是一块内存区域。
*
* @author Terry
*
*/
public class FileWriterDemo {
/**
* @param args
*/
public static void main(String[] args) {
String path = "c:\\1.txt";
// write(path);
//write2(path);
write3(path);
}
/**
* 不关闭对象执行代码
* 如果未关闭对象执行代码则内容不会被输出
* 如果使用了flush之后即使未关闭内容也会被输出
* @param path
*/
static void write3(String path) {
// 声明一个Writer对象
Writer writer = null;
try {
// 创建Writer对象
writer = new FileWriter(path);
String str = "哇哈哈哈哈,终于要放学了";
writer.write(str);
//加上后即使没有使用close()方法内容依旧被输出了
writer.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
}
}
/**
* 直接向文件中写入一个字符串
*
* @param path
*/
static void write2(String path) {
// 声明一个Writer对象
Writer writer = null;
try {
// 创建Writer对象
writer = new FileWriter(path);
String str = "哇哈哈哈哈,终于要放学了";
writer.write(str);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
// 关闭对象
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 向文件中写入一个字符
*
* @param path
*/
static void write(String path) {
// 声明一个Writer对象
Writer writer = null;
try {
// 创建writer对象
writer = new FileWriter(path);
// 写入一个字符
writer.write(65);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
// 关闭reader对象
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}