I/O:读和写

一般来说,流有两种基本形式:输入流和输出流。
根据输入流,程序可以从数据文件读取数据,但不可向输入流中写入数据;反之,通过输出流,程序可以向数据文件中写入数据。

I/O操作的一般步骤

  • 构造一个与介质相关的I/O对象 ,已提供一种低层次的方法将数据输入或输出到相应的介质;
  • 将与介质相关的对象强制类型转换为他的父类(即抽象I/O类),并利用该对象构造一个流对象。这样便建立起了流类对象与介质相关对象的关联;
  • 这时就可以利用流对象的I/O方法进行相应介质上的数据读写。

字节流和字符流

从流中传输的数据单位分为两类:

  • 字节流
    从InputStream和OutputStream派生出来的一系列类,以字节(byte)为基本处理单位。

  • 字符流
    从Reader和Writer派生出来的一系列类,以16位的Unicode码表示的字符为基本处理单元。

    文件与目录的描述类——File

    File类并不用来进行文件的读/写操作,它用来描述文件对象的属性,既可以表示文件,也可以表示目录。使用它提供的方法,我们可以得到所指对象的描述信息,包括名称、存在否、读/写权限、路径等等。

    在我们写路径的时候需要注意的问题

    当我们在Windows环境使用路径时,其分隔符不能是单一的“\”符号,因为与C/C++相同,符号“\”已经被转意了。例如:

    路径是非法的,系统c:\jbuilder3\java\bin
    不会识别,正确的应该为
    c:\jbilder3\java\bin
    或者直接使用反斜杠/来作为路径分隔符。如c:/jbilder3/java/bin

文件夹处理

list方法用于列出一个目录中所有的文件或与某个模式相匹配的文件。

列出目录中与某种模式相匹配的文件:
public String[] list(FilenameFilter filter);
在接口 FilenameFilter中定义的方法只有:
boolean accept(File dir,String name);

利用流进行文件I/O处理

  1. Byte流(字节流)文件的读取
    我们主要用其中的FileOutputStream和FileInputStream类,它们的父类为InputStream和OutputStream。

  2. Character流(字符流)文件的读取
    输入/输出类的父类为Reader、Writer。

  3. 二进制数据流的文件读取、

    如果要读取与机器无关的基本数据类型的数据,如整型或浮点型的二进制数,就要用到二进制数据文件流DataInputStream、DataOutputStream。实际使用中,类DataInputStream和DataOutputStream必须和一个输入类(InputStream)或输出类(OutputStream)联接起来,不能直接用文件名或文件对象(File)对其直接初始化。

  4. 随机访问文件的读取

    对于InputStream/OutputStream、Reader/Writer类来说,它们都是顺序访问流,只能进行顺序读写。而所谓随机读写,是指读写完上一个字节后,不只能读写其后继的字节,还可以读写文件中任意的字节,就好象文件中有一个随意移动的指针一样。

    Java语言提供了类RandomAccessFile来进行随机文件的读取。在生成一个RandomAccessFile对象时,不仅要说明文件对象或文件名,同时还需指明访问模式,即“只读方式”(r)或“读写方式”(rw),这类似于C/C++中的fopen() 函数。

通过类BufferedReader对文件实现按行读取,达到一行一行输出的目的。(字符流)

读取文件信息,保存到控制台。

import java.io.*;

public class ByteInputOutStream {

    public static void main(String[] args) throws IOException {
        FileReader fr=new FileReader("d:/Java/test.txt");//新建一个要读的文件对象
        BufferedReader br=new BufferedReader(fr);//创建一个BufferedReader对象
        String line=br.readLine();//用此方法,实现对文件中的内容一行一行读取
        while(line!=null){
            System.out.println(line);
            line=br.readLine();//指针指向下一个位置,如果有的话,不为空;没有的话,为空。
        }
        br.close();
    }

        }

结果为:
这里写图片描述

在控制台输入字符串,然后将其保存到磁盘中

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

public class ByteInputOutStream {
    
    

    public static void main(String[] args) throws IOException {
    Scanner sc =new Scanner(System.in);
        String str=sc.nextLine();
        TextToFile("D://Java/test5", str);


        }     
    /** 
     * 传入文件名以及字符串, 将字符串信息保存到文件中 
     *  
     * @param strFilename 
     * @param strBuffer 
     */ 
    public static void TextToFile(final String strFilename, final String strBuffer)  
    {  
        try  
        {      
            // 创建文件对象  
            File fileText = new File(strFilename);  
            // 向文件写入对象写入信息  
            FileWriter fileWriter = new FileWriter(fileText);  

            // 写文件        
            fileWriter.write(strBuffer);  
            // 关闭  
            fileWriter.close();  
            System.out.println("执行成功");
        }  
        catch (IOException e)  
        {  

            e.printStackTrace();  
        } 
    }

}

结果为:
这里写图片描述
此时,可以查看D://Java/test5中的信息,就是控制台输入的字符串。

文件的复制:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
    
    
    public static void main(String[] args) throws IOException {
    File file = new File("D://Java/ChartRoom.rar");
            File fileCopy = new File("D://Java/ChartRoom-copy.rar");
            if(!fileCopy.exists())
                fileCopy.createNewFile();
            try(FileInputStream fileInputStream = new FileInputStream(file); FileOutputStream fileOutputStream = new FileOutputStream(fileCopy)){
                    /*BufferedInputStream in = new BufferedInputStream(fileInputStream);//这个缓存区可以不定义
                    BufferedOutputStream out = new BufferedOutputStream(fileOutputStream);*/

                    byte[] b=new byte[1024];//如果不定义这个变量,直接调用无参的read()方法,将会读取的非常慢,因为他是一个一个比特位读的,而定义了此变量后,他每次是以1024个比特位读的,比较快。
                    int read=0;
                    while((read=fileInputStream.read(b))!=-1){
   
   每次都读取b中的内容,如果b中有内容,则输出,反之则为-1
                        fileOutputStream.write(b);//如果将b改为read,则只能复制1KB
                    }
                    fileOutputStream.flush();
                    System.out.println("复制成功");
                }catch(Exception e){

                }
            }

    }
    结果为:
        复制成功

序列化和反序列化

Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。

2.为什么需要序列化与反序列化

我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的。如何做到呢?这就需要Java序列化与反序列化了。换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象。

当我们明晰了为什么需要Java序列化和反序列化后,我们很自然地会想Java序列化的好处。其好处一是实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里),二是,利用序列化实现远程通信,即在网络上传送对象的字节序列。

猜你喜欢

转载自blog.csdn.net/qq_39650208/article/details/76736372