Java学习之IO流
IO流
|--字节流
|--字节输入流
InputStream
int read():一次读取一个字节
int read(byte[] bys):一次读取一个字节数组
|--FileInputStream
|--BufferedInputStream
|--字节输出流
OutputStream
void write(int by):一次写一个字节
void write(byte[] bys,int index,int len):一次写一个字节数组的一部分
|--FileOutputStream
|--BufferedOutputStream
|--字符流
|--字符输入流
Reader
int read():一次读取一个字符
int read(char[] chs):一次读取一个字符数组
|--InputStreamReader
|--FileReader
|--BufferedReader
String readLine():一次读取一个字符串
|--字符输出流
Writer
void write(int ch):一次写一个字符
void write(char[] chs,int index,int len):一次写一个字符数组的一部分
|--OutputStreamWriter
|--FileWriter
|--BufferedWriter
void newLine():写一个换行符
void write(String line):一次写一个字符串
File类
我们要想实现IO的操作,就必须知道硬盘上文件的表现形式。而Java就提供了一个类File供我们使用。
构造方法
- File(String pathname):根据一个路径得到File对象
- File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
- File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象
public class FileDemo {
public static void main(String[] args) {
// File(String pathname):根据一个路径得到File对象
// 把e:\\demo\\a.txt封装成一个File对象
File file = new File("E:\\demo\\a.txt");
// File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
File file2 = new File("E:\\demo", "a.txt");
// File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象
File file3 = new File("e:\\demo");
File file4 = new File(file3, "a.txt");
// 以上三种方式其实效果一样
}
}
功能
创建功能:
- public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
- public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
- public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来
File file = new File("D:\\file");
System.out.println("mkdir "+file.mkdir());
File file1 = new File(file,"a.txt");
System.out.println("creat: "+file1.createNewFile());
删除功能
- public boolean delete()
重命名
如果路径名相同,就是改名。
如果路径名不同,就是改名并剪切。
- public boolean renameTo(File dest)
判断功能
- public boolean isDirectory():判断是否是目录
- public boolean isFile():判断是否是文件
- public boolean exists():判断是否存在
- public boolean canRead():判断是否可读
- public boolean canWrite():判断是否可写
- public boolean isHidden():判断是否隐藏
获取功能
- public String getAbsolutePath():获取绝对路径
- public String getPath():获取相对路径
- public String getName():获取名称
- public long length():获取长度。字节数
- public long lastModified():获取最后一次的修改时间,毫秒值
- public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
- public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组
文件名称过滤
要想实现这个效果,就必须学习一个接口:文件名称过滤器
- public String[] list(FilenameFilter filter)
- public File[] listFiles(FilenameFilter filter)
public class FileDemo2 {
public static void main(String[] args) {
// 封装e判断目录
File file = new File("e:\\");
// 获取该目录下所有文件或者文件夹的String数组
// public String[] list(FilenameFilter filter)
String[] strArray = file.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isFile() && name.endsWith(".jpg");
}
});
// 遍历
for (String s : strArray) {
System.out.println(s);
}
}
}
IO流的分类
流向:
输入流 读取数据
输出流 写出数据
数据类型:
字节流
字节输入流 读取数据 InputStream
字节输出流 写出数据 OutputStream
字符流
字符输入流 读取数据 Reader
字符输出流 写出数据 Writer
字节流
输出流
OutputStream具体类为FileOutputStream类
操作步骤
- 创建字节输出流对象
- 写数据
- 释放资源
构造方法
- FileOutputStream(File file)
- FileOutputStream(String name)
输出方法
- public void write(int b):写一个字节
- public void write(byte[] b):写一个字节数组
- public void write(byte[] b,int off,int len):写一个字节数组的一部分
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
// 创建字节输出流对象
// FileOutputStream(File file)
// File file = new File("fos.txt");
// FileOutputStream fos = new FileOutputStream(file);
// FileOutputStream(String name)
FileOutputStream fos = new FileOutputStream("fos.txt");
/*
* 创建字节输出流对象了做了几件事情:
* A:调用系统功能去创建文件
* B:创建fos对象
* C:把fos对象指向这个文件
*/
//写数据
fos.write("hello,IO".getBytes());
fos.write("java".getBytes());
//释放资源
//关闭此文件输出流并释放与此流有关的所有系统资源。
fos.close();
/*
* 为什么一定要close()呢?
* A:让流对象变成垃圾,这样就可以被垃圾回收器回收了
* B:通知系统去释放跟该文件相关的资源
*/
//java.io.IOException: Stream Closed
//fos.write("java".getBytes());
}
}
输入流
InputStream具体类为FileInputStream类
操作步骤
- A:创建字节输入流对象
- B:调用read()方法读取数据,并把数据显示在控制台
- C:释放资源
输入方法
-
int read():一次读取一个字节 (汉字乱码)
public class FileInputDemo { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("xin.txt"); int by = 0; while ((by = fis.read())!=-1){ System.out.print((char)by); } fis.close(); } }
-
int read(byte[] b):一次读取一个字节数组 (汉字正常)
public class FileInputDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("xin.txt");
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));
}
// 释放资源
fis.close();
}
}
复制文件
数据源:从哪里来
a.txt – 读取数据 – FileInputStream
目的地:到哪里去
b.txt – 写数据 – FileOutputStream
//一个字节一个字节
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
// 封装数据源
FileInputStream fis = new FileInputStream("a.txt");
// 封装目的地
FileOutputStream fos = new FileOutputStream("b.txt");
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}
// 释放资源(先关谁都行)
fos.close();
fis.close();
}
}
//字节数组
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
// 封装数据源
FileInputStream fis = new FileInputStream("c:\\a.txt");
FileOutputStream fos = new FileOutputStream("d:\\b.txt");
// 复制数据
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
// 释放资源
fos.close();
fis.close();
}
}
缓冲区类
通过定义数组的方式确实比以前一次读取一个字节的方式快很多,所以,看来有一个缓冲区还是非常好的。
既然是这样的话,那么,java开始在设计的时候,它也考虑到了这个问题,就专门提供了带缓冲区的字节类。
这种类被称为:缓冲区类(高效类)
写数据:BufferedOutputStream
读数据:BufferedInputStream
构造方法可以指定缓冲区的大小,但是我们一般用不上,因为默认缓冲区大小就足够了。
为什么不传递一个具体的文件或者文件路径,而是传递一个OutputStream对象呢?
原因很简单,字节缓冲区流仅仅提供缓冲区,为高效而设计的。但是真正的读写操作还得靠基本的流对象实现。
public class BufferedOutputStreamDemo {
public static void main(String[] args) throws IOException {
// 简单写法
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("bos.txt"));
// 写数据
bos.write("hello".getBytes());
// 释放资源
bos.close();
}
}
public class BufferedInputStreamDemo {
public static void main(String[] args) throws IOException {
// BufferedInputStream(InputStream in)
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
"bos.txt"));
// 读取数据
// int by = 0;
// while ((by = bis.read()) != -1) {
// System.out.print((char) by);
// }
// System.out.println("---------");
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));
}
// 释放资源
bis.close();
}
}
字符流
简介
- 字节流操作中文数据不是特别的方便,所以就出现了转换流。
转换流的作用就是把字节流转换字符流来使用。 - 转换流其实是一个字符流
字符流 = 字节流 + 编码表 - 编码表
就是由字符和对应的数值组成的一张表
常见的编码表
ASCII
ISO-8859-1
GB2312
GBK
GB18030
UTF-8
字符串中的编码问题
编码
String – byte[]
解码
byte[] – String
//之前使用字节流可能会出现的问题
public class FileTnputStreamDemo {
public static void main(String[] args) throws IOException {
// 创建字节输入流对象
FileInputStream fis = new FileInputStream("a.txt");
//读取数据,此处不能打印出中文来,因为中文占两个字节,会出现乱码
int by = 0;
while ((by = fis.read()) != -1) {
System.out.print((char) by);
}
// byte[] bys = new byte[1024];
// int len = 0;
// while ((len = fis.read(bys)) != -1) {
// System.out.print(new String(bys, 0, len));
// }
// 释放资源
fis.close();
}
}
分类
Reader
|--InputStreamReader
|--FileReader
|--BufferedReader
Writer
|--OutputStreamWriter
|--FileWriter
|--BufferedWriter
编码问题
编码解码的格式要一致,我们才能看懂
-
编码:把看得懂的变成看不懂的
String – byte[]
-
解码:把看不懂的变成看得懂的
byte[] – String
方法
- String(byte[] bytes, String charsetName):通过指定的字符集解码字节数组
- byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组
输出流
构造方法
- OutputStreamWriter(OutputStream out):根据默认编码把字节流的数据转换为字符流
- OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
// 创建对象
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
// "osw.txt")); // 默认GBK
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
// "osw.txt"), "GBK"); // 指定GBK
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"osw.txt"), "UTF-8"); // 指定UTF-8
// 写数据
osw.write("中国");
// 释放资源
osw.close();
}
}
常用方法
- public void write(int c):写一个字符
- public void write(char[] cbuf):写一个字符数组
- public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
- public void write(String str):写一个字符串
- public void write(String str,int off,int len):写一个字符串的一部分
close()关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了。
flush()仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
// 创建对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"osw2.txt"));
// 写数据
// public void write(int c):写一个字符
// osw.write('a');
// osw.write(97);
// 为什么数据没有进去呢?
// 原因是:字符 = 2字节
// 文件中数据存储的基本单位是字节。
// void flush()
// public void write(char[] cbuf):写一个字符数组
// char[] chs = {'a','b','c','d','e'};
// osw.write(chs);
// public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
// osw.write(chs,1,3);
// public void write(String str):写一个字符串
// osw.write("我爱林青霞");
// public void write(String str,int off,int len):写一个字符串的一部分
osw.write("我爱林青霞", 2, 3);
// 刷新缓冲区
osw.flush();
// osw.write("我爱林青霞", 2, 3);
// 释放资源
osw.close();
// java.io.IOException: Stream closed
// osw.write("我爱林青霞", 2, 3);
}
}
输入流
构造方法
- InputStreamReader(InputStream is):用默认的编码读取数据
- InputStreamReader(InputStream is,String charsetName):用指定的编码读取数据
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
// 创建对象
// InputStreamReader isr = new InputStreamReader(new FileInputStream(
// "osw.txt"));
// InputStreamReader isr = new InputStreamReader(new FileInputStream(
// "osw.txt"), "GBK");
InputStreamReader isr = new InputStreamReader(new FileInputStream(
"osw.txt"), "UTF-8");
// 读取数据
// 一次读取一个字符
int ch = 0;
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
}
// 释放资源
isr.close();
}
}
常用方法
- int read():一次读取一个字符
- int read(char[] chs):一次读取一个字符数组
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
// 创建对象
InputStreamReader isr = new InputStreamReader(new FileInputStream(
"StringDemo.java"));
// 一次读取一个字符
// int ch = 0;
// while ((ch = isr.read()) != -1) {
// System.out.print((char) ch);
// }
// 一次读取一个字符数组
char[] chs = new char[1024];
int len = 0;
while ((len = isr.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
// 释放资源
isr.close();
}
}
缓冲区类
字符流为了高效读写,也提供了对应的字符缓冲流。
BufferedWriter:字符缓冲输出流
BufferedReader:字符缓冲输入流
BufferedWriter:字符缓冲输出流
- 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
- 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
// BufferedWriter(Writer out)
// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
// new FileOutputStream("bw.txt")));
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
bw.write("hello");
bw.write("world");
bw.write("java");
bw.flush();
bw.close();
}
}
BufferedReader:字符缓冲输入流
BufferedReader(Reader in)
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
// 创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
// 方式1
// int ch = 0;
// while ((ch = br.read()) != -1) {
// System.out.print((char) ch);
// }
// 方式2
char[] chs = new char[1024];
int len = 0;
while ((len = br.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
// 释放资源
br.close();
}
}
特殊用法
BufferedWriter:
public void newLine():根据系统来决定换行符
BufferedReader:
public String readLine():一次读取一行数据
包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
public class BufferedDemo {
public static void main(String[] args) throws IOException {
// write();
read();
}
private static void read() throws IOException {
// 创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("bw2.txt"));
// public String readLine():一次读取一行数据
// String line = br.readLine();
// System.out.println(line);
// line = br.readLine();
// System.out.println(line);
// 最终版代码
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//释放资源
br.close();
}
private static void write() throws IOException {
// 创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("bw2.txt"));
for (int x = 0; x < 10; x++) {
bw.write("hello" + x);
// bw.write("\r\n");
bw.newLine();
bw.flush();
}
bw.close();
}
}
复制文件
采用字符转换流
数据源:
a.txt – 读取数据 – 字符转换流 – InputStreamReader
目的地:
b.txt – 写出数据 – 字符转换流 – OutputStreamWriter
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
// 封装数据源
InputStreamReader isr = new InputStreamReader(new FileInputStream(
"a.txt"));
// 封装目的地
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"b.txt"));
// 读写数据
// 方式1
// int ch = 0;
// while ((ch = isr.read()) != -1) {
// osw.write(ch);
// }
// 方式2
char[] chs = new char[1024];
int len = 0;
while ((len = isr.read(chs)) != -1) {
osw.write(chs, 0, len);
// osw.flush();
}
// 释放资源
osw.close();
isr.close();
}
}
采用封装类FileReader,FileWriter
由于我们常见的操作都是使用本地默认编码,所以,不用指定编码。
而转换流的名称有点长,所以,Java就提供了其子类供我们使用。
OutputStreamWriter = FileOutputStream + 编码表(GBK)
FileWriter = FileOutputStream + 编码表(GBK)
数据源:
a.txt – 读取数据 – 字符转换流 – InputStreamReader – FileReader
目的地:
a.txt – 写出数据 – 字符转换流 – OutputStreamWriter – FileWriter
- 第一种和上面一样
- 第二种是已经封装好的
public class CopyFileDemo3 {
public static void main(String[] args) throws IOException {
// 封装数据源
FileReader fr = new FileReader("c:\\a.txt");
// 封装目的地
FileWriter fw = new FileWriter("d:\\b.txt");
// 读写数据
// int ch = 0;
int ch;
while ((ch = fr.read()) != -1) {
fw.write(ch);
}
//释放资源
fw.close();
fr.close();
}
}
采用缓冲区
数据源:
a.txt – 读取数据 – 字符转换流 – InputStreamReader – FileReader – BufferedReader
目的地:
b.txt – 写出数据 – 字符转换流 – OutputStreamWriter – FileWriter – BufferedWriter
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
// 封装数据源
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 封装目的地
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
// 两种方式其中的一种一次读写一个字符数组
char[] chs = new char[1024];
int len = 0;
while ((len = br.read(chs)) != -1) {
bw.write(chs, 0, len);
bw.flush();
}
// 释放资源
bw.close();
br.close();
}
}
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
// 封装数据源
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 封装目的地
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
// 两种方式其中的一种一次读写一个字符数组
char[] chs = new char[1024];
int len = 0;
while ((len = br.read(chs)) != -1) {
bw.write(chs, 0, len);
bw.flush();
}
// 释放资源
bw.close();
br.close();
}
}
数据操作流
可以操作基本类型的数据
-
数据输入流:DataInputStream
DataInputStream(InputStream in)
-
数据输出流:DataOutputStream
DataOutputStream(OutputStream out)
public class DataStreamDemo {
public static void main(String[] args) throws IOException {
// 写
// write();
// 读
read();
}
private static void read() throws IOException {
// DataInputStream(InputStream in)
// 创建数据输入流对象
DataInputStream dis = new DataInputStream(
new FileInputStream("dos.txt"));
// 读数据
byte b = dis.readByte();
short s = dis.readShort();
int i = dis.readInt();
long l = dis.readLong();
float f = dis.readFloat();
double d = dis.readDouble();
char c = dis.readChar();
boolean bb = dis.readBoolean();
// 释放资源
dis.close();
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(c);
System.out.println(bb);
}
private static void write() throws IOException {
// DataOutputStream(OutputStream out)
// 创建数据输出流对象
DataOutputStream dos = new DataOutputStream(new FileOutputStream(
"dos.txt"));
// 写数据了
dos.writeByte(10);
dos.writeShort(100);
dos.writeInt(1000);
dos.writeLong(10000);
dos.writeFloat(12.34F);
dos.writeDouble(12.56);
dos.writeChar('a');
dos.writeBoolean(true);
// 释放资源
dos.close();
}
}
内存操作流
有些时候我们操作完毕后,未必需要产生一个文件,就可以使用内存操作流。
-
字节数组:
ByteArrayInputStream
ByteArrayOutputStream
-
字符数组:
CharArrayReader
CharArrayWriter
-
字符串:
StringReader
StringWriter
public class ByteArrayStreamDemo { public static void main(String[] args) throws IOException { // 写数据 // ByteArrayOutputStream() ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 写数据 for (int x = 0; x < 10; x++) { baos.write(("hello" + x).getBytes()); } // 释放资源 // 通过查看源码我们知道这里什么都没做,所以根本需要close() // baos.close(); // public byte[] toByteArray() byte[] bys = baos.toByteArray(); // 读数据 // ByteArrayInputStream(byte[] buf) ByteArrayInputStream bais = new ByteArrayInputStream(bys); int by = 0; while ((by = bais.read()) != -1) { System.out.print((char) by); } // bais.close(); } }
打印流
只有写数据的,没有读取数据。只能操作目的地,不能操作数据源。
可以操作任意类型的数据。
如果启动了自动刷新,能够自动刷新。
该流是可以直接操作文本文件的。
public class PrintWriterDemo {
public static void main(String[] args) throws IOException {
// 作为Writer的子类使用
PrintWriter pw = new PrintWriter("pw.txt");
pw.write("hello");
pw.write("world");
pw.write("java");
pw.close();
}
}
自动刷新
PrintWriter pw = new PrintWriter(new FileWriter(“pw2.txt”), true);
还是应该调用println()的方法才可以
-
这个时候不仅仅自动刷新了,还实现了数据的换行。
println()
其实等价于于:
bw.write();
bw.newLine();
bw.flush();
public class PrintWriterDemo2 {
public static void main(String[] args) throws IOException {
// 创建打印流对象
// PrintWriter pw = new PrintWriter("pw2.txt");
PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true);
// write()是搞不定的,怎么办呢?
// 我们就应该看看它的新方法
// pw.print(true);
// pw.print(100);
// pw.print("hello");
pw.println("hello");
pw.println(true);
pw.println(100);
pw.close();
}
}
标准输入输出流
System类中的两个成员变量:
- public static final InputStream in “标准”输入流。
- public static final PrintStream out “标准”输出流。
使用方式
InputStream is = System.in;
PrintStream ps = System.out;
随机访问流
RandomAccessFile类不属于流,是Object类的子类。
但它融合了InputStream和OutputStream的功能。
支持对文件的随机访问读取和写入。
public RandomAccessFile(String name,String mode):第一个参数是文件路径,第二个参数是操作文件的模式。
-
模式有四种,我们最常用的一种叫"rw",这种方式表示我既可以写数据,也可以读取数据
-
可以按照文件指针的位置写数据和读数据,获取和改变文件指针的位置
合并流
把多个输入流的数据写到一个输出流中。
构造方法
- SequenceInputStream(InputStream s1, InputStream s2)
- SequenceInputStream(Enumeration<? extends InputStream> e)
public class SequenceInputStreamDemo2 {
public static void main(String[] args) throws IOException {
// 需求:把下面的三个文件的内容复制到Copy.java中
// ByteArrayStreamDemo.java,CopyFileDemo.java,DataStreamDemo.java
// SequenceInputStream(Enumeration e)
// 通过简单的回顾我们知道了Enumeration是Vector中的一个方法的返回值类型。
// Enumeration<E> elements()
Vector<InputStream> v = new Vector<InputStream>();
InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java");
InputStream s2 = new FileInputStream("CopyFileDemo.java");
InputStream s3 = new FileInputStream("DataStreamDemo.java");
v.add(s1);
v.add(s2);
v.add(s3);
Enumeration<InputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("Copy.java"));
// 如何写读写呢,其实很简单,你就按照以前怎么读写,现在还是怎么读写
byte[] bys = new byte[1024];
int len = 0;
while ((len = sis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
sis.close();
}
}
序列化流
序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。对象 – 流数据(ObjectOutputStream)
反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 – 对象(ObjectInputStream)
public class ObjectStreamDemo {
public static void main(String[] args) throws IOException,
ClassNotFoundException {
// 由于我们要对对象进行序列化,所以我们先自定义一个类
// 序列化数据其实就是把对象写到文本文件
// write();
read();
}
private static void read() throws IOException, ClassNotFoundException {
// 创建反序列化对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
"oos.txt"));
// 还原对象
Object obj = ois.readObject();
// 释放资源
ois.close();
// 输出对象
System.out.println(obj);
}
private static void write() throws IOException {
// 创建序列化流对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
"oos.txt"));
// 创建对象
Person p = new Person("林青霞", 27);
// public final void writeObject(Object obj)
oos.writeObject(p);
// 释放资源
oos.close();
}
}
public class Person implements Serializable {
private static final long serialVersionUID = -2071565876962058344L;
private String name;
// private int age;
private transient int age;
// int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
注意
类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
我们在实际开发中,可能还需要使用以前写过的数据,不能重新写入。原因是因为它们的id值不匹配。每次修改java文件的内容的时候,class文件的id值都会发生改变。所以我们自动生成一个uid就可以了
使用transient关键字声明不需要序列化的成员变量
Properties
Properties:属性集合类。是一个可以和IO流相结合使用的集合类。
- Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
- 是Hashtable的子类,说明是一个Map集合。
特有功能
public Object setProperty(String key,String value) 添加元素
public String getProperty(String key) 获取元素
public Set stringPropertyNames() 获取所有键的集合
public class PropertiesDemo2 {
public static void main(String[] args) {
// 创建集合对象
Properties prop = new Properties();
// 添加元素
prop.setProperty("张三", "30");
prop.setProperty("李四", "40");
prop.setProperty("王五", "50");
// public Set<String> stringPropertyNames():获取所有的键的集合
Set<String> set = prop.stringPropertyNames();
for (String key : set) {
String value = prop.getProperty(key);
System.out.println(key + "---" + value);
}
}
}
和IO流结合的方法
把键值对形式的文本文件内容加载到集合中
public void load(Reader reader)
public void load(InputStream inStream)
把集合中的数据存储到文本文件中
public void store(Writer writer,String comments)
public void store(OutputStream out,String comments)
public class PropertiesDemo3 {
public static void main(String[] args) throws IOException {
// myLoad();
myStore();
}
private static void myStore() throws IOException {
// 创建集合对象
Properties prop = new Properties();
prop.setProperty("林青霞", "27");
prop.setProperty("武鑫", "30");
prop.setProperty("刘晓曲", "18");
//public void store(Writer writer,String comments):把集合中的数据存储到文件
Writer w = new FileWriter("name.txt");
prop.store(w, "helloworld");
w.close();
}
private static void myLoad() throws IOException {
Properties prop = new Properties();
// public void load(Reader reader):把文件中的数据读取到集合中
// 注意:这个文件的数据必须是键值对形式
Reader r = new FileReader("prop.txt");
prop.load(r);
r.close();
System.out.println("prop:" + prop);
}
}
NIO
nio包在JDK4出现,提供了IO流的操作效率。
Path:路径
Paths:通过静态方法返回一个路径 public static Path get(URI uri)
Files:提供了常见的功能
复制文本文件 public static long copy(Path source,OutputStream out):复制文件
把集合中的数据写到文本文件 public static Path write(Path path,Iterable<? extends CharSequence> lines,Charset cs,OpenOption… options)
public class NIODemo {
public static void main(String[] args) throws IOException {
// public static long copy(Path source,OutputStream out)
// Files.copy(Paths.get("ByteArrayStreamDemo.java"), new
// FileOutputStream(
// "Copy.java"));
ArrayList<String> array = new ArrayList<String>();
array.add("hello");
array.add("world");
array.add("java");
Files.write(Paths.get("array.txt"), array, Charset.forName("GBK"));
}
}