字节流

IO流概述和分类:

IO流概述:

  1. 1. IO: 输入/输出(Input/Output)
  2. 1. **流**: 是一种抽象概念, 对**数据传输的**总称 . 也就是说数据在设备间的传输称为流, 流的本质是数据传输
  3. 1. IO流就是用来处理设备间数据传输问题的-- 常见的应用: 文件赋值; 文件上传; 文件下载

IO流分类:

  1. 1. 按照数据的流向分类
  2. 1. 输入流: 读数据
  3. 1. 输出流: 写数据
  4. 2. 按照数据类型分类(一般来说, IO流使用数据类型分类)
  5. 1. **字节流 **
  6. 1. 字节输入流 -- FileInputStream
  7. 1. 字节输出流 -- FileOutputStream
  8. 2. **字符流**
  9. 1. 字符输入流
  10. 1. 字符输出流
  11. 3. 区别字节流和字符流,主要是通过windows系统自带的记事本打开, 如果可以进行阅读就是字符流,无法阅读一堆乱码是字节流. 如果不知道使用哪种类型, 统一使用字节流

字节流写数据

字节输入流:

InputStream 类

  1. -- abstract implements Closeable<br /> -- 这个抽象类是表示输入字节流的所有类的超类<br /> -- 该类的所有子类都以(Audio, File, Filter , ByteArray,Object...)InputStream结尾

FileInputStream 类

  1. -- 从文件中的文件获取输入字节<br /> FileOInputStream(String name): <br /> -- 通过打开与实际文件的链接来创建一个FileInputStream 该文件由文件中的路径name命名

字节输出流:

OutputStream 类

  1. -- abstract implements Closeable,Flushable<br /> -- 这个抽象类是表示输出字节流的所有类的超类,输出流接收输出字节并将其发送到某个接收器<br /> -- 该类的所有子类都以(Object, File, Filter , ByteArray...)OutputStream结尾

FileOutputStream 类

— 文件输出流用于将数据写入File
— FileOutputStream(String name): 创建文件输出流以指定的名称写入文件

创建子接输出流对象的三个步骤

  1. 1. 调用系统功能创建文件
  2. 1. 创建字节输出流对象
  3. 1. 让字节输出流对象指向创建好的文件
  4. 1. 添加字节方法void writeint b
  5. 1. 所有和IO相关的操作都要释放资源 使用 void closee

public class FileOutStreamDemo {
_public static void main
(String[] args) throws IOException {
// 创建字节输出流的对象
// 需要写绝对路径
FileOutputStream fos = new FileOutputStream
(“D:\PgProject\test11\test.txt”);
/创建子接输出流对象的三个步骤
ⅰ. 调用系统功能创建文件
ⅱ. 创建字节输出流对象
ⅲ. 让字节输出流对象指向创建好的文件
/
// void write(int b): 该方法是将指定的字节传入文件输出流中
fos.write
(97); // 对应字符a
fos.write
(57); // 对应字符9
fos.write
(55); // 对应字符7
// void close(e) 所有和IO相关的操作都要释放资源
fos.close
(); } }_

字节流写数据的3种方式:

void write(int b) 将指定的字节写入此文件输出流
(一次写一个字节数据)
void write(byte[] b) 将b.length字节从指定的字节数组写入此文件输出流
(一次写一组字节数组)
void write(byte[] b, int off, int len) 将len字节从指定的字节数组开始,从偏移量off开始写入 (一次写一个字节数组的部分数据)

第三种方法的三个参数:

  1. 1. byte[] b 字节数组
  2. 1. int off 偏移量(索引的位置)
  3. 1. int len len字节的长度

