Java二进制I/O

阅读 21

02-01 21:00

前言

文件可以分为文本或者二进制的。可以使用文本编辑器,比如Windows下的记事本或者UNIX下的vi编辑器,进行处理(读取、创建或者修改)的文件称为文本文件。所有其他文件称为二进制文件。不能使用文本编辑器来读取二进制文件——它们被设计为使用程序来读取。例如,Java 源程序存储在文本文件中,可以使用文本编辑器读取,而Java类文件是二进制文件,由Java虚拟机读取。


一、Java如何处理文本I/O

为了实现I/O操作,需要使用正确的Java I/O类创建对象。这些对象包含从/向文件中读/写数据的方法。例如,要将文本写入一个名为temp.txt的文件中,可以使用PrintWriter类创建一个对象。

例如:

PrintWriter output = new PrintWriter ("temp.txt");

现在可以调用该对象的print方法向文件写入一个字符串。

例如:

output.print("Java 111");

下面的语句来关闭这个文件:

output.close();

Java有许多用于各种目的的I/O类。通常,可以将它们分为输入类和输出类。输入类的含读数据的方法,而输出类包含写数据的方法。Printwriter 是一个输出类的例子,而Scanner 是一个输入类的例子。下面的代码为文件temp.txt创建一个输入对象,并从该文件中读取数据:

Scanner input =new Scanner (new File("temp.txt"));
System.out.println("input.nextLine());

如果文件temp.txt中包含文本“Java 111”,那么Input.nextLine()方法会返回字符串“Java 111”。

输入对象从文件中读取数据流,输出对象将数据流写入文件。输入对象也称为输入流(input stream),输出对象也称为输出流(output stream)。


二、文本I/O与二进制I/O

计算机并不区分二进制文件和文本文件。所有的文件都是以二进制形式来存储的,因此从本质上说,所有的文件都是二进制文件。文本I/0建立在二进制1/0的基础之上,提供了一层抽象用于字符的编码和解码。对于文本I/0而言,编码和解码是自动进行的。在写入字符时,Java 虚拟机会将Unicode码转化为文件特定的编码,而在读取字符时,将文件特定的编码转化为Unicode码。例如,假设使用文本10将字符串"199”写入文件,那么每个字符都会写入文件中。由于字符1的Unicode编码为0x0031,所以会根据文件的编码方案将Unicode码0x0031转化成一个编码。(注意,前缀0x表示十六进制数。)在美国,Windows 系统中文本文件的默认编码方案是ASCII码。字符1的ASCII码是49(十六进制为0x31),而字符9的ASCII码是57(十六进制为0x39)。所以,为了以字符写入199,应该将三个字节0x31、0x39和0x39发送到输出。

总而言之,可以总结成: 字符 =字节+编码 字节 =字符+解码

由于二进制1/0不需要编码和解码,所以比文本I/O高效。二进制文件与主机的编码方案无关,因此是可移植的。任何机器上的Java程序都可以读取Java程序所创建的二进制文件。这就是为什么Java的类文件是二进制文件。Java类文件可以在任何有Java虚拟机的机器上运行。


三、字节流

1、什么是字节

字节(byte,简称 B)是计算机中存储数据的单元,它是一个 8 位的二进制数,是一个很具体的存储空间,一般而言,一个标准英文字母占一个字节位置。我们熟悉的 1KB 等于 1024B。

2、 字节流概述

在计算机中,无论是文本、图片、音频还是视频,所有文件都是以二进制(字节)形式存在的,I/O流中针对字节的输入/输出提供了一系列的流,统称为字节流。

3、InputStream 类(字节输入流)

通过一个代码来看看如何使用输入流:首先在D盘下创建一个hello.txt文件。输入文本Hello Java Hello InputStream。

File file = new File("D://hello.txt");
InputStream fs = new FileInputStream(file);  定义一个文件输入流
byte[] b = new byte[1024];  定义一个字节数组
fs.read(b);  将输入流的数据读入到字节数组
String str = new String(b,"UTF-8");  通过UTF-8码表将字节转换成字符
System.out.println(str);

输出:Hello Java Hello InputStram

4、OutputStream 类(字节输出流)

使用输出流将字符串hello educoder 写入到一个文件中:

String file = "D://test.txt";
 
OutputStream out = new FileOutputStream(file);  创建输出流
 
String str = "hello educoder";
 
byte[] b=str.getBytes();   字符转换成字节
 
out.write(b);  字节写出到文件
 
out.flush();   刷新缓冲区的数据,类似于保存操作

运行这段代码后,打开D盘会发现test.txt文件被创建了,并且文件的内容是hello educoder 。


四、字符流

1、什么是字符

我们想象一下,给你一串二进制码(如 1010),要你来分辨它是什么含义,是代表数字还是字母还是汉字,你能有效的分辨吗?

显然不能,一般来说,我们是比较难以理解一串二进制码代表的含义的,而且一串二进制码是代表什么含义也无法很直观的表示出来。

我们比较好识别的是文字、字母和符号。

所以就有了字符,字符是指计算机中使用的文字和符号,比如1、2、3、A、B、C、~!·#¥%……—*()——+、等等。

2、Reader 类(字符输入流)

Reader类与InputStream类类似,直接上代码:

public static void main(String[] args) throws IOException{
        //创建一个FileReader对象;
 
        Reader reader = new FileReader("/test/a.txt");
 
        for(;;){
        //反复强调read()方法,直到返回-1
 
        int n=reader.read();
 
        if(n==-1){
 
        break();
 }
 
//打印读取到的数据
         System.out.print((char)n);
         }
         //关闭流
         
         reader.close();
}

程序执行结果为:

  1. hello


3、Writer 类 (字符输出流)

Writer 类的常用方法

方法名

方法说

Writer()方法

写入一个字符到输出流

close()方法

用于关闭输出流

flush()方法

将缓冲区的内容真正输出到目的地

由于 Writer 类是抽象类,我们以它的子类 FileWriter 类为例:

public static void main(String[] args) throws IOException{
 
        String s="hello";
        // 创建 FileWriter 对象
 
        try (Writer write=new FileWriter("C:\\Users\\yy\\Desktop\\a.txt")) {
        // 向文件中写入字符流
 
            write.write(s);
 
            write.flush();
        }
    }

运行后,C中会出现此文件,且内容为hello 。

精彩评论(0)

0 0 举报