IO(Input Output)技术

IO(Input Output)技术

1 IO的概述

IO输入输出流。主要解决的是数据在不同设备(介质)之间的传输问题。IO的应用场景 非常广泛,比如文件上传与下载,还有资源的读写操作。

在java当中,数据除了在内存中保存。我们还可以将数据保存在文件中,那么我们需要使用一个类来描述文件,那么就是File类。

1.1 File类

File(java.io包)。File用来描述文件(目录)。我们要学习File。首先就需要学习File的 构造函数、api。

1.1.1 File的构造函数

描述File的构造函数主要是 3 个。

第一种: File(String path) 根据文件的路径(绝对路径 相对路径)去创建File对象。

//第一种创建对象的方法 传入的是描述文件的绝对路径
File file = new File("F:\\upload\\hello.txt");
System.out.println(file.exists()); //exists 判断文件是否存在 true 存在 false 不存在
//传入相对路径
File file1 = new File("test.txt");
System.out.println(file1.exists());

第二种:File(String parent,String child)。根据文件的父路径和文件名来构建File对象。

//第二种创建文件对象的方法
File file2 = new File("F:\\upload","demo1.txt");
System.out.println(file2.exists());

第三种:File(File parent,String child)。根据文件的父路径(File)和子路径来构建文件对象。

File f1 = new File("F:\\upload");
//参数1 文件对象 参数2 资源名称
File file3 = new File(f1,"demo1.txt");
System.out.println(file3.exists());

需要注意的是:关于文件的分隔符的问题。

在windows平台下面,我们描述文件使用到的分隔符是 \ \ (使用 / 也可以)。但是在linux操作系统里面我们使用文件分割符只能是/。这个时候会出现分隔符不兼容的 问题(windows平台开发的程序,在linux系统里面去运行)。

使用File.separator 描述分隔符的问题。

File file4 = new File("F:" + File.separator + "upload"+File.separator + "demo1.txt");
System.out.println(file4.exists());

1.1.2 File的常用的方法


1.1.2.1 创建和删除的方法

  • createNewFile() 创建文件的方法
public static void main(String[] args) throws IOException {
   File file = new File("F:\\upload\\Hello.java");
   if(!file.exists()){	//创建文件
   	boolean result = file.createNewFile();
       System.out.println("创建的结果是:" + result);
   }
}

这个方法的返回值是boolean类型的值。 创建文件的前提是文件不存在的情况下才

会创建。如果创建成功返回值为true。如果创建失败 返回值为false。

  • mkdir 创建文件目录(单级文件目录)

这个方法的返回值是bolean类型的值。true 创建成功。false 创建失败。

File file = new File("F:\\upload\\abc");
if(!file.exists()){    
    boolean flag = file.mkdir();   // make directory    				System.out.println(flag);
}
  • mkdirs 创建多级文件目录
File file = new File("F:\\upload\\a\\b\\c\\d");
if(!file.exists()){
	boolean flag = file.mkdirs(); //创建多级文件目录
	System.out.println(flag);
}
  • createNewFile()
