目录
前言
文件可以分为文本或者二进制的。可以使用文本编辑器,比如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 。