public static void main(_String[] args) throws IOException {
// FileOutputStream(String name): 创建文件输出流以指定的名称写入文件
FileOutputStream fos = new FileOutputStream
(“D:\PgProject\test11\test.txt”);
// FileOutputStream该方法底层逻辑是使用匿名内部类 new File(…)
FileOutputStream fos = new FileOutputStream
(new File(“D:\PgProject\test11\test01.txt”));
// FileOutputStream(File file): 创建文件输出流以指定的File对象表示的文件
File file = new File
(“test11\test02.txt”);
FileOutputStream fos1 = new FileOutputStream
(file);
// void write(int b)将指定的字节写入此文件输出流 (一次写一个字节数据)
fos.write
(97);
fos.write
(98);
fos.write
(99);
fos.write
(100);
fos.write
(101);
// void write(byte[] b) 将b.length字节从指定的字节数组写入此文件输出流(一次写一组字节数组)
byte
[] bytes = {97, 98, 99, 100, 101};
// String字符串中使用getBytes()方法可以根据String的字节数组
byte
[] bytes1 = “abcde”.getBytes();
// fos.write(bytes);
fos.write
(bytes1);
// void write(byte[] b, int off, int len)
// 将len字节从指定的字节数组开始,从偏移量off开始写入(一次写一个字节数组的部分数据)
fos.write
(bytes1,0,4); // 从索引0开始写入到索引4的字节
// 释放资源(字节写入一定要使用close())
fos.close
(); }_

字节流写数据的两个问题

字节流写数据如何实现换行?

  1. 1. 每个系统对换行符的识别不同
  2. 1. windows: \r\n
  3. 1. Linux: \n
  4. 1. mac: \r
  5. 2. Idea编译器直接写入"\n".getBytes()获取换行字符

代码实现:
public static void main(_String[] args) throws IOException {
// 创建字节流输出对象
FileOutputStream fos = new FileOutputStream
(“D:\PgProject\test11\test01.txt”);
// 写数据
for
(int i = 0; i < 10; i++) {
fos.write(“hello”.getBytes());
// 写入\n换行字节
fos.write
(“\n”.getBytes()); }
// 释放资源
fos.close
(); }_

字节流写数据如何实现追加写入呢?

  1. 3. public FileOutputStream(String name,boolean append)
  2. 3. 方法解释: 创建文件输出流以指定的名称写入文件。如果第_二个参数为true,则字节将写入文件的末尾而不是开头, 没有写true是默认从开头追加
  3. // public FileOutputStream(String name,boolean append) 对字节流对象添加append为true从末尾追加<br />FileOutputStream fos = new FileOutputStream_(_"D:\\PgProject\\test11\\test01.txt",true_)_;

字节流写数据加异常处理

finally 控制异常

try{…}catch{…}inally{….}:

在异常处理时finally块来执行所有清除操作, 比如IO流中的释放资源
特点: 被finall控制的语句一定会执行,除非JVM退出
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常类的处理代码;
}finally{
执行所有清除操作;
}
代码实现:
// 使用finally来清除所有资源
FileOutputStream fos = null;
try {
_new FileOutputStream
(“D:\PgProject\test11\test02.txt”);
fos.write
(“abcde”.getBytes());
} catch (IOException ioe){
ioe.printStackTrace();
}finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace(); } }_

字节流读数据(一次读一个字节数据)

FileInputStream 类

— 从文件中的文件获取输入字节
FileOInputStream(String name):
— 通过打开与实际文件的链接来创建一个FileInputStream, 该文件由文件中的路径name命名

使用字节输入流读取数据的步骤:

  1. 1. 创建字节输入流对象 FileInputStream
  2. 1. 调用字节输入流对象的读数据方法
  3. 1. 释放资源

