java IO
IO流的概述
/**
* 流的分类
* 1.操作数据:字节流Byte,字符流char
* 2.数据流向:输入流,输出流(以程序为中心)
* 3.流的角色:节点流(FileInputStream),处理流(BufferInputStream)
* 处理流是工作在节点流之上的数据流。
*
* 流的体系结构:
* 抽象基类 节点流(节点流) 缓冲流(处理流)作用于已有流之上
* InputStream FileInputStream BufferInputStream
* OutPutStream FileOutPutStream BufferOutPutStream
* Reader FileReader BufferReader
* Writer FileWriter BufferWriter
*
* 常用流:转化流:InputStreamReader: 基类Reader 字节流装换为字符流
* OutPutStreamWriter:基类writer 字节流转化为字符流
*
* 序列化:objectInputStream:把java对象序列化持久化到磁盘或网络传输
* objectOutPutStream:从磁盘中或网络传输的对象中反序列化到java对象
*
* 流的异常处理需要try catch 必须释放数据流。读入文件需要存在否则报文件找不到
* 写文件时注意是覆盖文件还是追加内容
* 字符流适用于文本 一个中文3个字节
* 字节流适用于非文本文件(ppt mp3 .jpg)
* 字节流读入的是Byte 8个比特位
* 流的使用需要注意释放连接
*
* 缓冲流为文件读写提供类缓冲区,读写效率更高
* java io在设计上体现了装饰者设计模式:在一个类上调用另一类作为参数,进行了功能的增强
*
* 序列化机制:
* 序列化:把内存中的java对象装换为与平台无关的二进制流形式,持久化保存到磁盘或者通过网络
节点进行数据传输
*
* 反序列化:把持久化到磁盘中的java对象,或者网络传输过来的数据流装换成java对象。
* 扩展:
* java NIO (new io)
* apache的工具类FileUtils
* @author stack
*/
文件读写操作
public class FileReadTest {
@Test
public void FileReadTest1() {
//相对路径 绝对路径,指明要操作对象
File file=new File("hello.txt");
//创建输入流
FileReader fileReader=null;
try {
fileReader=new FileReader(file);
//数据读入
int read = fileReader.read();
while (read !=-1){
System.out.print((char)read);
read=fileReader.read();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//jvm无法自动回收,需要手动释放物理连接
try {
if(fileReader!=null){
fileReader.close();}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//read方法的重载
@Test
public void FileReadTest2() {
//相对路径 绝对路径,指明要操作对象
File file=new File("hello.txt");
//创建输入流
FileReader fileReader=null;
try {
fileReader=new FileReader(file);
//数据读入 读入文件到一个字符数组,字符数组每次都被覆盖,没有覆盖的
//上次被保存
char[] cbuf=new char[5];
int len=-1;
while ((len=fileReader.read(cbuf))!=-1){
for(int i=0;i<len;i++){
System.out.print(cbuf[i]);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//jvm无法自动回收,需要手动释放物理连接
try {
if(fileReader!=null){
fileReader.close();}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//写数据到文件
//写文件操作,对应的文件可以不存在,会自动自动创建
//写文件,是需要对FileWrite添加是否覆盖的参数。
@Test
public void FileWriteTest1() {
File file=new File("hello1.txt");
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
FileWriter writer= null;
try {
//注意是否覆盖文件
writer = new FileWriter(file,true);
writer.write("I have a dream \n");
writer.write("you is fish");
} catch (IOException e) {
e.printStackTrace();
}finally {
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void FileReadAndWrite() {
File rFile=new File("hello.txt");
File wFile=new File("hello_copy.txt");
FileReader reader=null;
FileWriter writer= null;
try {
//注意是否覆盖文件
reader =new FileReader(rFile);
writer = new FileWriter(wFile,true);
//边读边写
char[] cbuf=new char[5];
int len=-1;
while((len=reader.read(cbuf))!=-1){
writer.write(cbuf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(reader!=null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void FileInAndOut() {
File rFile=new File("1.jpg");
File wFile=new File("1_copy.jpg");
FileInputStream reader=null;
FileOutputStream writer= null;
try {
//注意是否覆盖文件
reader =new FileInputStream(rFile);
writer = new FileOutputStream(wFile,true);
//边读边写
byte[] cbuf=new byte[1024];
int len=-1;
while((len=reader.read(cbuf))!=-1){
writer.write(cbuf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(reader !=null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void FileBuffInAndOut() {
File rFile=new File("1.jpg");
File wFile=new File("1_copy2.jpg");
FileInputStream fileReader=null;
FileOutputStream fileWriter= null;
BufferedInputStream reader=null;
BufferedOutputStream writer=null;
try {
//注意是否覆盖文件
fileReader =new FileInputStream(rFile);
fileWriter = new FileOutputStream(wFile,true);
reader=new BufferedInputStream(fileReader);
writer=new BufferedOutputStream(fileWriter);
//边读边写
byte[] cbuf=new byte[1024];
int len=-1;
while((len=reader.read(cbuf))!=-1){
writer.write(cbuf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//先关闭外部流在关闭内部流
//关闭外层流的同时也会关闭内层流
try {
reader.close();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void FileBuffReadAndWrite() {
File rFile=new File("hello.txt");
File wFile=new File("hello_copy2.txt");
FileReader fileReader=null;
FileWriter fileWriter= null;
BufferedReader reader=null;
BufferedWriter writer=null;
try {
//注意是否覆盖文件
fileReader =new FileReader(rFile);
fileWriter = new FileWriter(wFile,true);
reader=new BufferedReader(fileReader);
writer=new BufferedWriter(fileWriter);
//边读边写
char[] cbuf=new char[5];
String text;
while((text = reader.readLine())!=null){
writer.write(text);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(reader!=null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
其他流的使用
import org.junit.Test;
import java.io.*;
import java.util.Scanner;
/**
* 标准流:
* System.in
* System.out
* System.err
* 通过修改标准的输入输出流可改变读取/输出的位置 setIn/setOut
* (默认输入设备键盘,输出设备显示器)
* 打印流(输出流):
* printStream system.out实际上就是printStream
* printWriter
* 提供了一系列的print和println方法 将类型装换为字符输出
* 数据流:
* DataInputStream
* DataOutputStream
* 操作基本数据类型和string类型数据
* @author stack
*/
public class OtherStreamTest {
public static void main(String[] args) throws IOException {
//字节流装换字符流
InputStreamReader inputStreamReader=new InputStreamReader(System.in);
//处理流
BufferedReader reader=new BufferedReader(inputStreamReader);
System.out.println("请输入字符串:");
while (true){
String data=reader.readLine();
if("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)){
break;
}
System.out.println(data.toUpperCase());
}
System.out.println("成功退出");
reader.close();
}
@Test
public void test1(){
}
}
转化流使用
import org.junit.Test;
import java.io.*;
/**
* 装换流 处理流 属于字符流(看流后面的名称区分)
* InputStreamReader:将字节的输入流转化为字符的输入流
* OutPutStreamWriter: 将字符的输出流装换为字节的输出流
*
* 提供字节流于字符流之间的装换
* 字节Byte-》字符char:解码
* 字符Byte-》字节char: 编码
* @author stack
*/
public class InputStreamReaderTest {
@Test
public void test1() throws IOException {
FileInputStream inputStream=new FileInputStream("hello.txt");
//把读入的字节Byte装换为字符char 构造参数中可以指定字符集 不指定默认按照系统
InputStreamReader reader=new InputStreamReader(inputStream,"utf8");
char[] chars=new char[5];
int len=-1;
while((len=reader.read(chars))!=-1){
for(int i=0;i<len;i++){
System.out.print(chars[i]);
}
}
//关闭外层流自动关闭内层流
reader.close();
}
@Test
public void test2() throws IOException {
FileInputStream inputStream=new FileInputStream("hello.txt");
FileOutputStream outputStream=new FileOutputStream("hellocopy.txt");
//把读入的字节Byte装换为字符char 构造参数中可以指定字符集 不指定默认按照系统
InputStreamReader reader=new InputStreamReader(inputStream,"UTF-8");
//把字节流byte装换为字符流char输出
OutputStreamWriter writer=new OutputStreamWriter(outputStream,"UTF-8");
char[] chars=new char[5];
int len=-1;
while((len=reader.read(chars))!=-1){
for(int i=0;i<len;i++){
writer.write(chars[i]);
}
}
//关闭外层流自动关闭内层流
reader.close();
writer.close();
}
}
object流
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,
或通过网络将这种二进制流传 输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
序列化是 RMI(Remote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI 是JavaEE 的基础。因此序列化机制是 JavaEE 平台的基础
Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传
来的字节流中的 serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致
的,可以进行反序列化,否则就会出现序列化版本不一致的异 常。(InvalidCastException)
注意:
该类必须需要实现接口:Serializable,否则,会抛出NotSerializableException异常
该类需要提供一个全局常量:serialVersionUID (为了表示序列化版本标识符)
private static final long serialVersionUID;
serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反
序列化时是否兼容。
如果类没有显示定义这个静态常量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修
改,serialVersionUID 可能发生变化。故建议, 显式声明
该类的内部所有属性必须是可序列化的(默认情况下,基本数据类型均可序列化)(static和transient修饰的成员
变量不能进行序列化)因为Static属于类的所以不可进行序列化,transient是一个关键字声明这个属性是不可序列
化
import org.junit.Test;
import java.io.*;
/**
* 序列化机制:
* 序列化:把内存中的java对象装换为与平台无关的二进制流的形似,持久化保存到磁盘或者通过网络节点进行数据传输
*
* 反序列化:把持久化到磁盘中的java对象,或者网络传输过来的数据流装换成java对象。
*
* @author stack
*/
public class ObjectOutputStreamTest implements Serializable {
class Person implements Serializable{
private static final long serialVersionUID=1024856L;
String name;
int age;
public Person(){
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
@Test
public void test1() throws IOException {
ObjectOutputStream obj=new ObjectOutputStream(new FileOutputStream("object.dat"));
obj.writeObject(new String("haha"));
obj.close();
}
@Test
public void test2() throws IOException, ClassNotFoundException {
ObjectInputStream obj=new ObjectInputStream(new FileInputStream("object.dat"));
String object = (String)obj.readObject();
obj.close();
System.out.println(object);
}
@Test
public void test3() throws IOException {
ObjectOutputStream obj=new ObjectOutputStream(new FileOutputStream("person.dat"));
obj.writeObject(new Person("stack", 15));
obj.flush();
obj.close();
}
@Test
public void test4() throws IOException, ClassNotFoundException {
ObjectInputStream obj=new ObjectInputStream(new FileInputStream("person.dat"));
Person object = (Person)obj.readObject();
obj.close();
System.out.println(object);
}
}