File file = new File("/test.txt");
if(!file.exists() || (file.exists() && file.isDirectory()){
	file.createNewFile();
}
  • renameTo(File file)

    • 如果是在同级目录下面操作文件,这个方法就是重命名
File file = new File("F:\\upload\\hello.txt");  //重命名
boolean result = file.renameTo(new File("F:\\upload\\hello1.txt"));
System.out.println(result);

  • 如果不是在同一个目录下面操作文件,这个方法就是剪切并重命名
File file = new File("F:\\upload\\hello1.txt");
boolean result = file.renameTo(new
File("F:\\upload\\jd\\cat.txt"));
System.out.println(result);
  • delete 删除文件(目录)
//删除文件
File file = new File("F:\\upload\\jd\\cat.txt");
boolean flag = file.delete();
System.out.println("删除的结果是:" + flag);

//删除目录 只能删除空目录,不能删除带有文件的目录
File file = new File("F:\\upload\\abc");
System.out.println(file.delete());

1.1.2.2 判断的方法
  • exists 判断文件(目录)是否存在
//第一种创建对象的方法 传入的是描述文件的绝对路径
File file = new File("F:\\upload\\demo1.txt");
System.out.println(file.exists()); 
//exists 判断文件是否存在 true 存在 false 不存在
  • isFile() 判断是否是文件
File file = new File("F:\\upload\\abc\\demo1.txt");
System.out.println(file.isFile());// true 就是文件 false 不是文件
  • isDirectory() 判断是否是文件目录
File file = new File("F:\\upload\\abc");
System.out.println(file.isDirectory());
  • canRead() 判断文件是否只读
File file = new File("F:\\upload\\abc\\demo1.txt");
System.out.println(file.canRead());
  • canWrite() 判断文件是否可写
File file = new File("F:\\upload\\abc\\demo1.txt");
System.out.println(file.canWrite());
  • isHidden() 判断文件是否是隐藏文件
File file = new File("F:\\upload\\abc\\demo1.txt");
System.out.println(file.isHidden());
  • isAbsolute() 判断文件的路径是否是绝对路径
File file = new File("F:\\upload\\abc\\demo1.txt");
System.out.println(file.isAbsolute());
1.1.2.3 获取的方法
  • getName() 获取文件的名称
public static void main(String[] args) {
	File file = new File("F:\\upload\\Hello.java");
	if(file.exists()){
		String name = file.getName();
        //不管文件存不存在 都会获取文件的名称。		
        System.out.println(name);
    }
}

注意:

getName方法获取文件的名称。不管文件存不存在,都会拿到文件的名称。所以我们在使用这个方法的时候,最好先判断一下文件是否存在,如果文件存在,再去获取文件的名称。

  • getParent() 获取文件的父级目录
File file = new File("F:\\upload\\Hello.java");
String parent = file.getParent();
System.out.println(parent);
  • getAbsolutePath() 获取文件的绝对路径
File file = new File("F:\\upload\\Hello.java");
String path = file.getAbsolutePath();
System.out.println(path);
  • lastModified() 获取文件最后的修改时间
public static void main(String[] args) {
    File file = new File("F:\\upload\\Hello.java");
    long modified = file.lastModified();
    System.out.println(modified);
    //将毫秒值转换成时间格式的数据
    Date date = new Date(modified);
    //SimpleDateFormat进行日期格式的转换
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //将date类型的数据转换成String类型的数据
    String dateTime = sdf.format(date);
    System.out.println(dateTime);
}
  • length 获取文件的长度
long length = file.length();
System.out.println(length);
1.1.2.4 与文件夹有关的方法
  • listRoots 获取当前计算机的盘符列表
File[] roots = File.listRoots();
for(File file : roots){
	System.out.println(file);
}
  • list 获取指定目录下面的文件和文件目录的所有名称
File file = new File("F:\\upload");
String[] list = file.list();
for(String str: list){
	System.out.println(str);
}
  • listFiles 获取指定目录下面的所有文件对象
File file = new File("F:\\upload");
File[] files = file.listFiles();
for(File f : files){
//获取文件(目录)的名称
	System.out.println(f.getName());
}

1.1.3 File相关的案例

  • 案例 1 需求:获取指定目录下面的所有java文件

方法 1 :

public static void main(String[] args) {
	File file = new File("F:\\upload");  //获取指定目录下面的所有文件
    String[] list = file.list();
	for(String fileName : list){
		if(fileName.endsWith(".java")){	 //判断字符串以指定的内容结尾
			System.out.println(fileName);
        }
    }
}

方法 2 :

第一步: 定义文件过滤器

//定义文件过滤器
public class FileFilter implements FilenameFilter {
     /**
    * 定义过滤的规则
    * @param dir 文件目录的File对象
    * @param name 文件名
    * @return
	*/
    @Override
    public boolean accept(File dir, String name) {
        return name.endsWith(".java");
        }
}

第二步: 使用文件过滤器

public static void main(String[] args) {
	File file = new File("F:\\upload");
	String[] list = file.list(new FileFilter());
	for(String fileName : list){
		System.out.println(fileName);
    }
}
  • 案例 2 将指定目录下面的文件归类输出
public static void main(String[] args) {
    File file = new File("F:\\upload");
    File[] files = file.listFiles();
    //遍历文件目录
    for(File f : files){
    	String fileName = f.getName();
    	if(f.isDirectory()){ //获取文件目录
    		System.out.println("文件目录:" + fileName);
    	}
    }
    //遍历图片信息
    for(File f : files){
    	String fileName = f.getName();
    	if(fileName.endsWith(".jpg")){
   			 System.out.println("图片:" + fileName);
   	 	}
	}
    //遍历txt文档
	for(File f : files){
		String fileName = f.getName();
		if(fileName.endsWith(".txt")){
			System.out.println("txt文件:" + fileName);
		}
	}
    //遍历java文件
	for(File f : files){
		String fileName = f.getName();
		if(fileName.endsWith(".java")){
			System.out.println("Java文件:" + fileName);
		}
    }
}	
  • 案例 3 获取指定目录下面的所有文件夹
public class MyFilter implements FilenameFilter {
    @Override
	public boolean accept(File dir, String name) {
		File file = new File(dir,name);
		return file.isDirectory();   //获取文件目录
    }
}
public static void main(String[] args) {
	File file = new File("F:\\upload");
	File[] files = file.listFiles(new MyFilter());
	for(File f : files){
		System.out.println(f.getName());
    }
}

1.2 IO流

数据在硬盘和内存之间进行传输需要的流通道。IO流根据流向的划分可以分为输入流,输出流。我们也可以根据类型来划分,根据类型可以划分为字节流 字符流


1.2.1 字节流


1.2.1.1 字节输入流

InputStream 是所有字节输入流的基类(父类),它是一个抽象类

FileInputStream 字节输入流,继承了InputStream

需求:读取txt文档里面的数据。

使用字节输入流读取文件的步骤:

  1. 构建文件对象
  2. 构建字节输入流
  3. 执行read操作,读取文件
  4. 关闭流通道,释放资源

第一种读取文件的方式: 循环读取每个字节,然后再强制转换成字符。

public class IODemo1 {
    public static void main(String[] args) throws Exception{
        //构建文件对象
        File file = new File("F:\\upload\\Demo.txt");
        //构建输入流对象
        InputStream in = new FileInputStream(file);
        int data = 0;
        //指定读操作。如果到达文件的末尾处,read的返回值就为-1
        while((data = in.read()) != -1){
            System.out.print((char)data);
        }
        //关闭资源
        in.close();
    }
}

注意:

1.循环读取字节,为什么返回值必须为-1才跳出循环操作。

在官方源码里面定义好了。

在这里插入图片描述

  1. 必须要记得关闭资源。因为如果不关闭资源 会导致内存空间得不到释放,最终会导致内存溢出的问题。

面试考点:

内存泄漏(memory leak):

是指程序在申请内存后,无法释放已申请的内存空间,导致系统无法及时回收内存并且分配给其他进程使用。通常少次数的内存无法及时回收并不会到程序造成什么影响,但是如果在内存本身就比较少获取多次导致内存无法正常回收时,就会导致内存不够用,最终导致内存溢出。

内存溢出(out of memory):

指程序申请内存时,没有足够的内存供申请者使用,导致数据无法正常存储到内存中。也就是说给你个int类型的存储数据大小的空间,但是却存储一个long类型的数据,这样就会导致内存溢出。

第二种读取文件的方式:

配合字节数组批量读取,提高读取文件的效率。

public class IODemo2 {
    public static void main(String[] args) throws Exception{
        //构建文件对象
        File file = new File("F:\\upload\\Demo.txt");
        //构建输入流对象
        InputStream in = new FileInputStream(file);
        byte[] bytes = new byte[1024];
        int data = 0; //实际读取字节的个数
        //配合字节数组进行读操作
        while((data = in.read(bytes)) != -1){
            String msg = new String(bytes,0,data);
            System.out.println(msg);
        }
        //关闭资源
        in.close();
    }
}
1.2.1.2 字节输出流

OutputStream是所有字节输出流的基类。它也是一个抽象类。

FileOutputStream 是OutputStream的子类。

需求:将指定的数据写入到指定文件中。

public class IODemo3 {
    public static void main(String[] args) throws Exception {
        //构建文件对象
        File file = new File("F:\\upload\\Demo.txt");
        //构建输出流对象(新写入的内容会覆盖掉后写入的内容)
        //OutputStream out = new FileOutputStream(file);
        //参数1 文件对象  参数2 是否追加新内容 true 追加 false 不追加,直接覆盖
        OutputStream out = new FileOutputStream(file,true);
        String msg = "hello,java....";
        //执行写操作
        out.write(msg.getBytes());
        //关闭资源
        out.close();
    }
}

案例:使用字节输入流和字节输出流实现图片的拷贝。

/**
 * 使用字节输入流和字节输出流实现图片的拷贝
 */
public class CopyImageDemo {
    public static void main(String[] args) throws Exception{
        //创建图片的源对象
        File file = new File("F:\\upload\\AudiA7.jpg");
        //构建字节输入流
        InputStream in = new FileInputStream(file);
        //创建输出的文件对象
        File newFile = new File("F:\\upload\\A7.jpg");
        //构建字节输出流对象
        OutputStream out = new FileOutputStream(newFile);
        //先读 再写
        byte[] bytes = new byte[1024];
        int data = 0;
        while((data = in.read(bytes)) != -1){//读操作
            out.write(bytes,0,data);//写操作
        }
        //关闭资源
        out.close();
        in.close();
    }
}
1.2.1.3 字节缓冲流

缓冲流java给我们提供的一个字节流,专门用来提高文件的读写效率。

BufferedInputStream 缓冲字节输入流,间接的继承了InputStream。

在这里插入图片描述

BufferedOutputStream 缓冲字节输出流,间接的继承了OutputStream。

在这里插入图片描述

缓冲字节输入流和缓冲字节输出流主要是通过减少文件的读写次数来提高文件的读写效率。为什么它们可以提高文件的读写效率呢,因为缓冲流的内部维护了一个缓冲区。缓冲区的内部其实维护了一个字节数组,默认字节数组的大小了8192.

我们使用缓冲区进行文件读写的时候,我们首先会把数据写到缓冲区里面,当缓冲区满了之后,然后刷新缓冲区(flush方法)。一般适用于文件内容比较多的场景。

1.2.1.3.1 使用缓冲流来进行数据的读取
/**
 * 使用缓冲流读取数据
 */
public class BufferedIODemo1 {
    public static void main(String[] args) throws Exception {
        File file = new File("F:\\upload\\Hello.java");
        InputStream in = new FileInputStream(file);
        //构建缓冲输入流
        BufferedInputStream bif = new BufferedInputStream(in);
        int data = 0;
        //执行读操作
        while((data = bif.read()) != -1){
            System.out.print((char)data);
        }
        //关闭资源
        bif.close();
        in.close();
    }
}
1.2.1.3.2 使用缓冲流来进行数据的写操作
/**
 * 使用缓冲流读取数据
 */
public class BufferedIODemo2 {
    public static void main(String[] args) throws Exception {
        File file = new File("F:\\upload\\Hello.java");
        OutputStream out = new FileOutputStream(file,true);
        //构建缓冲输出流对象
        BufferedOutputStream bos = new BufferedOutputStream(out);
        String message = "hello,spring";
        //写操作
        bos.write(message.getBytes());
        //刷新缓冲区
        bos.flush(); 
        //关闭资源
        bos.close();
        out.close();
    }
}

练习:使用缓冲输入流和缓冲输出流实现文件的拷贝

/**
 * 使用缓冲流的方式读写文件
 */
public class IOTest {
	public static void main(String[] args) throws Exception{
		//构建字节流
		InputStream in = new FileInputStream(new File("F:\\upload\\AudiA7.jpg"));
		OutputStream out = new FileOutputStream(new
File("F:\\upload\\A8.jpg"));
		//根据字节流构建缓冲流
		BufferedInputStream bin = new BufferedInputStream(in);
		BufferedOutputStream bout = new BufferedOutputStream(out);
		int length = 0 ;
		//byte[] bytes = new byte[1024];
		while((length = bin.read()) != - 1 ){
			//bout.write(bytes,0,length);
			bout.write(length); 
        }
        //关闭流通道
        bout.close();
        bin.close();
        out.close();
        in.close();
    }
}

1.2.2 字符流

字符流主要是用来处理中文的。如果使用字节流进行中文数据读取的话,会出现中文乱码的问题。所以我们需要使用字符流来解决这个问题,字符流根据流向的划分,又可以划分为字符输入流、字符输出流。

1.2.2.1 字符输入流

Reader: 字符输入流的基类。是一个抽象类。

FileReader: 字符输入流,间接的继承了Reader这个类。

在这里插入图片描述

需求:使用字符输入流读取文件。

步骤:

  1. 构建目标文件对象

  2. 构建字符流通道

  3. 进行文件的读取操作

  4. 关闭流通道

  • 方案 1 按照字节一个个的读取
public class FileReaderDemo1 {
	public static void main(String[] args) throws Exception{
		//1.构建File对象
		File file = new File("F:\upload\Demo.txt");
		//2.创建字符输入流
		FileReader reader = new FileReader(file);
		int length = 0 ;
		//3.执行读操作
		while((length = reader.read()) != - 1 ){
			System.out.print((char) length);
        }
		//4.关闭资源	
		reader.close();
   	}
}
  • 方法 2 配合字符数组来批量读取
/**
 * 配合字符数组批量读取
 */
public class FileReaderDemo2 {
	public static void main(String[] args) throws Exception {
		//1.构建File对象
		File file = new File("F:\upload\Demo.txt");
		//2.创建字符输入流
		FileReader reader = new FileReader(file);
		int length = 0 ;
		char[] chars = new char[ 1024 ];
		//3.配合字符数组 批量读取文件
		while((length = reader.read(chars)) != - 1 ){
			System.out.println(new String(chars, 0 ,length));
		}
		//4.关闭资源
		reader.close();
    }
}
1.2.2.2 字符输出流

Writer: 字符输出流的基类 它是一个抽象类。

FileWriter: 字符输出流,间接的继承了Writer。

在这里插入图片描述

需求:使用字符输出流写文件。

步骤:

1.构建目标文件对象。

2.构建字符输出流通道。

3.进行文件的写出操作。

4.关闭资源。

/**
* 使用字符输出流写数据
*/
public class FileWriterDemo1 {
	public static void main(String[] args) throws Exception{
        //构建目标文件对象
        File file = new File("F:\\upload\\Demo.txt");
        //构建字符输出流通道 true 追加的内容不会将原来的内容覆盖
        FileWriter writer = new FileWriter(file,true);
        String message = "我爱学习数学";
        //执行写操作
        writer.write(message);
        //关闭资源
        writer.close();
    }
}
1.2.2.3 字符缓冲流
  • 缓冲字符输入流

在java中,sun公司通过BufferedReader这个类来描述缓冲字符输入流。 这个类直
接继承了Reader这个字符流的基类。

public class BufferedReader extends Reader{}

需求: 使用字符缓冲流来读取文件。

方法 1 : 配合字符数组读取,或者单个单个字符读取。

/**
 * 使用缓冲字符输入流来读取文件
 */
public class BufferedFileReaderDemo1 {
	public static void main(String[] args) throws Exception {
		//构建目标文件对象
		File file = new File("F:\\upload\\Demo.txt");
		//构建字符输入流对象
		Reader reader = new FileReader(file);
		//构建缓冲字符输入流对象
		BufferedReader br = new BufferedReader(reader);
		int length = 0 ;
		char[] chars = new char[ 1024 ];
		//读取文件
        /*while((length = br.read()) != -1){
        	System.out.print((char)length);
        }*/
        while((length = br.read(chars)) != - 1 ){
            System.out.println(new String(chars, 0 ,length));
        }
        //关闭资源
        br.close();
        reader.close();
    }
}

方法 2 : 为了提高读取效率,我们可以一行行读取。

readLine方法: 一行行的读取文件,方法的返回值为String。如果到达文件的末尾处,返回值为null。

在这里插入图片描述

public class BufferedFileReaderDemo2 {
	public static void main(String[] args) throws Exception {
        //构建目标文件对象
        File file = new File("F:\\upload\\Demo.txt");
        //构建字符输入流对象
        Reader reader = new FileReader(file);
        //构建缓冲字符输入流对象
        BufferedReader br = new BufferedReader(reader);
        //执行读取操作
        String content = null;
        //content 存储的是每次读取文件的行内容
        while((content = br.readLine()) != null){//readLine一行行读取
        	System.out.println(content);
        }
        //关闭资源
        br.close();
        reader.close();
    }
}
  • 缓冲字符输出流

在java中,sun公司通过BufferedWriter这个类来描述缓冲字符输出流。 这个类直接继承了Writer这个字符流的基类。

public class BufferedWriter extends Writer {}

需求: 使用字符缓冲输出流来写文件。

public class BufferedFileWriterDemo1 {
    public static void main(String[] args) throws Exception {
        File file = new File("F:\\upload\\Demo.txt");
        FileWriter writer = new FileWriter(file,true);
        //构建缓冲字符输出流
        BufferedWriter bw = new BufferedWriter(writer);
        String message = "我爱学习PHP";
        //执行换行输出
        bw.newLine();
        //执行写操作
        bw.write(message);
        //关闭资源
        bw.close();
        writer.close();
    }
}

1.2.3 序列化和反序列化

Java序列化:就是指把Java对象转换为字节序列的过程(将java对象以字节流的方式写入到文件中)。

Java反序列化:就是指把字节序列恢复为Java对象的过程(将字节流读取到程序中,并转换成java对象的过程)。

在java中,我们通过下面的几个类来实现对象的序列化的反序列化。

ObjectOutputStream: 对象写入到文件中 需要用到的一个类。使用这个类的时候,操作对象所属的类必须要实现Serializable接口,否则会出现异常。

public class ObjectOutputStream   
    extends OutputStream implements ObjectOutput, 				ObjectStreamConstants{}

ObjectInputStream:将对象从文件中读到程序中来使用的类。

public class ObjectInputStream    extends InputStream implements ObjectInput, ObjectStreamConstants{}

案例: 序列化和反序列化User对象。

public class User implements Serializable {    
    //序列化的版本号    
    private static final long serialVersionUID = -5194183731020781169L;   
    private String username;    
    private String password;    
    public String getUsername() {        
        return username;   
    }    
    public void setUsername(String username) {        
        this.username = username;   
    }    
    public String getPassword() {        
        return password;   
    }    
    public void setPassword(String password) {        
        this.password = password;   
    }    
    @Override    
    public String toString() {        
        return "User{" +               
            "username='" + username + '\'' +                
            ", password='" + password + '\'' +                
            '}';   
    }
}

/** 
 * 序列化和反序列化对象 
 */
public class UserDemo {    
    //序列化    
    @Test   //注解 修饰一个方法,标识当前方法是一个测试类    
    public void test01() throws Exception{       
        User user = new User();       
        user.setUsername("eric");        
        user.setPassword("admin");       
        //创建输出流对象        
        FileOutputStream out = new FileOutputStream(new File("F:\\upload\\user.txt"));        
        //构建序列化流(对象输出流)       
        ObjectOutputStream oos = new ObjectOutputStream(out);
        //进行对象的序列化        
        oos.writeObject(user);        
        //关闭资源        
        oos.close();        
        out.close();   
    }    
    //反序列化    
    @Test    
    public void test02() throws Exception{        
        //创建输入流对象        
        FileInputStream in = new FileInputStream(new File("F:\\upload\\user.txt"));        
        //构建反序列化流(对象输入流)        
        ObjectInputStream oin = new ObjectInputStream(in);        
        //执行读操作        
        User user = (User) oin.readObject();
        System.out.println(user);        
        //关闭资源        
        oin.close();        
        in.close();   
    }
}

上面使用的是Junit’单元测试。我们只需要在方法上面加上一个@Test注解即可。这个注解修饰的方法就是一个测试方法,功能和main方法一样。

简单了解junit里面的几个常用的注解:

public class TestDemo{    
    @Test    
    public void test03(){        
        System.out.println("test03方法执行了......");   
    }  
    
    @Before //标识在@Test方法之前执行    
    public void before(){        
        System.out.println("before方法执行了......");   
    }
    
    @After //标识在@Test方法之后执行    
    public void after(){        
        System.out.println("after方法执行了......");   
    }
}

问题: 在序列化和反序列化的时候,为什么我们必须要实现Serializable接口?(面试题)

凡是实现 Serializable 接口的类都有一个表示序列化版 本标识符的静态变量:private static final long serialVersionUID;

serialVersionUID 用来表明序列化的版本。它的值是一个静态常量,是 Java 运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。

简单来说,Java 的序列化机制是通过在运行时判断类 的 serialVersionUID 来验证版本一致性的。在进行反序列化时,JVM 会把传来的字节流中的 serialVersionUID 与本地相应实体类的 serialVersionUID 进行比较,如果相同就 认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)

