1 字节输出流:OutputStream
1.1 基本概念
-
在程序中所有的数据都是以流的方式传输或保存的。
-
在 Java 中 IO 操作的主要流程:
(1)使用 File 类打开一个文件。
(2)通过字节流或字符流的子类指定输出位置
(3)进行读/写操作。
(4)关闭输入输出。 -
字节流主要是操作 byte 类型数据,以 byte 数组为准,主要操作类就是 字节输出流:OutputStream 和 字节输入流: InputStream。
-
OutputStream 是一个抽象类,如果想要使用此类的话,首先必须通过子类实列化对象。如果现在要操作的是一个文件,则可以使用 FileOutputStream 类,通过向上转型之后,可以为 OutputStream 实列化。
1.2 字节输出流基本操作
1. 向文件写入数据
实列1代码:
package self.learn.javaio;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class IoPractices {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// 向文件中写入字符串
//String path = "D:"+File.separator+"SVN"+File.separator+"outPutStream.txt";
String path = "D:\\SVN\\outPutStream.txt";
// 1. 使用 File 类找到一个文件
File file = new File(path);
// 2. 通过子类实例化父类对象
OutputStream output = null;
output = new FileOutputStream(file); // 通过对象多态性进行实例化
// 3. 进行写操作
String str = "Hello OutputStream!"; // 准备一个字符串
// OutputStream 主要是操作 byte 类数据,所以把字符串转换为 byte 数组
byte b[] = str.getBytes();
output.write(b); // 将内容输出,保存到文件
// 将内容一个字节一个字节写入文件
// for(int i = 0; i < b.length; i++) {
// output.write(b[i]);
// }
// 第四步:关闭输出流
output.close();
}
}
运行结果截图:
如果在操作之前文件不存在,则操作后自动创建并写入内容。
实列2代码(通过循环将内容一个字节一个字节写入文件):
package self.learn.javaio;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class IoPractices {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// 向文件中写入字符串
//String path = "D:"+File.separator+"SVN"+File.separator+"outPutStream.txt";
String path = "D:\\SVN\\outPutStream.txt";
// 1. 使用 File 类找到一个文件
File file = new File(path);
// 2. 通过子类实例化父类对象
OutputStream output = null;
output = new FileOutputStream(file); // 通过对象多态性进行实例化
// 3. 进行写操作
String str = "Hello OutputStream! Java 真好!"; // 准备一个字符串
// OutputStream 主要是操作 byte 类数据,所以把字符串转换为 byte 数组
byte b[] = str.getBytes();
//output.write(b); // 将内容输出,保存到文件
//通过循环将内容一个字节一个字节写入文件
for(int i = 0; i < b.length; i++) {
output.write(b[i]);
}
// 第四步:关闭输出流
output.close();
}
}
运行结果截图:
2. 追加新内容
之前所有的操作,如果重新执行程序,则肯定会覆盖文件中的已有内容,那么此时可以通过 FileOutputSream 类的另一种构造方法进行实例化,向文件中追加内容。
实列3代码:
package self.learn.javaio;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class IoPractices {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// 向文件中写入字符串
//String path = "D:"+File.separator+"SVN"+File.separator+"outPutStream.txt";
String path = "D:\\SVN\\outPutStream.txt";
// 1. 使用 File 类找到一个文件
File file = new File(path);
// 2. 通过子类实例化父类对象
OutputStream output = null;
// 通过对象多态性进行实例化, 设置为 true 表示在文件末尾追加内容
output = new FileOutputStream(file,true);
// 3. 进行写操作
String str = "我要追加内容!"; // 准备一个字符串
// OutputStream 主要是操作 byte 类数据,所以把字符串转换为 byte 数组
byte b[] = str.getBytes();
//output.write(b); // 将内容输出,保存到文件
//通过循环将内容一个字节一个字节写入文件
for(int i = 0; i < b.length; i++) {
output.write(b[i]);
}
// 第四步:关闭输出流
output.close();
}
}
运行结果截图:
知识小补充:增加换行(使用 “\r\n” 增加换行)
实列4代码:
package self.learn.javaio;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class IoPractices {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// 向文件中写入字符串
//String path = "D:"+File.separator+"SVN"+File.separator+"outPutStream.txt";
String path = "D:\\SVN\\outPutStream.txt";
// 1. 使用 File 类找到一个文件
File file = new File(path);
// 2. 通过子类实例化父类对象
OutputStream output = null;
// 通过对象多态性进行实例化, 设置为 true 表示在文件末尾追加内容
output = new FileOutputStream(file,true);
// 3. 进行写操作 " \r ":归位 、" \n ":换行
// 使用 "\r\n" 增加换行
String str = "\r\n 不好意思我要再这里换行!"; // 准备一个字符串
// OutputStream 主要是操作 byte 类数据,所以把字符串转换为 byte 数组
byte b[] = str.getBytes();
//output.write(b); // 将内容输出,保存到文件
//通过循环将内容一个字节一个字节写入文件
for(int i = 0; i < b.length; i++) {
output.write(b[i]);
}
// 第四步:关闭输出流
output.close();
}
}
运行结果截图:
提示: 使用字节输出流 OutputStream ,当文件不存在时在操作后会自动创建。
2 字节输入流:InputStream
2.1 基本概念
- 通过 InputStream 类从文件中把内容读取过来。 InputStream 本身也是一个抽象类,必须依靠其子类,如果现在是从文件中读取进来,子类肯定是 FileInputStream 类。
2.2 基本操作
1. 读取文件内容
实列5代码:
package self.learn.javaio;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class IoPractices {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// 向文件中写入字符串
//String path = "D:"+File.separator+"SVN"+File.separator+"outPutStream.txt";
String path = "D:\\SVN\\outPutStream.txt";
// 1. 使用 File 类找到一个文件
File file = new File(path);
// 2. 通过子类实例化父类对象
InputStream input = null;
// 通过对象多态性进行实例化
input = new FileInputStream(file);
// 3. 进行读操作
byte b[] = new byte[1024];
input.read(b); // 把内容读取出,内容读到 byte 数组中
input.close();
// 把数组变为字符串输出
System.out.println("内容为:\n"+new String(b));
}
}
运行结果截图:
知识小补充:
开辟 byte 数组大小为1024 字节,而实际内容只有 94 字节,也就是说存在了 930 个字节的空白空间,在将 byte 转换为字符串的时候也将这 930 个字节的空间空间转换为字符串了
实列6代码:
package self.learn.javaio;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class IoPractices {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// 向文件中写入字符串
//String path = "D:"+File.separator+"SVN"+File.separator+"outPutStream.txt";
String path = "D:\\SVN\\outPutStream.txt";
// 1. 使用 File 类找到一个文件
File file = new File(path);
// 2. 通过子类实例化父类对象
InputStream input = null;
// 通过对象多态性进行实例化
input = new FileInputStream(file);
// 3. 进行读操作
byte b[] = new byte[1024];
int len = input.read(b); // 把内容读取出,内容读到 byte 数组中
input.close();
System.out.println("读取过来的内容有:"+len+" 个字节");
// 把数组变为字符串输出,这里只转换了 byte 数组中实际有内容的部分
System.out.println("内容为:\n"+new String(b,0, len));
}
}
运行结果截图:
知识小补充:在使用 FileInputStream 读取文件是如果指定路径不存在,则程序会出现异常。
2. 读取文件内容,根据文件大小创建 byte 数组
这样做的好处是按需开辟空间。利用 File 类中存在一个 length(), 此方法就可以取得文件的大小。
实列7代码:
package self.learn.javaio;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class IoPractices {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// 向文件中写入字符串
//String path = "D:"+File.separator+"SVN"+File.separator+"outPutStream.txt";
String path = "D:\\SVN\\outPutStream.txt";
// 1. 使用 File 类找到一个文件
File file = new File(path);
// 2. 通过子类实例化父类对象
InputStream input = null;
// 通过对象多态性进行实例化
input = new FileInputStream(file);
// 3. 进行读操作
// 数组大小由文件决定,但是文件内容不能过大
byte b[] = new byte[(int)file.length()];
int len = input.read(b); // 把内容读取出,内容读到 byte 数组中
input.close();
System.out.println("读取过来的内容有:"+len+" 个字节");
// 把数组变为字符串输出,这里只转换了 byte 数组中实际有内容的部分
System.out.println("内容为:\n"+new String(b));
}
}
运行结果截图:
2. 通过循环把文件中的内容一个字节一个字节的读取过来(使用 read( ) 函数循环读取)
实列8代码:
package self.learn.javaio;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class IoPractices {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// 向文件中写入字符串
//String path = "D:"+File.separator+"SVN"+File.separator+"outPutStream.txt";
String path = "D:\\SVN\\outPutStream.txt";
// 1. 使用 File 类找到一个文件
File file = new File(path);
// 2. 通过子类实例化父类对象
InputStream input = null;
// 通过对象多态性进行实例化
input = new FileInputStream(file);
// 3. 进行读操作
// 数组大小由文件决定,但是文件内容不能过大
byte b[] = new byte[(int)file.length()];
//int len = input.read(b); // 把内容读取出,内容读到 byte 数组中
for(int i = 0; i < b.length; i++) {
b[i] = (byte)input.read();
}
input.close();
// 把数组变为字符串输出,这里只转换了 byte 数组中实际有内容的部分
System.out.println("内容为:\n"+new String(b));
}
}
运行结果截图:
3. 上面的程序是在明确知道了具体数组大小的前提下展开的,如果此时不知道要输入的内容有多大,则只能通过判断是否读到文件末尾的方式来读取文件。
实列9代码:
package self.learn.javaio;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class IoPractices {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// 向文件中写入字符串
//String path = "D:"+File.separator+"SVN"+File.separator+"outPutStream.txt";
String path = "D:\\SVN\\outPutStream.txt";
// 1. 使用 File 类找到一个文件
File file = new File(path);
// 2. 通过子类实例化父类对象
InputStream input = null;
// 通过对象多态性进行实例化
input = new FileInputStream(file);
// 3. 进行读操作
byte b[] = new byte[1024];
int len = 0; // 用于记录读取的数据个数
int temp = 0; // 接收读取的每一个内容
while((temp = input.read()) != -1) {
// 将每次读取的内容 给 temp 变量,如果 temp 的值不是 -1, 则表示文件没有读完
b[len] = (byte)temp;
len++;
}
input.close();
// 把数组变为字符串输出,这里只转换了 byte 数组中实际有内容的部分
System.out.println("内容为:\n"+new String(b));
}
}
运行结果截图:
提示: 文件读到末尾了,则返回的内容为 - 1。只有当输入流的内容已经读到底,才会返回这个数字,可以通过这个数字判断输入流中是否还有其他内容。