Java IO 是一套Java用来读写数据(输入和输出)的API。大部分程序都要处理一些输入,并由输入产生一些输出。Java为此提供了java.io
包,主要涉及文件,网络数据流,内存缓冲等的输入输出。
Java IO中的一个核心概念是流(Stream),从外部(包括磁盘文件、键盘、网络套接字)读入到内存中的数据序列称为输入流,从内存写入到外部设备的数据序列称为输出流。
流中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:
提示
在最底层,所有的输入/输出都是字节形式的。基于字符的流只为处理字符提供方便有效的方法。
字节流的最顶层是两个抽象类:InputStream
和OutputStream
,其他关于处理字节的类都是它们的子类,这些子类对不同的外设进行处理,例如磁盘文件,网络连接,甚至是内存缓冲区。
以下为常见字节流处理类
类 | 功能 |
---|---|
BufferedInputStream | 缓冲输入流 |
BufferedOutputStream | 缓冲输出流 |
ByteArrayInputStream | 从字节数组读取的输入流 |
ByteArrayOutputStream | 向字节数组写入的输出流 |
FileInputStream | 读取文件的输入流 |
FileOutputStream | 写文件的输出流 |
PrintStream | 包含print() 和 println() 方法的输出流 |
InputStream | 描述输入流的抽象类 |
OutputStream | 描述输出流的抽象类 |
抽象类InputStream
和 OutputStream
中定义两个关键的抽象方法read()
和write()
,它们分别对数据的字节进行读写,其子类重载完成特定输入输出方式的对应实现。
下面的代码通过FileInoutStream
和FileOutputStream
来完成文件内容的拷贝:
package com.tianmaying;
import java.io.*;
public class CopyFileByte {
public static void main(String args[]) throws IOException
{
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("input.txt");
out = new FileOutputStream("output.txt");
int c;
while ((c = in.read()) != -1) { // 返回-1 表示达到文件结尾
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
字节流的每次操作都是一个数据单位——字节。假如input.txt文件中包含“Hello world”,那么它将复制完'H'之后,再复制'e',接下来复制'l',直到其结束。in.read()
每次从输入流中读取一个字节,如果达到文件末尾就返回-1
。注意使用完输入输出流,一定调用close()
方法将其关闭。
Java 字符流用于处理16位 unicode 的输入和输出。字符流的两个顶层抽象类是Reader
和Writer
,分别定义了关键方法read()
和write()
,表示对字符的读写。
类 | 功能 |
---|---|
BufferedReader | 缓冲输入字符流 |
BufferedWriter | 缓冲输出字符流 |
CharArrayReader | 从字节数组读取的字符输入流 |
CharArrayWriter | 向字节数组写入的字符输出流 |
FileReader | 读取文件的字符输入流 |
FileWriter | 写文件的字符输出流 |
Reader | 描述字符输入流的抽象类 |
Writer | 描述字符输出流的抽象类 |
用字符流的方式进行文件内容拷贝的代码如下:
package com.tianmaying;
import java.io.*;
public class CopyFileCharacter {
public static void main(String args[]) throws IOException
{
FileReader in = null;
FileWriter out = null;
try {
in = new FileReader("input.txt");
out = new FileWriter("output.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
这里使用的FileReader
和FileWriter
,它们操作的最小单位是一个字符16 bits,而FileInputStream
和FileOutputStream
最小单位则是一个字节8 bits.
所有的编程语言都提供了对标准 I/O 流的支持,即用户可以从键盘上进行输入,并且从控制台屏幕上输出。Java提供了以下的三种标准流:
System.in
,其类型是InputStream
System.out
,其类型是PrintStream
System.err
,类型和System.out
相同是PrintStream
提示
这些流都有默认的设备(键盘和屏幕),但它们可以重定向到任何兼容的输入/输出设备。
下面的程序通过创建一个InputStreamReader
来读标准输入流直到用户输入字符 "q":
package com.tianmaying;
import java.io.*;
class ConsoleInOut {
public static void main(String args[])throws IOException{
InputStreamReader isr = null;
try {
isr = new InputStreamReader(System.in);
System.out.println("Enter characters, 'q' to quit.");
char c;
do {
c = (char) isr.read();
System.out.println(c);
} while(c != 'q');
}finally {
if (isr != null) {
isr.close();
}
}
}
}
如果我们在控制台中输入tianmaying!
,则控制台的输入如下:
从控制台读入单个字符我们用了read()
方法,读入字符串则可以使用readLine()
方法,该方法返回的是String
类型的字符串对象。
回顾我们已经学习过的Scanner
,创建Scanner
对象时需要用System.in
作为它的参数, Scanner
从System.in
取得用户输入的内容后,进一步提供了更易于我们调用的方法,如:
next()
:取得一个字符串hasNext()
:是否还有输入nextInt()
:将取得的字符串转换成int
类型的整数nextFloat()
:将取得的字符串转换成float
型nextBoolean()
:将取得的字符串转换成boolean
型使用Scanner
非常方便,但也有不足。Scanner取得输入的依据是空格符,包括空格键、Tab键和回车键等。当按下这些键时,Scanner
就会返回下一个输入。因此当你输入的内容中间包括空格时,显然使用Scanner
不能完整的获得你输入的字符串。
文件处理最常用的两个流是FileInputStream
和FileOutputStream
。
对于FileInputStream
,可以以文件名的字符串为参数来创建一个输入流对象去读文件:
也可以以一个文件对象作为参数来去创建一个输入流对象去读文件,首先我们需要创建一个File
文件对象
对于FileOutputStream
类似。
下面的代码将产生test.txt文件并且以二进制格式写入给出的数字,并在屏幕输出。
package com.tianmaying;
import java.io.*;
public class fileStreamTest{
public static void main(String args[]){
try{
byte bWrite [] = {10,20,30,40,50};
OutputStream os = new FileOutputStream("test.txt");
for(int x = 0; x < bWrite.length ; x++){
os.write( bWrite[x] ); // writes the bytes
}
os.close();
InputStream is = new FileInputStream("test.txt");
int size = is.available();
for(int i = 0; i< size; i++){
System.out.print((char)is.read() + " ");
}
is.close();
} catch(IOException e){
System.out.print("IOException");
}
}
}
上一节中创建文件输入输出流时,我们用到了File
类。File
类用于进行文件(以及目录)的相关操作,位于java.io
包中。对一个文件进行操作,可以创建一个File
对象:
File file = new File("input.txt"); //文件位于当前目录下
File file = new File("D:/java","input.txt"); //文件位于/home/user目录下
File
类主要的的方法包括:
方法 | 功能 |
---|---|
exists() | 判断文件或目录是否存在 |
mkdir() | 创建目录 |
mkdirs() | 创建目录以及上级目录 |
isFile() | 判断是否为文件 |
isDirectory() | 判断是否为目录 |
delete() | 删除文件 |
getPath() | 获取文件或者目录的路径 |
list() | 将目录中所有文件名保存在字符串数组中返回 |
canRead() | 判断文件是否可读 |
create() | 创建文件 |
下面的代码展示了一些File
的常见操作:
package com.tianmaying;
import java.io.*;
public class TestAbstract {
public static void main(String args[]) throws IOException {
File dir = new File("D:/java");
File file1 = new File(dir, "fileTest001.txt");
File file2 = new File(dir, "fileTest002.java");
if (!dir.exists())
dir.mkdir();
if (!file1.exists())
file1.createNewFile();
if (!file2.exists())
file2.createNewFile();
System.out.println("file1's AbsolutePath= " + file1.getAbsolutePath());
System.out.println("file2's AbsolutePath= " + file2.getAbsolutePath());
System.out.println("file1 Canread=" + file1.canRead());
System.out.println("file1's len= " + file1.length());
String[] fileList = dir.list();
System.out.println("there are " + fileList.length + " file(s) in D:/java");
}
}
输出如下:
登录发表评论 登录 注册
read作用是返回字节流的十进制整数他这里讲得很不全
file这一节中,第一段代码中的第二句,注释有误
File file = new File("D:/java","input.txt"); //文件位于/home/user目录下
应该为“位于D:/java”目录下
字节流这一节,代码上方的有错误
下面的代码通过
FileInoutStream
和FileOutputStream
来完成文件内容的拷贝:FileInoutStream
写错了下面的代码通过
FileInoutStream
和FileOutputStream
来完成文件内容的拷贝:这里
FileInoutStream
应该是FileInputStream ??
这章讲File类的创建文件的create()方法写错了吧应该是createNewFile()吧 >_<
public static void main(String args[])throws IOException{
这里为什么是(String args[])而不是(String[] args)呢?
下面的代码通过
FileInoutStream
和FileOutputStream
来完成文件内容的拷贝这里应该是FileInputStream
返回-1 表示达到文件结尾,只能-1
16课,文件的输入输出 这一节 最后的输出什么意思? 输出结果为 “ ( 2 ” 是个什么东西?
-1是什么意思?-2,-3,-4都可以吗?1,2,3,...也可以吗?还是只能-1
作业问题在答疑区或者代码区提问哈
读取文件不对
请问这里为什么到-1循环就停了?字节流的话c不是全是0和1么,永远不会等于-1吧?