1.2.4 二进制流

案例:将图片转换成二进制数据,再将二进制的数据转换成图片信息。

/** 
 * 将图片转换成二进制的数据 
 * 再将二进制的数据转换成图片 
 */
public class ImageIODemo1 {    
    static BASE64Encoder encoder = new sun.misc.BASE64Encoder();  
    static BASE64Decoder decoder = new sun.misc.BASE64Decoder();  
    public static void main(String[] args) throws Exception{      
        String message = getImageBinary();        
        System.out.println(message);        
        base64StringToImage(message);   
    }    
    //将图片转换成二进制数据    
    public static String getImageBinary() throws Exception{        
        File file = new File("F:\\upload\\A7.jpg");        
        BufferedImage bufferedImage = ImageIO.read(file);        
        //构建二进制输出流对象
        ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
        //将图片相关的数据写入到ByteArrayOutputStream中        
        ImageIO.write(bufferedImage, "jpg", baos);  //经测试转换的图片是格式这里就什么格式,否则会失真        
        byte[] bytes = baos.toByteArray();        
        return encoder.encodeBuffer(bytes).trim();   
    }    
    
    //再将二进制的数据转换成图片    
    public static void base64StringToImage(String message) throws Exception{        
        byte[] bytes1 = decoder.decodeBuffer(message);        
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes1); 
        BufferedImage bi1 = ImageIO.read(bais);        
        File w2 = new File("F:\\upload\\jd\\QQ.jpg");
        // 可以是jpg,png,gif格式        
        ImageIO.write(bi1, "jpg", w2);
        // 不管输出什么格式图片,此处不需改动   
    }
}

eBinary() throws Exception{
File file = new File(“F:\upload\A7.jpg”);
BufferedImage bufferedImage = ImageIO.read(file);
//构建二进制输出流对象
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//将图片相关的数据写入到ByteArrayOutputStream中
ImageIO.write(bufferedImage, “jpg”, baos); //经测试转换的图片是格式这里就什么格式,否则会失真
byte[] bytes = baos.toByteArray();
return encoder.encodeBuffer(bytes).trim();
}

//再将二进制的数据转换成图片    
public static void base64StringToImage(String message) throws Exception{        
    byte[] bytes1 = decoder.decodeBuffer(message);        
    ByteArrayInputStream bais = new ByteArrayInputStream(bytes1); 
    BufferedImage bi1 = ImageIO.read(bais);        
    File w2 = new File("F:\\upload\\jd\\QQ.jpg");
    // 可以是jpg,png,gif格式        
    ImageIO.write(bi1, "jpg", w2);
    // 不管输出什么格式图片,此处不需改动   
}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值