查看api文档(自己一定要动手)
InputStream 有read方法,一次读取一个字节,OutputStream的write方法一次写一个int。发现这两个类都是抽象类。意味着不能创建对象,那么需要找到具体的子类来使用。
通过查看api文档,找到了FileInputStream类,该类正是我们体验Io流的一个输入流。
实现;显示指定文件内容。
明确使用流,使用哪一类流?使用输入流,FileInputStream
1:打开流(即创建流)
2:通过流读取内容
3:用完后,关闭流资源
显然流是Java中的一类对象,要打开流其实就是创建具体流的对象,由于是读取硬盘上的文件,应该使用输入流。所以找到了InputStream类,但是InputStream是抽象类,需要使用它的具体实现类来创建对象就是FileInputStream。通过new 调用FileInputStream 的构造方法来创建对象。发现FileInputStream的构造方法需要指定文件的来源。查看构造方法,可以接受字符串也可以接受File对象。我们通过构建File对象指定文件路径。
使用流就像使用水管一样,要打开就要关闭。所以打开流和关闭流的动作是比不可少的。如何关闭流?使用close方法即可,当完成流的读写时,应该通过调用close方法来关闭它,这个方法会释放掉十分有限的操作系统资源.如果一个应用程序打开了过多的流而没有关闭它们,那么系统资源将被耗尽.
如何通过流读取内容?
查找api文档通过read方法,查看该方法,发现有返回值,并且是int类型的,该方法一次读取一个字节(byte)
1.1. 输入流读取方式1:
read方法()
一次读取一个字节,读到文件末尾返回-1.
仔细查看api文档发现read方法如果读到文件的末尾会返回-1。那么就可以通过read方法的返回值是否是-1来控制我们的循环读取。
* 根据read方法返回值的特性,如果独到文件的末尾返回-1,如果不为-1就继续向下读。
private
static
void
showContent(String path)
throws
IOException {
//
打开流
FileInputStream fis =
new
FileInputStream(path);
int
len =
fis.read();
while
(len != -1
) {
System.out.print((
char
)len);
len
=
fis.read();
//
使用完关闭流
fis.close();
我们习惯这样写:
* 根据read方法返回值的特性,如果独到文件的末尾返回-1,如果不为-1就继续向下读。
private
static
void
showContent(String path)
throws
IOException {
//
打开流
FileInputStream fis =
new
FileInputStream(path);
int
len;
while
((len = fis.read()) != -1
) {
System.out.print((
char
) len);
//
使用完关闭流
fis.close();
1.2. 输入流读取方式2:
使用read(byte[] b) 方法。使用缓冲区(关键是缓冲区大小的确定)
使用read方法的时候,流需要读一次就处理一次,可以将读到的数据装入到字节数组中,一次性的操作数组,可以提高效率。
问题
1:
缓冲区大小
那么字节数组如何定义?定义多大?
可以尝试初始化长度为5的byte数组。通过read方法,往byte数组中存内容
那么该read方法返回的是往数组中存了多少字节。
* 使用字节数组存储读到的数据
private
static
void
showContent2(String path)
throws
IOException {
//
打开流
FileInputStream fis =
new
FileInputStream(path);
//
通过流读取内容
byte
[] byt =
new
byte
[5
];
int
len =
fis.read(byt);
for
(
int
i = 0; i < byt.length; i++
) {
System.out.print((
char
) byt[i]);
//
使用完关闭流
fis.close();
问题
1:
缓冲区太小
:
数据读取不完.
测试发现问题,由于数组太小,只装了5个字节。而文本的字节大于数组的长度。那么很显然可以将数组的长度定义大一些。例如1024个。
* 使用字节数组存储读到的数据
private
static
void
showContent2(String path)
throws
IOException {
//
打开流
FileInputStream fis =
new
FileInputStream(path);
//
通过流读取内容
byte
[] byt =
new
byte
[1024
];
int
len =
fis.read(byt);
for
(
int
i = 0; i < byt.length; i++
) {
System.out.print(byt[i]);
//
使用完关闭流
fis.close();
问题三
:
缓冲区有默认值
.
测试,打印的效果打印出了很多0,因为数组数组有默认初始化值,所以,我们将数组的数据全部都遍历和出来.现在需要的是取出数组中的部分数据.需要将循环条件修改仔细查看api文档。发现该方法read(byte[] b)返回的是往数组中存入了多少个字节。就是数组实际存储的数据个数。
* 使用字节数组存储读到的数据
private
static
void
showContent2(String path)
throws
IOException {
//
打开流
FileInputStream fis =
new
FileInputStream(path);
//
通过流读取内容
byte
[] byt =
new
byte
[1024
];
int
len =
fis.read(byt);
for
(
int
i = 0; i <len; i++
) {
System.out.print(byt[i]);
//
使用完关闭流
fis.close();
问题一:为什么打印的不是字母而是数字,
是字母对应的码值。
如何显示字符,强转为char即可
问题二:注意:回车和换行的问题。
windows的换车和换行是"\r\n" 对应码表是13和10 。
1.3. 输入流读取方式3:
使用read(byte[] b,int off,int len)
查看api文档,
b显然是一个byte类型数组,当做容器来使用
off,是指定从数组的什么位置开始存字节
len,希望读多少个
其实就是把数组的一部分当做流的容器来使用。告诉容器,从什么地方开始装要装多少。
* 把数组的一部分当做流的容器来使用
* read(byte[] b,int off,int len)
private
static
void
showContent3(String path)
throws
IOException {
//
打开流
FileInputStream fis =
new
FileInputStream(path);
//
通过流读取内容
byte
[] byt =
new
byte
[1024
];
//
从什么地方开始存读到的数据
int
start = 5
;
//
希望最多读多少个(如果是流的末尾,流中没有足够数据)
int
maxLen = 6
;
//
实际存放了多少个
int
len =
fis.read(byt, start, maxLen);
for
(
int
i = start; i < start + maxLen; i++
) {
System.out.print((
char
) byt[i]);
//
使用完关闭流
fis.close();
需求2:测试skip方法
通过Io流,读取"c:/a.txt"文件中的第9个字节到最后所有的内容并在控制台显示出来。
分析:其实就是要跳过文件中的一部分字节,需要查找API文档。可以使用skip方法skip(long n),参数跟的是要跳过的字节数。
我们要从第9个开始读,那么要跳过前8个即可。
* skip方法
private
static
void
showContent4(String path)
throws
IOException {
//
打开流
FileInputStream fis =
new
FileInputStream(path);
//
通过流读取内容
byte
[] byt =
new
byte
[1024
];
fis.skip(
8
);
int
len =
fis.read(byt);
System.out.println(len);
System.out.println(
"**********"
);
for
(
int
i = 0; i < len; i++
) {
System.out.println((
char
) byt[i]);
//
使用完关闭流
fis.close();
1.4. 输入流读取方式4:
使用缓冲(提高效率),并循环读取(读完所有内容).
总结:读完文件的所有内容。很显然可以使用普通的read方法,一次读一个字节直到读到文件末尾。为了提高效率可以使用read(byte[] byt);方法就是所谓的使用缓冲提高效率。我们可以读取大文本数据测试(大于1K的文本文件.)
* 使用字节数组当缓冲
private
static
void
showContent5(String path)
throws
IOException {
FileInputStream fis
=
new
FileInputStream(path);
byte
[] byt =
new
byte
[1024
];
int
len =
fis.read(byt);
System.out.println(len);
String buffer
=
new
String(byt, 0
, len);
System.out.print(buffer);
注意:如何将字节数组转成字符串? 可以通过创建字符串对象即可。
发现:一旦数据超过1024个字节,数组就存储不下。
如何将文件的剩余内容读完?
我们可以通过通过循环保证文件读取完。
* 使用字节数组当缓冲
private
static
void
showContent7(String path)
throws
IOException {
FileInputStream fis
=
new
FileInputStream(path);
byte
[] byt =
new
byte
[1024
];
int
len = 0
;
while
((len = fis.read(byt)) != -1
) {
System.out.println(
new
String(byt, 0
, len));