IO流的学习
IO流的学习
IO流的概述及其分类
A:IO流的概述
IO流用来处理设备之间的数据传输
Java对数据的操作十通过流的方式
Java用于操作流的对象都在IO包中Java.io
B:IO流分类
a:按数据流向,站在内存角度
输入流 读入数据
输出流 写入数据
b:按照数据类型
字节流 可以读写任何类型的文件,比如音频 视频 文本文件
字符流 只能读写文本文件
什么情况下使用哪种流呢?
如果数据所在的文件通过windows自带的记事本打开并能读懂里面的内容,就用字符流。其他用字节流如果你什么都不知道,就用字节流
IO流基类概述和FileOutputStream的构造方法
A:IO流基类概述
a:字节流的抽象基类:
InputStream,Outputstram.
b:字符流的抽象基类:
Reader,Writer.
注:由这四个类派生出来的子类名称都是以其父类作为子类名的后缀。
如:InputStream的子类FileInputStream。
如:Reader的子类FileInpurStream
B:FileOutStream的构造方法
由一个案例引出使用流程,由于字节流先出现就先字节输出流基本的类型OutputStream,使用具体子类FileOutputStream
IO流的分类:
(1):按照流向 划分
输入流
输出流
(2):按照操作的的数据进行划分
字节流
字节输入流 InputStream 读
字节输出流 OutputStream 写
字符流
字符输入流 Reader 读
字符输出流 Writer 写
需求:往一个文本文件中写一串数据 Hello IO
分析:
a:我们现在操作的是文本文件,所有按照我们的想法,我们优先使用字符流,但是字节流是优于字节流。所以先使用字节流
b:因为我们要写数据,所以我们应该使用字节输出流 OutputStream
我们发现OutputStream是一个抽象类,我们不能对其进行直接实例化,而我们需要使用子类对其进行实例化,那么使用哪个子类?
我们现在操作的是文件所以我们选择的是FileOutputStream
IO流(FileOutputStream写出数据)(掌握)
A: 构造方法
FileOutputStream(File file)
FileOutputStream(String name)
B:案例演示
FileOutputStream写出数据
注意事项:
创建字节输出流对象了做了几件事情?
a:调用系统资源创建a.txt文件
b:创建了一个fos对象
c:把fos对象指向这个文件
为什么一定要close()?
a: 通知系统释放关于管理a.txt文件的资源
b: 让Io流对象变成垃圾,等待垃圾回收器对其回收
public class MyTest {
public static void main(String[] args) throws IOException {
// 类 FileOutputStream 文件输出流是用于将数据写入 File 的输出流
/* FileOutputStream(String name)
创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(File file)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。*/
//输出流,所关联的文件如果不存在,会自动创建
FileOutputStream out = new FileOutputStream("a.txt");
FileOutputStream out2 = new FileOutputStream(new File("b.txt"));
}
}
IO流(FileOutputStream的)的三个write()方法
A:FileOutStream的三个write()方法
public void write(int b):写一个字节 超过一个字节 砍掉前面的字节
public void write(byte[] b):写一个字节数组
public void write(byte[] b,int off,int len):写一个字节数组的一部分
B:案例演示:FileOutputStream的三个write()方法
public class MyTest2 {
public static void main(String[] args) throws IOException {
FileOutputStream out = new FileOutputStream("a.txt");
//往文件中写入数据
//一次写入一个字节数据
out.write(97);
out.write(98);
out.write(99);
out.write(127);
//如果超过一个字节,会丢弃掉多余字节
out.write(300);
// [-26, -120, -111]
out.write(-26);
out.write(-120);
out.write(-111);
// out.write();
//byte[] bytes = "我".getBytes();
//System.out.println(Arrays.toString(bytes));
//一次写入一个字节数组
out.write("我爱你".getBytes());
byte[] arr = {97, 98, 99, 100, 101};
out.write(arr);
//一次写入字节数组的一部分
//2 索引 3 字节个数
out.write(arr, 2, 3);
String str = "西部开源";
byte[] bytes = str.getBytes();
System.out.println(Arrays.toString(bytes));
//6 是索引, 6 字节个数
out.write(str.getBytes(), 6, 6);
//流使用完毕,记得关闭流
out.close(); //销毁输出流对象,释放系统底层资源
}
}
IO流(FileOutputStream写出数据实现换行和追加写入)
A:案例演示:FileOutputStream写出数据如何实现数据的换行
Windows下的换行符只用是 \r\n
Linux \n
Mac \r
eclipse/IDEA中的记事本软件以及editpius这样的第三种软件都做了平台的兼容
B:案例演示:FileOutputStream写出数据如何实现数据的追加写入
public class MyTest4 {
public static void main(String[] args) throws IOException {
/*
* windows下的换行符是 \r\n
Linux \n
Mac \r
*
*
* */
//参数:true 表示追加写入,false或省略该参数,就不会追加,而是覆盖。
FileOutputStream out = new FileOutputStream("诗.txt", true);
out.write("去年今日此门中,".getBytes());
//写入换行符
out.write("\r\n".getBytes());
out.write("人面桃花相映红。".getBytes());
out.write("\r\n".getBytes());
out.write("人面不知何处去,".getBytes());
out.write("\r\n".getBytes());
out.write("桃花依旧笑春风。".getBytes());
out.write("\r\n".getBytes());
out.close();
}
}
IO流(FileOutputStream写出数据加入异常处理)
A:案例演示:FileOutputStream写出数据加入异常处理
public class MyTest {
public static void main(String[] args) {
//流的异常处理
FileOutputStream out = null;
try {
out = new FileOutputStream("a.txt");
out.write("abc".getBytes());
//System.out.println(1 / 0);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
System.out.println("进来了");
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
IO流(FileInputStream读取数据一次一个字节)
A:案例演示: int read():一次读取一个字节
如果没有数据返回的就是-1
public class MyTest2 {
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream("a.txt");
//读取文件数据,
int by = in.read(); //一次读取一个字节数据,返回的是你读取到的那个字节
System.out.println(by);
//System.out.println((char) by);
by = in.read(); //一次读取一个字节数据
System.out.println(by);
by = in.read(); //一次读取一个字节数据
System.out.println(by);
//文件中数据读取完毕,然后读取不到了,返回 -1 我们可以使用 -1 来判断文件是否读取完毕。
by = in.read(); //一次读取一个字节数据
System.out.println(by);
}
}
IO流(字节流复制文本文件)(掌握)
A:案例演示: 字节流一次读写一个字节复制文本文件
分析:
- a: 创建字节输入流对象和字节输出流对象
- b: 频繁的读写操作
- c: 释放资源
public class MyTest {
public static void main(String[] args) throws IOException {
//复制文件,读取一个字节,写入一个字节来复制
FileInputStream in = new FileInputStream("C:\\Users\\ShenMouMou\\Desktop\\MyTest.java");
FileOutputStream out = new FileOutputStream("D:\\test\\MyTest.java");
/* while (true) {
int by = in.read();
if (by == -1) {
break;
}
out.write(by);
}*/
int by = 0;
while ((by = in.read()) != -1) {
out.write(by);
}
in.close();
out.close();
}
}
IO流(字节流复制MP3)
A:案例演示: 字节流一次读写一个字节复制MP3
public class MyTest2 {
public static void main(String[] args) throws IOException {
//复制文件,读取一个字节,写入一个字节来复制
FileInputStream in = new FileInputStream("C:\\Users\\ShenMouMou\\Desktop\\烟花易冷Live_林志炫.mp3");
FileOutputStream out = new FileOutputStream("D:\\test\\烟花易冷Live.mp3");
/* while (true) {
int by = in.read();
if (by == -1) {
break;
}
out.write(by);
}*/
long start = System.currentTimeMillis();
int by = 0;
while ((by = in.read()) != -1) {
out.write(by);
}
long end = System.currentTimeMillis();
in.close();
out.close();
System.out.println("复制完成耗时:" + (end - start) + "毫秒");
}
}
IO流(FileInputStream读取数据一次一个字节数组)(掌握)
A:案例演示: int read(byte[] b):一次读取一个字节数组
返回的int类型的值表示的意思是读取到的字节的个数,如果没有数据了就返回-1
public class MyTest3 {
public static void main(String[] args) throws IOException {
//很显然:读取一个字节,写入一个字节来复制 效率很低
//你 可以一次读取一个数组,写出一个字节数组,来复制。
FileInputStream in = new FileInputStream("C:\\Users\\ShenMouMou\\Desktop\\烟花易冷Live_林志炫.mp3");
File file = new File("D:\\test");
if (!file.exists()) {
file.mkdirs();
}
FileOutputStream out = new FileOutputStream(new File(file, "烟花易冷Live.mp3"));
//定义字节数组,充当缓冲区
byte[] bytes = new byte[1024 * 8];
//定义一个变量,用来记录实际读取到的字节个数
int len = 0;
long start = System.currentTimeMillis();
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
out.flush(); //刷新缓冲区
}
long end = System.currentTimeMillis();
System.out.println("复制完成耗时:" + (end - start) + "毫秒");
in.close();
out.close();
}
}
IO流(FileInputStream读取数据的两种方式比较图解)(掌握)
A:画图演示: FileInputStream读取数据的两种方式比较图解
IO流(字节流复制文本文件2)(掌握)
A:案例演示: 字节流一次读写一个字节数组复制文本文件
public class MyTest4 {
public static void main(String[] args) {
//很显然:读取一个字节,写入一个字节来复制 效率很低
//你 可以一次读取一个数组,写出一个字节数组,来复制。
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("C:\\Users\\ShenMouMou\\Desktop\\烟花易冷Live_林志炫.mp3");
out = new FileOutputStream("D:\\test\\烟花易冷Live.mp3");
//定义字节数组,充当缓冲区
byte[] bytes = new byte[1024 * 8];
//定义一个变量,用来记录实际读取到的字节个数
int len = 0;
long start = System.currentTimeMillis();
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
out.flush(); //刷新缓冲区
}
long end = System.currentTimeMillis();
System.out.println("复制完成耗时:" + (end - start) + "毫秒");
} catch (IOException e) {
e.printStackTrace();
} finally {
//释放资源
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
IO流(字节流复制MP3)(掌握)
A:案例演示: 字节流一次读写一个字节数组复制MP3
public class MyTest {
public static void main(String[] args) throws IOException {
// BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。
// 在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,
// 一次填充多个字节
// BufferedInputStream
//该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
//BufferedOutputStream
// BufferedInputStream(InputStream in)
// 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
//test1(); //复制完成耗时:24962毫秒 14毫秒
//test2(); // 复制完成耗时:188毫秒 复制完成耗时:12毫秒
}
private static void test2() throws IOException {
FileInputStream in = new FileInputStream("C:\\Users\\ShenMouMou\\Desktop\\烟花易冷Live_林志炫.mp3");
FileOutputStream out = new FileOutputStream("D:\\test\\烟花易冷Live.mp3");
BufferedInputStream bin = new BufferedInputStream(in);
//ctrl+Q 查看方法的文档
//ctrl+P 查看方法的参数
BufferedOutputStream bout = new BufferedOutputStream(out);
byte[] bytes = new byte[1024 * 8];
int by = 0;
long start = System.currentTimeMillis();
while ((by = bin.read(bytes)) != -1) {
bout.write(bytes, 0, by);
}
long end = System.currentTimeMillis();
bin.close();
bout.close();
System.out.println("复制完成耗时:" + (end - start) + "毫秒");
}
private static void test1() throws IOException {
FileInputStream in = new FileInputStream("C:\\Users\\ShenMouMou\\Desktop\\烟花易冷Live_林志炫.mp3");
FileOutputStream out = new FileOutputStream("D:\\test\\烟花易冷Live.mp3");
byte[] bytes = new byte[1024 * 8];
int by = 0;
long start = System.currentTimeMillis();
while ((by = in.read(bytes)) != -1) {
out.write(bytes, 0, by);
out.flush();
}
long end = System.currentTimeMillis();
in.close();
out.close();
System.out.println("复制完成耗时:" + (end - start) + "毫秒");
}
}
IO流(BufferedOutputStream写出数据)
A:缓冲思想
字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多
这是加入了数组这样的缓冲区效果,Java本身在设计的时候,也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流
B:BufferedOutStream的构造方法
查看API
BufferedOutputStream(OutputStream out)
C:案例演示
BufferedInputStream写出数据
public class MyTest4 {
public static void main(String[] args) throws IOException {
// InputStreamReader InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
/* InputStreamReader(InputStream in)
创建一个使用默认字符集的 InputStreamReader。*/
//输入流所关联的文件如果不存在,就报错
InputStreamReader in = new InputStreamReader(new FileInputStream("b.txt"));
char[] chars = new char[10];
//一次读取一个字符数组 ,返回值是你读取到的实际的字符个数
//int len = in.read(chars);
///一次读取一个字符数组,一部分,读取3个字符,填充到容器中
int len = in.read(chars, 0, 3);
System.out.println(len);
System.out.println(Arrays.toString(chars));
System.out.println(String.valueOf(chars, 0, len));
System.out.println(new String(chars, 0, len));
in.close();
}
}
IO流(BufferedInputSreeam读取数据)
A:BufferedInputStream的构造方法
查看API
BufferedInputStream(InputStream in)
B:案例演示
BufferedInputStream读取数据
public class MyTest3 {
public static void main(String[] args) throws IOException {
// InputStreamReader InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
/* InputStreamReader(InputStream in)
创建一个使用默认字符集的 InputStreamReader。*/
//输入流所关联的文件如果不存在,就报错
InputStreamReader in = new InputStreamReader(new FileInputStream("b.txt"));
int ch = in.read();
System.out.println(ch);
ch = in.read();
System.out.println(ch);
ch = in.read();
System.out.println(ch);
ch = in.read();
System.out.println(ch);
ch = in.read();
System.out.println(ch);
ch = in.read();
System.out.println(ch);
ch = in.read();
System.out.println(ch);
ch = in.read();
System.out.println(ch);
ch = in.read();
//如果读取不到就返回-1 我们用-1可以判断文件是否读取完毕
System.out.println(ch);
in.close();
}
}
字符流出现的原因以及编码表概述和常见编码表
A:案例演示:字符流出现的原因:由于字节流操作中文不是特别方便,所以,Java就提供了字符流。
B:码表
C:字符流:字符流 = 字节流 + 编码表
IO流(String类中的编码和解码问题)
编码:就是把字符串换成字节数组
把一个字符串转换成一个字节数组
public byte[] getBytes(); 使用平台的默认字符集将此String编码为byte序列,并将结果存储到一个新的byte数组中。
public byte[] getBytes(String charsetName) 使用指定的字符集将此String 编码为byte序列,并将结果存储新的byte数组中。
解码:把字节数组转换成字符串
public String(byte[] bytes):通过使用平台的默认字符集解码指定的byte数组,构造一个新的String。
public String (byte[] bytes,String charsetName)通过使用指定的charset解码指定的byte数组,构造一个新的String.
使用什么字符集进行