public static void main(_String[] args) throws IOException {
// 创建字节输入流对象 FileInputStream(String name)
FileInputStream fis = new FileInputStream
(“D:\PgProject\test11\test.txt”)_;
// 调用字节输入流对象的读取方法
// int read() 从输入流读取一个字节的数据
/int by = fis.read();
// 第一次读取数据
System.out.println(by); // 97
// 读取该字节的字符,使用字节(char)强制转换
System.out.println((char)by); //a
// 第二次读取数据
by = fis.read();
System.out.println(by); // 98
System.out.println((char)by);
// 第三次读取数据
by = fis.read();
System.out.println(by); // 13
// 第四次读取数据,到达文件的末尾为-1
by = fis.read();
System.out.println(by); // -1
/

  1. // 先在外读取一次字节并获取,判断字节是否为-1<br /> /*int by = fis.read();<br /> while (by != -1){<br /> System.out.print((char) by);<br /> // 文件执行过一次read ,必须在执行往下读取的方法<br /> by = fis.read();<br /> }*/<br /> <br /> // 优化上面的循环<br /> /*fis.read(): 读数据<br /> by = fis.read(): 将读取的数据给by赋值<br /> by != -1: 判断读取到的数据是否为-1*/<br /> int by;<br /> while _((_by = fis.read_()) _!= -1_) { _System._out_.print_((_char_) _by_)_; _}<br /> _// 释放资源<br /> fis.close_()_; _}_

案例: 复制文本文件

需求: 把”D:\PgProject\test11\test.txt”的内容复制到模块目录下的”test.txt”中

分析:

  1. 1. 复制文本文件, 其实就是把文本文件的内容从一个文件中读取出来(数据源), 然后写入到另一文件中(目的地)
  2. 1. 数据源: D:\\Test\\test.txt -- 读数据 -- InputStream -- FileInputStream
  3. 1. 目的地: test11\\test.txt -- 写数据 -- OutputStream -- FileOutputStream

思路:

  1. 1. 根据数据源创建字节输入流对象
  2. 1. 根据目的地创建字节输出流对象
  3. 1. 读写数据, 复制文本文件(一次读取一个字节, 一次写入一个字节)
  4. 1. 释放资源

代码实现:
public class CopyTxtDemo {
_public static void main
(String[] args) throws IOException {
// 1. 根据数据源创建字节输入流对象
FileOutputStream fos = new FileOutputStream
(“D:\Test\test.txt”);
// 2. 根据目的地创建字节输出流对象
FileInputStream fis = new FileInputStream
(“D:\PgProject\test11\test.txt”);
// 3. 读写数据, 复制文本文件(一次读取一个字节, 一次写入一个字节)
int by;
while
((by = fis.read()) != 1) { fos.write(by); }
// 4. 释放资源
fos.close
();
fis.close
(); } }_

字节流读数据(一次读一个数组数据)

需求: 把文件fos.txt中的内容读取出来在控制台输出

使用字节输入流读取数据的步骤:

  1. 1. 创建字节输入流对象 FileInputStream
  2. 1. 调用字节输入流对象的读数据方法
  3. 1. 释放资源

public class FileOutStream05 {
_public static void main
(String[] args) throws IOException {
// 1. 创建字节输入流对象 FileInputStream
FileInputStream fis = new FileInputStream
(“D:\PgProject\test11\test.txt”);
// 2. 调用字节输入流对象的读数据方法
// int read(byte[] b); 从该输入流读取最多b.length个字节的数据到一个字节数组中
// 定义一组字节
/ byte[] bys = new byte[5];
// 第一次读取数据
int len = fis.read(bys);
System.out.println(len); // 5
// 使用String类中的String(byte[] bytes)转换字符
System.out.println(new String(bys)); // hello
// 第二次读取数据
len = fis.read(bys);
System.out.println(len); // 5
System.out.println(new String(bys,0,len)); // \r\n wor
// 第三次读取数据
len = fis.read(bys);
System.out.println(len); // 4
// String (byte[] bytes, int offset, int length) — 只转字节数组的部分
System.out.println(new String(bys,0,len)); //ld \r\n r
/
/ hello \r\n
world \r\n
第一次: hello
第二次: \r\n wor
第三次: ld \r\n r
第四次读取数据: -1 -1
/
byte
[] bytes = new byte[1024]; // 定义字节数组一般使用1024以及其整数倍
int len;
while
((len= fis.read(bytes)) != -1){ System._out.println(_new String(bytes,0,len)); }
// 3. 释放资源
fis.close
(); } }_

案例: 复制图片

需求: 把”C:\Users\76411\Desktop\中国石化标识.png”复制到模块目录下的”中国石化标识.png”
思路:

  1. 1. 根据数据源创建字节输入流对象
  2. 1. 根据目的地创建字节输出流对象
  3. 1. 读写数据, 复制文本文件(一次读取一个字节, 一次写入一个字节)
  4. 1. 释放资源

public class CopyPngDemo {
_public static void main
(String[] args) throws IOException {
// 根据数据源创建字节输入流对象
FileInputStream fis = new FileInputStream
(“C:\Users\76411\Desktop\中国石化标识.jpg”);
// 根据目的地创建输出流对象
FileOutputStream fos = new FileOutputStream
(“D:\PgProject\test11\中国石化标识.jpg”);
// 读取数据,复制图片(一次读取一个字节数组,一次写入一个字节数组)
byte
[] bytes = new byte[1024];
int len;
while
((len= fis.read(bytes)) != -1) { System._out.println(_new String(bytes, 0, len)); }
// 释放资源
fis.close
();
fos.close
(); } }_

字节缓冲流

BufferedOutputStream类

BufferedOutputStream的爷爷类是OutputStream是字节输出流
该类实现缓冲输出流, 通过设置这样的输出流, 应用程序可以向底层输出流入字节。而不必为写入的每个字节导致底层系统的调用
FileOutputStream这个类每次写入数据需要调用系统底层,设置该类为缓冲区,可以一次性写入数据则不需要反复调用底层系统
构造方法:(参数为字节输出流—new FileOutputStream)
BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,将数据写入指定的底层输出流

BufferedInputStream类

BufferedInputStream的爷爷类是InputStream是字节输入流
该类是创建BufferedInputStream将创建一个内部缓冲区数组, 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流重新,一次填充很多字节
构造方法:(参数为字节输入流 — new FileInputStream)
BufferedInputStream(InputStream in) 创建一个BufferedInputStream并保存其参数,输入流in供以后使用

为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?
— 字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象操作
public static void main(_String[] args) throws IOException {
// 创建字节缓冲输出流,参数为输出字节流,对象为输出流
// FileOutputStream fos = new FileOutputStream(“D:\PgProject\test11\test.txt”);
// 创建BufferedOutputStream(OutputStream out) 对象,参数为定义的fos
//BufferedOutputStream bos = new BufferedOutputStream(fos);
// 合并创建,使用匿名内部类直接创建FileOutputStream()
BufferedOutputStream bos = new BufferedOutputStream
(new FileOutputStream(“D:\PgProject\test11\test.txt”));
// 写数据,使用getBytes()获取字节
bos.write
(“hello\r\n”.getBytes());
bos.write
(“world\r\n”.getBytes());
// 释放资源
bos.close
();
// 创建字节缓冲输入流,参数为输输入字节流,对象为输入流使用匿名内部类直接创建FileInputStream()
BufferedInputStream bis = new BufferedInputStream
(new FileInputStream(“D:\PgProject\test11\test.txt”));
// 使用while循环,先定义一个初始数,一次读取一个字节
int by;
while
((by= bis.read())!=-1){ System._out.println((_char) by); }
// 释放资源
bis.close
();
// 使用while循环,先定义一个数组,一次定义一个数组
byte
[] bytes = new byte[1024];
int len; // while给定一个初始值, 使用read()参数为定义的数组bytes
// 使用String (byte[] bytes, int offset, int length)方法只转字节数组的部分
while
(( len = bis.read(bytes))!=-1){ System._out.println(_new String(bytes,0,len)); }
// 释放资源
bis.close
(); }_

案例: 复制视频

需求: 把”C:\Users\76411\Desktop\test.avi”复制到模块目录下的”test.avi”
思路:

  1. 1. 根据数据源创建字节输入流对象
  2. 1. 根据目的地创建字节输出流对象
  3. 1. 读写数据, 复制文本文件(一次读取一个字节, 一次写入一个字节)
  4. 1. 释放资源

使用四种方式实现复制视频,并记录每种方式复制视频的时间

  1. 1. 基本字节流一次读写一个字节
  2. 1. 基本字节流一次读写一个字节数组
  3. 1. 字节缓冲流一次读写一个字节
  4. 1. 字节缓冲流一个词读写一个字节数组

public class CopyAvi {
_public static void main
(String[] args) throws IOException {
// 记录开始时间,通过System的currentTimeMillis()方法获取当前系统时间
long startTime = System._currentTimeMillis()
;
// 复制视频
// method()); // 调用第一种方法 传送时长:124103毫秒
// method1(); // 调用第二种方法 传送时长: 313毫秒
// method2(); // 调用第三种缓存方法 传送时长: 1262毫秒
method(); // 调用第四种缓存方法 传送时长: 124毫秒
// 记录结束时间
long endTime = System.currentTimeMillis();
System.out.println(“传送时长: “ + (_endTime - startTime) + “毫秒”); }

  1. _// 定义方法写入视频流,一次读写入一个字节<br /> public static void method_() _throws IOException _{<br /> _// 定义一个输入流对象<br /> FileInputStream fis = new FileInputStream_(_"C:\\Users\\76411\\Desktop\\test.avi"_)_;<br /> // 定义一个输出流对象<br /> FileOutputStream fos = new FileOutputStream_(_"D:\\PgProject\\test11\\test.avi"_)_;<br /> // 基本字节流一次读写一个字节<br /> int by;<br /> while _((_by = fis.read_()) _!= -1_) { _fos.write_(_by_)_; _}<br /> _// 释放资源<br /> fis.close_()_;<br /> fos.close_()_; _}
  2. _// 定义方法写入视频流,一次读写入一个字节数组<br /> public static void method1_() _throws IOException _{<br /> _// 定义一个输入流对象<br /> FileInputStream fis = new FileInputStream_(_"C:\\Users\\76411\\Desktop\\test.avi"_)_;<br /> // 定义一个输出流对象<br /> FileOutputStream fos = new FileOutputStream_(_"D:\\PgProject\\test11\\test.avi"_)_;<br /> // 基本字节流一次读写一个数组<br /> byte_[] _bytes = new byte_[_1024_]_;<br /> int len;<br /> while _((_len = fis.read_(_bytes_)) _!= -1_) { _fos.write_(_bytes, 0, len_)_; _} }
  3. _// 字节缓冲流,一次读写一个字节<br /> public static void method2_() _throws IOException _{<br /> _// 创建字节缓冲输入对象,并直接匿名内部类创建FilieInputStream对象<br /> BufferedInputStream bis = new BufferedInputStream_(_new FileInputStream_(_"C:\\Users\\76411\\Desktop\\test.avi"_))_;<br /> // 创建字节缓冲输入对象,并直接匿名内部类创建FilieInputStream对象<br /> BufferedOutputStream bos = new BufferedOutputStream_(_new FileOutputStream_(_"D:\\PgProject\\test11\\test.avi"_))_;<br /> // 缓冲字节流一次读写一个字节<br /> int by;<br /> while _((_by = bis.read_()) _!= -1_) { _bos.write_(_by_)_; _}<br /> _// 释放资源<br /> bis.close_()_;<br /> bos.close_()_; _}
  4. _// 字节缓冲流,一次读写一个字节数组<br /> public static void method3_() _throws IOException _{<br /> _// 创建字节缓冲输入对象,并直接匿名内部类创建FilieInputStream对象<br /> BufferedInputStream bis = new BufferedInputStream_(_new FileInputStream_(_"C:\\Users\\76411\\Desktop\\test.avi"_))_;<br /> // 创建字节缓冲输入对象,并直接匿名内部类创建FilieInputStream对象<br /> BufferedOutputStream bos = new BufferedOutputStream_(_new FileOutputStream_(_"D:\\PgProject\\test11\\test.avi"_))_;<br /> // 缓冲字节流一次读写一个字节<br /> byte_[] _bytes = new byte_[_1024_]_;<br /> int len;<br /> while _((_len = bis.read_(_bytes_)) _!= -1_) { _bos.write_(_bytes, 0, len_)_; _}<br /> _// 释放资源<br /> bis.close_()_;<br /> bos.close_()_; _} }

_