IO流(超详解)
常见的字符集
ASCII
ASCII(American Standard Code for Information Interchange) :美国信息交换标准代码,包括了英文、符号等。
标准ASCII使用1个字符存储一个字符,首尾为0,总共可表示128个字符,对美国来说是完全够用了
GBK(汉字内码扩展规范,国标)
汉字编码字符集,高寒了2万多个汉字等字符,GBK中一个中文字符编码成两个字节的形式存储
注意:GBK兼容了ASCII字符集,并且规定汉字的第一个字节第一位必须是1
// 例如:我a你
//1xxxxxxx xxxxxxxx 0xxxxxxx 1xxxxxxx xxxxxxxx
Unicode字符集(统一码,也叫万国码)
Unicode是国际组织制定的,可以容纳世界上所有文字、符号的字符集。
UTF-32:
4个字节表示一个字符,可以称为有容乃大,但是就会感觉非常的奢侈,占存储空间,通信效率变低!
//00000006 00000000 00000000 01100001
// 一个简单的字符就需要在前面添加很多的0 ,非常的占空间
UTF-8:
是Unicode字符集的一种编码方案,采取可变长编码方案,共分四个长度区:1个字节,2个字节,3个字节,4个字节。英文字符、数字等只占1个字节(兼容标准ASCII编码),汉字字符占用3个字节。
//OXXXXXxX | xXxXXXXX XXXXXXXX XxXXXXXX | xXXXXXx
//例如:a我m
//01100001 1110xxxx 10xxXxxxx 10xxxxxx 01101101
注意:
- 技术人员在开发时都应该使用UTF-8编码!
- 字符编码时使用的字符集,和解码时使用的字符集必须一致,否则会出现乱码
- 英文,数字一般不会乱码。因为很多字符集都兼容了ASCII编码
总的来说就是:
ASCII字符集: 只有英文、数字、符号等,占1个字节。
GBK字符集: 汉字占2个字节,英文、数字占1个字节。
UTF-8字符集: 汉字占3个字节,英文、数字占1个字节。
字符集的编码、解码操作
编码:把字符按照指定'字符集编码成字节。
解码:'把字节按照指定'字符集解码成‘字符。
java完成对字符的编码:
| String提供了如下方法 | 说明 |
|---|---|
| byte[ ] getBytes() | 使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中 |
| byte[ ] getBytes(String charsetName) | 使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中 |
java代码完成对字符的解码:
| String提供了如下方法 | 说明 |
|---|---|
| string(byte[ ] bytes) | 通过使用平台的默认字符集解码指定的字节数组来构造新的String |
| String(byte[] bytes,String charsetName) | 通过指定的字符集解码指定的字节数组来构造新的 String |
String name="我爱中国b";
byte[] x=name.getBytes("GBK"); //按照指定字符集进行编码
System.out.println(Arrays.toString(x)); //[-50, -46, -80, -82, -42, -48, -71, -6, 98]
//解码
String names=new String(x,"GBK"); //按照GBK格式解码
System.out.println(names); //我爱中国b
IO流
认识IO流
IO,即**input和output,** 也就是输入和输出,指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接。
Java 中是通过流处理IO 的,那么什么是流?
流(Stream),是一个抽象的概念,是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道。
当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。
那么一般用在什么地方呢?一般像文件的写入读取、聊天等等,都会用到IO流
IO流分类
IO流按照流的方向分为:输入流、输入流
IO流按照流中的数据的最小单位分为:字节流、字符流
总结流的四大类:
- 字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流
- 字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流。
- 字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流。
- 字符输出流:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流。
IO流-字节流
FileInputStream(文件字节输入流)
作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。
构造器:
| 构造器 | 说明 |
|---|---|
| public FileInputstream(File file) | 创建字节输入流管道与源文件接通(文件对象) |
| public FileInputStream(String pathname) | 创建字节输入流管道与源文件接通(字符串文件路径) |
常用方法:
| 方法名称 | 说明 |
|---|---|
| public int read() | 每次读取一个字节返回,如果发现没有数据可读会返回-1. |
| public int read(byte[ ] buffer) | 每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1. |
用FileInputStream读取单个字节
- 读取数据的性能很差!
- 读取汉字输出会乱码!!无法避免的!!
- 流使用完毕之后,必须关闭!释放系统资源! close()
public class myFileinputStream {
public static void main(String[] args) throws IOException {
try(//低级输入流 FileInputStream
//创建管道 括号中可以是文件对象,也可以直接是一个路径,这里是相对路径
InputStream ins=new FileInputStream("\Ajava-code\src\texts.txt");)
{
// 将文件中的数据一个一个字符的写入内存
// int re1= ins.read();
// System.out.println((char) re1); //因为是一个字节是一个数字编码,转为字符才文件中的
//一个字节一个字节的读取性能太差了,所以需要循环的读取
int len; // 用于记住读取的字节
while ((len=ins.read())!=-1){
System.out.print((char)len); //abcdefghijklmn
}
ins.close(); //使用完一定要关闭流,否则占用资源
} catch (IOException e) {
e.printStackTrace();
}
}
}
用FileInputStream读取多个字节
public class myFileinputStream2 {
public static void main(String[] args) {
//初级输入流,一次读取多个字节
try(// 创建输入流管道和源文件接通
InputStream ins=new FileInputStream("\Ajava-code\src\texts.txt");//多态写法)
) {
File f=new File("\Ajava-code\src\texts.txt");
//创建一个水桶,定义每一次读取的字节
// byte[] bytes=new byte[3];
long size =f.length();
byte[] bytes=new byte[(int)size]; //直接让桶的容量为文件的长度,这样就可以一次性的读完整个文件
int len; //记录每一次的读取的长度
while ((len=ins.read(bytes))!=-1){
//读取出来已经装到水桶里面了,就是字节数组,接受一下
String newins=new String(bytes);
System.out.println(newins);
}
}
}
使用FileInputStream每次读取多个字节,读取性能得到了提升,但读取汉字输出还是会乱码。
解决中文乱码问题
方式一
自己定义一个字节数组与被读取的文件大小一样大,然后使用该字节数组,一次读完文件的全部字节。
File f=new File("\Ajava-code\src\texts.txt");
//创建一个水桶,定义每一次读取的字节
// byte[] bytes=new byte[3];
long size =f.length();
byte[] bytes=new byte[(int)size]; //直接让桶的容量为文件的长度,这样就可以一次性的读完整个文件
方式二
Java官方为InputStream提供了如下方法,可以直接把文件的全部字节读取到一个字节数组中返回。
| 方法名称 | 说明 |
|---|---|
| public byte[] readAllBytes() throws TOException | 直接将当前字节输入流对应的文件对象的字节数据装到一个字节数组返回 |
//官方的直接把文件全部字节读取到一个字节数组返回
// readAllBytes( path); 里面必须是一个path对象
Path path= Paths.get("\Ajava-code\src\texts.txt");
byte[] bytes1= Files.readAllBytes(path);
String as=new String(bytes1);
System.out.println(as);
直接把文件数据全部读取到一个字节数组可以避免乱码,是否存在问题?
如果文件过大,创建的字节数组也会过大,可能引起内存溢出。
所以读写文本内容更适合用字符流,字节流适合做数据的转移,如:文件复制等。
FileOutputStream(文件字节输出流)
作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去
构造器:
| 构造器 | 说明 |
|---|---|
| public Fileoutputstream(File file) | 创建字节输出流管道与源文件对象接通 |
| public Fileoutputstream(String filepath) | 创建字节输出流管道与源文件路径接通 |
| public Fileoutputstream(File file, boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
| public FileOutputStream(String filepath,boolean append) | 创建字节输出流管道与源文件路径接通,可追加数据 |
方法:
| 方法名称 | 说明 |
|---|---|
| public void write(int a) | 写一个字节出去 |
| public void write(byte[ ] buffer), | 写一个字节数组出去 |
| public void write(byte[] buffer , int pos , int len) | 写一个字节数组的一部分出去。 |
| public void close() throws IOException | 关闭流。 |
public class myOutputStream {
//字节输出流
public static void main(String[] args) throws FileNotFoundException {
try( //创建链接文件的输出管道 后一个true参数是是否可以追加,否则就是写入一次就覆盖已经有的
OutputStream outs=new FileOutputStream("\Ajava-code\src\text2.txt");) {
//一个一个字节的输出写入到文件
outs.write(98);
// outs.write('哎');
// outs.write('哎');
//写入一个字节数组
byte[] buffer="我爱你中国".getBytes(StandardCharsets.UTF_8);
outs.write(buffer);
//写入换行
byte[] br="\r\n".getBytes();
outs.write(br);
//指定字节数组写入的长度
byte[] buffer1="我爱你中国".getBytes(StandardCharsets.UTF_8);
outs.write(buffer1,0,15); //最后一个参数是要写入的字节长度
outs.close();// 关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件复制
字节流非常话合做一切文件的复制操作,因为任何文件的底层都是字节,字节流做复制,是一字不漏的转移完全部字节,只要复制后的文件格式一致就没问题!
public class copyFile {
//文件复制
public static void main(String[] args) {
File starts=new File("\Ajava-code\src\texts.txt");
File ends=new File("\Ajava-code\src\text3.txt");
copyFiles(starts,ends);
}
public static void copyFiles(File start,File end) {
try(//先获取输入管道
InputStream ins=new FileInputStream(start);
//获取输出管道
OutputStream outs=new FileOutputStream(end);
)
{
//创建一个字节数组,增加性能
byte [] buffer=new byte[(int) start.length()];
int len ; //记录读取到的字节
//拿到需要复制的文件里面的内容
while ((len=ins.read(buffer))!=-1){
//输入写入到目标文件,把桶里面的到出来
outs.write(buffer,0,len);// 有多少就到多少,防止乱码
}
System.out.println("文件复制成功!!!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
IO流-释放资源
java中有两种专业的释放IO流的方式,其实就是关闭流的方式,因为有时候会忘记关闭,或者不知道什么时候关闭流,所以可以直接通过下面的两种方式,完美的关闭流
try-catch-finally
finally代码区的特点:无论try中的程序是正常执行了,还是出现了异常,最后都一定会执行finally区,除非JVM终止。
作用:一般用于在程序执行完成后进行资源的释放操作(专业级做法) 。
try{
.........
...
}catch(IOException e){
e.printStackTrace();
}finally{
//return 11; 千万不要在这里面返回值
}
try-with-resource
JDK提供的方式
try(定义资源1;定义资源2;...) { //()中只能放置资源,否则报错
//可能出现异常的代码;
}catch(异常类名变量名){
//异常的处理代码;
}
该资源使用完毕后,会自动调用其close()方法,完成对资源的释放!
括号中只可以放置资源,那么什么是资源呢?
资源一般指的是最终实现了AutoCloseable接口。
public abstract class InputStream implements closeable{ }
public abstract class OutputStream implements Closeable,Flushable { }
public interface closeable extends AutoCloseable { }
IO流-字符流
FileReader 文件字符输入流
作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。
构造器
| 构造器 | 说明 |
|---|---|
| public FileReader(File file) | 创建字符输入流管道与源文件接通 |
| public FileReader (String pathname) | 创建字符输入流管道与源文件接通 |
方法
| 方法名称 | 说明 |
|---|---|
| public int read() | 每次读取一个字符返回,如果发现没有数据可读会返回-1. |
| public int read(char[ ] buffer) | 每次用一个字符数组去读取数据,返回字符数组读取了多少个字符,如果发现没有数据可读会返回-1. |
基本使用:
public class myfileReader {
//字符输入流
public static void main(String[] args) {
try {
//创建字符输入流与文件接通的管道
Reader reader=new FileReader("\Ajava-code\src\text3.txt");
//读取文到内存中,一个一个字符的读取
// int buf= reader.read();
// System.out.println(buf);
//循环输入
// int len;
// while ((len= reader.read())!=-1){ //每一次读取一个字符是肯定性能比较差的
// System.out.print((char) len);
// }
//一个字符数组进行读取
System.out.println("============");
char[] buffer=new char[3]; //一次读取3个字符
int len1; //记录读取了几个字符
while ((len1= reader.read(buffer))!=-1){
//输入到数组中了,在倒出来
System.out.print(buffer); //abcdefghijklmn
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
FileWriter 文件字符输出流
作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去。
构造器:
| 构造器 | 说明 |
|---|---|
| public Filewriter(File file) | 创建字符输出流管道与源文件对象接通 |
| public Filewriter(string filepath) | 创建字符输出流管道与源文件对象接通 |
| public Filewriter(File file,boolean append) | 创建字符输出流管道与源文件对象接通,可追加数据 |
| public Filewriter(string filepath,boolean append) | 创建字符输出流管道与源文件路径接通,可追加数据 |
方法:
| 方法名称 | 说明 |
|---|---|
| void write(int c) | 写一个字符 |
| void write(String str) | 写一个字符串 |
| void write(String str, int off, int len) | 写一个字符串的一部分 |
| void write(char[] cbuf) | 写入一个字符数组 |
| void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
//基本使用
public class myFileWriter {
//文件字符输出流
public static void main(String[] args) {
// try {
// //创建一个字符输出流和文件的通道
// Writer outs=new FileWriter("\Ajava-code\src\text4.txt");
// outs.write(87);
// outs.flush();
// 字符输出流写出数据后,必须需要刷新一下流或者关闭流才可以真正的写入到指定的文件中
// } catch (IOException e) {
// e.printStackTrace();
// }
try( //创建一个字符输出流和文件的通道
Writer outs=new FileWriter("\Ajava-code\src\text4.txt");) {
outs.write(87);
//加了异常后就会自动关闭流了,就不用手动刷新了
// outs.flush(); //需要刷新一下才可以真正的写入到指定的文件中
//直接写入一个字符串
outs.write("今天的天气很好的,适合出去转一转");
// 因为可以直接输出一个字符串,所以就是输入换行的字符串
outs.write("\r\n");
outs.write("今天的天气很好的,适合出去转一转");
// 写入字符串的一部分
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意事项
字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效
| 方法名称 | 说明 |
|---|---|
| public void flush() throws IOException | 刷新流,就是将内存中缓存的数据立即写到文件中去生效! |
| public void close() throws IOException | 关闭流的操作,包含了刷新! |
流刷新过后还是可以继续写入的,如果缓冲区装满了,就会自动刷新,然后放入到文件中
但是如果关闭流了就不可以继续写入了
IO流-缓冲流
字节缓冲流的作用:
提高字节流读写数据的性能
原理:字节缓冲输入流自带了8KB缓冲池;字节缓冲输出流也自带了8KB缓冲池。
如何包装原始的字节流(缓冲字节流)
构造器
| 构造器 | 说明 |
|---|---|
| public BufferedInputStream(InputStream is) | 把低级的字节输入流包装成一个高级的缓冲字节输入流,从而提高读数据的性能 |
| public BufferedOutputStream(OutputStream os) | 把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能 |
放发和基本流的差不多一样
public class BufferedInput {
public static void main(String[] args) {
try(//字节缓冲输入输出流
InputStream ins=new FileInputStream("\Ajava-code\src\text4.txt");
//通过字节输入缓冲流包装初级流
BufferedInputStream bufinput=new BufferedInputStream(ins);
OutputStream outs=new FileOutputStream("\Ajava-code\src\text5.txt");
//通过字节输入缓冲流包装初级流
BufferedOutputStream bufoutput=new BufferedOutputStream(outs);
) {
// 字节数组
byte[] bytes=new byte[1024]; //1kB 的读取
//读取数据
int len; //记录读取了多少字节
while((len=bufinput.read(bytes))!=-1){ //从输入的缓冲池里面读取
//输出到文件中
bufoutput.write(bytes,0,len); //满了8KB 就放到管道,写出到文件中
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
如何包装原始的字符流(缓冲字符流)
作用:自带8K(8192)的字符缓冲池,可以提高字符输入流读取字符数据的性能。
和缓冲字节流大同小异
构造器
| 构造器 | 说明 |
|---|---|
| public BufferedReader(Reader r) | 把低级的字符输入流包装成字符缓冲输入流管道,从而提高字符输入流读字符数据的性能 |
字符缓冲输入流新增的功能:按照行读取字符
| 方法 | 说明 |
|---|---|
| public String readLine() | 读取一行数据返回,如果没有数据可读了,会返回null |
使用方法和缓冲字节流一样
IO流-转换流
不同编码读职出现乱码的问题
如果代码编码和被读取的文本文件的编码是一致的,使用字符流读取文本文件时不会出现乱码!
lnputStreamReader(字符输入转换流)
解决不同编码时,字符流读取文本内容乱码的问题。
解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。
构造器
| 构造器 | 说明 |
|---|---|
| public InputStreamReader( InputStream is) | 把原始的字节输入流,按照代码默认编码转成字符输入流(与直接用FileReader的效果一样) |
| public InputStreamReader(InputStream is , String charset) | 把原始的字节输入流,按照指定字符集编码转成字符输入流 (重点) |
InputStream is=new FileInputStream("\Ajava-code\src\text4.txt");
Reader isr=new InputStreamReader(is,"GBK");
指定的字符集编码,一般都是文件是啥类型,就写啥类型,这样后面怎么读取都不会乱码了
OutputStreamWriter字符输出转换流
作用:可以控制写出去的字符使用什么字符集编码。
解决思路︰获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了。
| 构造器 | 构造器 |
|---|---|
| public Outputstreamwriter(outputstream os) | 可以把原始的字节输出流,按照代码默认编码转换成字符输出流。 |
| public OutputStreamMriter(OutputStream os,String charset) | 可以把原始的字节输出流,按照指定编码转换成字符输出流(重点) |
使用方法和字符输入转换流一样的;
IO流-打印流
PrintStream
作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。
构造器
| 构造器 | 说明 |
|---|---|
| public PrintStream(outputStream/File/String) | 打印流直接通向字节输出流/文件/文件路径 |
| public PrintStream(String fileName,Charset charset) | 可以指定写出去的字符编码 |
| public Printstream(outputstream out, boolean autoFlush) | 可以指定实现自动刷新 |
| public PrintStream(OutputStream out, boolean autoFlush, String encoding) | 可以指定实现自动刷新,并可指定字符的编码 |
方法
| 方法 | 说明 |
|---|---|
| public void println(Xxx xx) | 打印任意类型的数据出去 |
| public void write(int/byte[]/byte[] 一部分) | 可以支持写字节数据出去 |
基本使用:
public class printIO {
//打印流
public static void main(String[] args) throws IOException {
//创建打印流管道
InputStream inputs=new FileInputStream("\Ajava-code\src\text6.txt");
PrintStream p1=new PrintStream("\Ajava-code\src\text7.txt");
p1.println(78);
p1.println("中国"); //支持打印任何的数据类型
byte[] bytes="今天天气好".getBytes(StandardCharsets.UTF_8);
p1.write(bytes);
// System.out.println(Arrays.toString(bytes));
System.out.println("天天向上");
System.out.println("快乐向前冲");
//应用,输出语句重定向
PrintStream p2=new PrintStream("\Ajava-code\src\text8.txt");
//把系统默认的打印流对象改成自己设置的打印流
System.setOut(p2);
System.out.println("熊大熊二光头强");
System.out.println("肥波");
}
}
PrintWriter
和printStream也是大同小异
构造器
| 构造器 | 说明 |
|---|---|
| public Printwriter(outputstream/writer/File/string) | 打印流直接通向字节输出流/文件/文件路径 |
| public Printwriter(string fileName,Charset charset) | 可以指定写出去的字符编码 |
| public Printwriter(outputstream out/writer, boolean autoFlush) | 可以指定实现自动刷新 |
| public Printwriter(OutputStream out, boolean autoFlush,Sstring encoding) | 可以指定实现自动刷新,并可指定字符的编码 |
方法
| 方法 | 说明 |
|---|---|
| public void println(Xxx xx) | 打印任意类型的数据出去 |
| public void write(int/string/char[]/..) | 可以支持写字符数据出去 |
PrintStream和PrintWriter的区别
打印数据的功能上是一模一样的:都是使用方便,性能高效(核心优势)
PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法。
PrintWriter继承自字符输出流Writer,因此支持写字符数据出去。
打印流的应用-----输出语句的重定向
可以把输出语句的打印位置改到某个文件中
PrintStream p2=new PrintStream("\Ajava-code\src\text8.txt");
//把系统默认的打印流对象改成自己设置的打印流
System.setOut(p2);
System.out.println("熊大熊二光头强");
System.out.println("肥波");
IO流-数据流
DataOutputStream(数据输出流)
允许把数据和其类型一并写出去。
构造方法:
| 构造器 | 说明 |
|---|---|
| public DataOutputstream(outputstream out) | 创建新数据输出流包装基础的字节输出流 |
方法
| 方法 | 说明 |
|---|---|
| public final void writeByte(int v) throws IOException | 将byte类型的数据写入基础的字节输出流 |
| public final void writeInt(int v) throws IOException | 将int类型的数据写入基础的字节输出流 |
| public final void writeDouble(Double v) throws TOException | 将double类型的数据写入基础的字节输出流 |
| public final void writeUTF(String stn) throws IOException | 将字符串数据以UTF-8编码成字节写入基础的字节输出流 |
| public void write(int/byte[]/byte[]一部分) | 支持写字节数据出去 |
DataInputStream(数据输入流)
用于读取数据输出流写出去的数据 。遵循怎么写的怎么读,写的和读的类型需要一样
构造方法:
| 构造器 | 说明 |
|---|---|
| public DataInputStream( Inputstream is) | 创建新数据输入流包装基础的字节输入流 |
方法
| 方法 | 说明 |
|---|---|
| Public final byte readByte() throws IOException | 读取字节数据返回 |
| public final int readInt() throws IOException | 读取int类型的数据返回 |
| public final double readDouble( ) throws IOException | 读取double类型的数据返回 |
| public final string readUTF( ) throws IOException | 读取字符串数(UTF-8)据返回 |
| puNic int readInt()/read(byte[]) | 支持读字节数据进来 |
public class DataIO {
public static void main(String[] args) throws FileNotFoundException {
try( // 数据流
OutputStream outs=new FileOutputStream("\Ajava-code\src\text9.txt");
//创建数据输出流管道
DataOutputStream data=new DataOutputStream(outs);) {
data.writeInt(89);
data.writeBoolean(true);
data.writeDouble(89.7);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class DataIo2 {
public static void main(String[] args) {
try( // 数据流
InputStream ins=new FileInputStream("\Ajava-code\src\text9.txt");
//创建数据输出流管道
DataInputStream data=new DataInputStream(ins);) {
int a=data.readInt();
boolean b=data.readBoolean();
double c=data.readDouble();
System.out.println(a); //89
System.out.println(b); //true
System.out.println(c); //89.7
} catch (IOException e) {
e.printStackTrace();
}
}
}
IO流-序列化流
ObjectOutputStream(对象字节输出流)
可以把Java对象进行序列化:把Java对象存入到文件中去。
| 构造器 | 说明 |
|---|---|
| public objectoutputstream(Outputstream out) | 创建对象字节输出流,包装基础的字节输出流 |
方法:
| 方法 | 说明 |
|---|---|
| public final void writeObject(Object o) throws TOException | 把对象写出去 |
注意:对象如果要参与序列化,必须实现序列化接口(java.io.Serializable)
ObjectInputStream(对象字节输入流)
可以把java对象进行反序列化:把存储文件中的java对象读到内存中来
| 构造器 | 说明 |
|---|---|
| public ObjectInputstream(Inputstream is) | 创建对象字节输入流,包装基础的字节输入流 |
方法:
| 方法 | 说明 |
|---|---|
| public final Object readObject() | 把存储在文件中的java对象读出来 |
下面是序列化流的案例:
封装一个学生类
import java.io.Serializable;
public class Student implements Serializable { //使用序列化流,就必须让对象事项这个接口,标记一下
private String name;
private int age;
private char sex;
public Student() {
}
@Override
public String toString() {
return "Student{" +
"name='" + name + ''' +
", age=" + age +
", sex=" + sex +
'}';
}
public Student(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
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;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
操作序列化类:
public class ObjectIO {
public static void main(String[] args) {
//先创建一个对象
Student stu=new Student("张三",18,'男');
try( //对象字节输出流
OutputStream outs=new FileOutputStream("\Ajava-code\src\text10.txt");
//创建对象直接流管道包装初级字节输出流管道
ObjectOutputStream obj1=new ObjectOutputStream(outs);
//对象字节输入流
InputStream ins=new FileInputStream("\Ajava-code\src\text10.txt");
//创建对象直接流管道包装初级字节输入流管道
ObjectInputStream obj2=new ObjectInputStream(ins);) {
//把学生对象输出到文件中
obj1.writeObject(stu);
//把学生对象输入到文件中
Object obs=obj2.readObject();
System.out.println(obs); //Student{name='张三', age=18, sex=男}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
如果要一次序列化多个对象,怎么办?
用一个ArrayList集合存储多个对象,然后直接对集合进行序列化即可
注意:ArrayList集合已经实现了序列化接口!