20.01_IO流概述及其分类
A:IO流概述
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的对象都在IO包中 java.io
B:Io流分类
a:按照数据流向 站在内存角度
输入流 读入数据
输出流 写出数据
b:按照数据类型
字节流 可以读写任何类型的文件 比如音频 视频 文本文件
字符流 只能读写文本文件
什么情况下使用哪种流?
如果数据所在的文件通过Windows自带的记事本打开并能读懂里面
的内容,就是字符流。其他用字节流。
如果你什么都不知道,就用字节流
20.02_IO流基类概述和FileOutputStream的构造方法
A:IO流基类概述
a:字节流的抽象基类:
InputStream ,OutputStream
b:字符流的抽象基类:
Reader , Writer
注:由这四个类派生出来的子类名称都是及其父类名作为子类名的后缀。
如:InputStream的子类FileInputStream
如:Reader的子类FileReader
B:FileOutputStream的构造方法
FileOutputStream(File file)
FileOutputStream(String name)
注意事项:
创建字节输出流对象做了几件事情?
a:调用系统资源创建文件,如:a.txt
b:创建一个FOS对象
c:把FOS对象指向这个文件
close()的目的:
a:通知系统释放关于管理文件的资源
b:让IO流对象变成垃圾,等待垃圾回收器对其回收
C:FileOutputStream的三个write()方法
public void write(int b); 写一个字节 超过一个字节,砍掉前
面的字节
public void write(byte[] b); 写一个字节数组
public void write(byte[] b,int off,int len); 写一个字节数组
的一部分
D:FileOutputStream的数据换行
windows \r\n
Linux \n
Mac \r
public static void main(String[] args) throws IOException {
// FileOutputStream 文件输出流
//文件输出流是用于将数据写入 File。
/* FileOutputStream(File file)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(String name)
创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(File file, boolean append)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(String name, boolean append)
创建一个向具有指定 name 的文件中写入数据的输出文件流。*/
File file = new File("a.txt");
//创建一个输出流,关联一个文件,文件输出流所关联的文件如果不存在会
//自动创建
/* if (!file.exists()) {
file.createNewFile();
}*/
FileOutputStream out = new FileOutputStream(file);
}
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(200);
byte[] bytes = {100, 101, 102, 103};
out.write(bytes);
//一次可以写入字节数组的一部分。参数1:数组中元素索引,参数2,个数
out.write(bytes,0,2);
out.write(bytes,1,3);
byte[] bytes1 = "我".getBytes();
// [-26, -120, -111]
System.out.println(Arrays.toString(bytes1));
out.write(bytes1);
out.write(-26);
out.write(-120);
out.write(-111);
byte[] bytes2 = "我爱你中国".getBytes();
out.write(bytes2);
/* 方法摘要
void close ()
关闭此文件输出流并释放与此流有关的所有系统资源。
*/
//当你流使用完毕之后,一定记得释放资源
out.close();
}
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("a.txt");
/*
* 创建字节输出流对象了做了几件事情?
a:调用系统资源创建a.txt文件
b:创建了一个fos对象
c:把fos对象指向这个文件
为什么一定要close()?
a: 通知系统释放关于管理a.txt文件的资源
b: 让Io流对象变成垃圾,等待垃圾回收器对其回收
*
*
* */
fos.close();
}
public static void main(String[] args) throws IOException {
//参数2:是否追加写入,true 就是追加写入,false就是不追加写入
FileOutputStream out = new FileOutputStream("a.txt",true);
out.write("abcdef".getBytes());
//写入换行符
/* windows下的换行符是 \r\n
Linux \n
Mac \r
*/
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();
}
public static void main(String[] args) {
FileOutputStream out = null;
try {
// System.out.println(1 / 0);
//流的异常处理
out = new FileOutputStream("c.txt");
out.write("但愿你的眼睛,只看得到笑容".getBytes());
out.write("\r\n".getBytes());
out.write("但愿你流下每一滴泪,都让人感动".getBytes());
out.write("\r\n".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//释放资源
try {
if(out != null){
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("下面的代码");
System.out.println("下面的代码");
System.out.println("下面的代码");
}
20.03_FileInputStream读取数据
A:int read(); 一次读取一个字节,如果没有数据返回的就是-1
public static void main(String[] args) throws IOException {
/* java.io
类 FileInputStream java.io.FileInputStream 从文件系统中的某个文
件中获得输入字节。
*/
/* FileInputStream(String name)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通
过文件系统中的路径名 name 指定。
FileInputStream(File file)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通
过文件系统中的 File 对象 file 指定。
*/
// FileNotFoundException:c.txt(系统找不到指定的文件。)
//输入流,所关联的文件,如果不存在,就会报错
FileInputStream in = new FileInputStream(new File("a.txt"));
//读取文件中的数据
//一次读取一个字节,如果读取不到,返回-1 我们就可以使用 -1 来判断
//这个文件是否读取完了。
int by = in.read();
System.out.println(by);
by = in.read();
char ch = (char)by;
System.out.println(ch);
//使用完毕,记得关闭流
in.close();
}
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream("c.txt");
//定义一个字节数组,来充当这个缓冲区
byte[] bytes = new byte[1024 * 1024];
//一次读取多个字节,填满到你给的这个字节数组中,返回的是读取到的
//有效的字节个数
int len = in.read(bytes);
System.out.println(len);
String s = new String(bytes, 0, len);
System.out.println(s);
}
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream("c.txt");
//定义一个字节数组,来充当这个缓冲区
byte[] bytes = new byte[1024];
//一次读取你指定的一部分字节,填充到你给的缓冲区当中
//从0索引处开始填充3个字节
int len = in.read(bytes, 0, 3);
for (byte aByte : bytes) {
System.out.println(aByte);
}
String s = new String(bytes,0,3);
System.out.println(s);
in.close();
}
复制文件
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream("C:\\Users\\ShenMouMou\\Music\\夜夜夜夜.mp3");
FileOutputStream out = new FileOutputStream("E:\\夜夜夜夜.mp3");
int by = 0;
while((by = in.read()) != -1){
out.write(by);
out.flush();
System.out.println("正在复制...");
}
in.close();
out.close();
//很显然一次读写一个字节,来进行文件的复制,效率太低,你应该一次
//读取一个字节数组,来进行复制。
}
public static void main(String[] args) throws IOException {
//很显然一次读写一个字节,来进行文件的复制,效率太低,你应该一次
//读取一个字节数组,来进行复制。
FileInputStream in = new FileInputStream("C:\\Users\\ShenMouMou\\Music\\夜夜夜夜.mp3");
FileOutputStream out = new FileOutputStream("E:\\夜2222.mp3");
//创建一个数组来充当缓冲区
byte[] bytes = new byte[1024 * 8];
//返回的是读取的到有效的字节个数
int len = 0; //定义一个变量,来接收每次读取到的有效的字节个数
while((len = in.read(bytes)) != -1){
out.write(bytes,0,len);
out.flush();
System.out.println("正在复制...");
}
/* while (true) {
int len = in.read(bytes);
if (len == -1) {
break;
}
out.write(bytes, 0, len);
}*/
in.close();
out.close();
System.out.println("复制完毕");
}
public static void main(String[] args) {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("C:\\Users\\ShenMouMou\\Music\\夜夜夜夜.mp3");
out = new FileOutputStream("E:\\夜2222.mp3");
//创建一个数组来充当缓冲区
byte[] bytes = new byte[1024 * 8];
//返回的是读取的到有效的字节个数
int len = 0; //定义一个变量,来接收每次读取到的有效的字节个数
while ((len = in.read(bytes)) != -1){
out.write(bytes,0,len);
out.flush();
System.out.println("正在复制...");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(in != null){
in.close();
}
if(out != null){
out.close();
}
System.out.println("复制完毕");
} catch (IOException e) {
e.printStackTrace();
}
}
}
20.04_BufferedOutputStream写出数据
A:缓冲思想
字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,
这是加入了数组这样的缓冲区效果,java本身设计的时候;也考虑到了
这样的设计思想,所以提供了字节缓冲区流
B:BufferedOutputStream的构造方法
查看API
BufferedOutputStream(OutputStream out)
20.05_BufferedInputStream读取数据
A:BufferedInputStream的构造方法
查看API
BufferedInputStream(InputStream in)
public static void main(String[] args) throws IOException {
/* 该类实现缓冲的输出流。通过设置这种输出流,
应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入
调用底层系统。*/
//高效的字节输入输出流
// BufferedInputStream
// BufferedOutputStream
//构造方法
// BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出
//流,以将数据写入指定的底层输出流。
/*BufferedInputStream(InputStream in)
创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来
使用。*/
long start = System.currentTimeMillis();
//copyFile();
copyFile2();
long end = System.currentTimeMillis();
System.out.println("耗时" + (end - start) + "毫秒");
}
private static void copyFile() throws IOException{
FileInputStream in = new FileInputStream("F:\\CloudMusic\\LiSA - 紅蓮華 (THE FIRST TAKE Studio Ver.).mp3");
FileOutputStream out = new FileOutputStream("C:\\Users\\57642\\Desktop\\红莲华.mp3");
byte[] bytes = new byte[1024 * 8];
int len = 0;
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
out.flush();
System.out.println("正在复制...");
}
}
private static void copyFile2() throws IOException {
BufferedInputStream in = new BufferedInputStream(new FileInputStream("F:\\CloudMusic\\LiSA - 紅蓮華 (THE FIRST TAKE Studio Ver.).mp3"));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("C:\\Users\\57642\\Desktop\\红莲华.mp3"));
byte[] bytes = new byte[1024 * 8];
int len = 0;
while ((len = in.read(bytes)) != -1){
out.write(bytes,0,len);
out.flush();
System.out.println("正在复制");
}
in.close();
out.close();
}
20.06_String类中的编码和解码问题
A:编码:把字符串转换成字节数组
public byte[] getBytes(); 使用平台的默认字符集将此String
编码为byte序列,并将结果存储到
一个新的byte数组中。
public byte[] getBytes(String charsetName);
使用指定的字符集将此String编码
为byte序列,并将结果存储到一个
新的byte数组中。
B:解码:把字节数组转换成字符串
public String(byte[] bytes); 通过使用平台默认字符集解码指定
的byte数组,构造一个新的String。
public String(byte[] bytes,String charsetName);
通过使用指定的charset解码指定的
byte数组,构造一个新的String。
C:使用什么字符集进行编码,就使用什么字符集进行解码
public static void main(String[] args) throws IOException {
//Unicode 码表 收录了所有国家的字符编码
//UTF-8 GBK 对Unicode标准的实现
//编码:把字符串转换成字节数组
//解码:把字节数组转换成字符串
String str = "我爱你";
//编码:getBytes();按照平台默认的码表进行编码
// byte[] bytes = str.getBytes();
byte[] bytes = str.getBytes("UTF-8");
System.out.println(Arrays.toString(bytes));
//解码 :new String(bytes);按照平台默认的码表进行解码
String s = new String(bytes, "UTF-8");
System.out.println(s);
//中文乱码:就是编解码使用的不是同一个码表。
}
20.07_转换流OutputStreamWriter的使用
A:OutputStreamWriter的构造方法
OutputStreamWriter(OutputStream out); 根据默认编码(GBK)把字节
流的数据转换为字符流
OutputStreamWriter(OutputStream out,String charsetName);
根据指定编码把字节流数
据转换为字符流
B:字符流的5种写数据的方式
public void write(int c) 写一个字符
public void write(char[] cbuf) 写一个字符数组
public void write(char[] cbuf,int off,int len)
写一个字符数组的一部分
public void write(String str) 写一个字符串
public void write(String str,int off,int len)
写一个字符串的一部分
public static void main(String[] args) throws IOException {
/*
* 根据文件头数据判断文件类型
现有一文件,其扩展名未知或标记错误。假设它是一个正常的、非空的
文件,且将扩展名更正后可以正常使用,那么,如何判断它是哪种类型
的文件?
在后缀未知,或者后缀被修改的文件,依然通过文件头来判断该文件究
竟是什么文件类型。
* 我们可以使用一个文本编辑工具如UltraEdit打开文件(16进制模式下),
* 然后看文件头是什么字符,以下是常见文件类型的文件头字符(16进制),
JPEG (jpg),文件头:FFD8FF
PNG (png),文件头:89504E47
GIF (gif),文件头:47494638
TIFF (tif),文件头:49492A00
* */
//文件的后缀名的作用,告诉系统用什么默认软件来打开该文件。真正的
//区分文件的类型,在文件字节数据的文件头一部分字节来标识这个文件类
//型的
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("b.txt"));
out.write("我爱你爱我");
out.write("\r\n");
//一次写入一个字符串的一部分
out.write("根据文件头数据判断文件类型",0,5);
out.write("\r\n");
char[] chars = {'a','b','c','好'};
out.write(chars);
out.write("\r\n");
//一次写入字符数组的一部分字符。
out.write(chars,3,1);
out.write("\r\n");
out.flush();
//释放资源
out.close();
}
public static void main(String[] args) throws IOException {
// 字符流,只能操作文本文件,
// OutputStreamWriter
/* OutputStreamWriter 是字符流通向字节流的桥梁:
可使用指定的 charset
将要写入流中的字符编码成字节。
它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符
集。*/
/* OutputStreamWriter(OutputStream out)
创建使用默认字符编码的 OutputStreamWriter。
*/
//输出流,所关联的文件如果不存在,则自动创建。
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("a.txt"));
//一次写入一个字符
out.write('你');
//字符流需要刷新一下
out.flush();
out.write('你');
out.write('你');
out.write('你');
out.flush();
out.write('你');
out.write('你');
out.flush();
out.write('你');
out.write('你');
out.write('你');
out.write('你');
out.write('你');
out.flush();
out.close(); //关闭并刷新
}
public static void main(String[] args) throws IOException {
/* OutputStreamWriter(OutputStream out, String charsetName)
创建使用指定字符集的 OutputStreamWriter。*/
//可以指定码表。
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("d.txt"), "UTF-8");
out.write("我爱你");
out.close();
}
20.08_转换流InputStreamReader的使用
A:InputStreamReader的构造方法
InputStreamReader(InputStream is) 用默认的编码(GBK)读取数据
InputStreamReader(InputStream is,String charsetName);
用指定的编码读取数据
B:字符流的2种读数据的方法
public int read() 一次读取一个字符,如果没有读到,返回-1
public int read(char[] cbuf)
一次读取一个字符数组,如果没有读到,返回-1
public static void main(String[] args) throws IOException {
// InputStreamReader 是字节流通向字符流的桥梁:它使用指定的
// charset 读取字节并将其解码为字符。
// 它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的
// 字符集。
/* InputStreamReader(InputStream in)
创建一个使用默认字符集的 InputStreamReader。*/
//输入流,所关联的文件,如果不存在,就会报错。
InputStreamReader in = new InputStreamReader(new FileInputStream("d.txt"));
//一次读取一个字符,如果读取不到返回 -1 我们可以通过-1 来判断文件
//是否读取完
int ch = in.read();
//char ch2 = (char) ch;
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);
in.close();
}
public static void main(String[] args) throws IOException {
InputStreamReader in = new InputStreamReader(new FileInputStream("d.txt"));
char[] chars = new char[100];
//一次读取多个字符,填充到字符数组中
//int len = in.read(chars);
//一次读取2个字符,填充到字符数组中 从0开始填入
int len2 = in.read(chars, 0, 2);
System.out.println(len2);
String s = new String(chars, 0, len2);
System.out.println(s);
String s1 = String.valueOf(chars);
System.out.println(s1);
}
20.09_FileWriter和FileReader复制文本文件
A:FileReader和FileWriter的出现
转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的
所以,为了简化我们的书写,转换流提供了对应的子类。
FileWriter
FileReader
字符流便捷类:因为转换流的名字太长了,并且在一般情况下我们不需要制定字
符集,于是java就给我们提供转换流对应的便捷类
转换流 便捷类
OutputStreamWriter —————————— FileWriter
InputStreamReader ——————————— FileReader
public static void main(String[] args) throws IOException {
//使用字符流来复制文本文件
//1.一次读取一个字符,写入一个字符来复制 ,效率慢,不推荐使用
//2. 一次读取一个字符数组,写入一个数组复制,推荐方式。
//ctrl+alt+空格 手动提示
InputStreamReader reader = new InputStreamReader(new FileInputStream("a.txt"));
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("C:\\Users\\57642\\Desktop\\MyTest2.java"));
/* while (true) {
int ch = reader.read();
if (ch == -1) {
break;
}
writer.write(ch);
writer.flush();
}*/
int ch = 0;
while((ch = reader.read()) != -1){
writer.write(ch);
writer.flush();
}
reader.close();
writer.close();
}
public static void main(String[] args) throws IOException {
InputStreamReader reader = null;
OutputStreamWriter writer = null;
try {
reader = new InputStreamReader(new FileInputStream("b.txt"));
writer = new OutputStreamWriter(new FileOutputStream("C:\\Users\\57642\\Desktop\\MyTest2.java"));
//定义一个字符数组来充当缓冲区
char[] chars = new char[2000];
int len = 0; //记录每次读取到的有序的字符个数
while((len = reader.read(chars)) != -1){
writer.write(chars,0,len);
writer.flush();
System.out.println("复制");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(reader != null){
reader.close();
}
if(writer != null){
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
// 父类---------------------子类
// InputStreamReader ------ FileReader
// OutputStreamWriter ------ FileWriter
// ctrl+Q 可以查看文档
FileReader reader = new FileReader("MyTest.java");
FileWriter writer = new FileWriter("MyTest2.java");
//定义一个字符数组来充当缓冲区
char[] chars = new char[2000];
int len = 0; //记录每次读取到的有序的字符个数
while((len = reader.read(chars)) != -1){
writer.write(chars,0,len);
writer.flush();
System.out.println("复制");
}
reader.close();
writer.close();
}
20.10_字符缓冲流的基本使用
A:高效的字符流
高效的字符输出流:BufferedWriter
构造方法:public BufferedWriter(Writer w)
高效的字符输入流:BufferedReader
构造方法:public BufferedReader(Reader e)
B:字符缓冲流的特殊功能
BufferedWriter:public void newLine():
根据系统来决定换行符,具有系统兼容性的换行符
BufferedReader:public String readLine():
一次读取一行数据,是以换行符为标记的 读到换行符就换
行 没读到数据返回null 包含该行内容的字符串,不包括
任何终止符,如果已到达流末尾,则返回null
public static void main(String[] args) throws IOException {
//高效的字符流
// BufferedReader
//BufferedWriter
// new BufferedReader(new InputStreamReader(new FileInputStream("MyTest.java")));
BufferedReader reader = new BufferedReader(new FileReader("MyTest.java"));
//new BufferedWriter(new OutputStreamWriter(new FileOutputStream("MyTest3.java")));
BufferedWriter writer = new BufferedWriter(new FileWriter("myTest3.java"));
char[] chars = new char[2000];
int len = 0; //记录每次读取到的有序的字符个数
while((len = reader.read(chars)) != -1){
writer.write(chars,0,len);
writer.flush();
System.out.println("复制");
}
reader.close();
writer.close();
}
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("MyTest.java"));
BufferedWriter writer = new BufferedWriter(new FileWriter("myTest5.java"));
//高效的字符流有两个特有的方法,比较好用。经常用
//一次读取一行,读取不到返回null
//String s = reader.readLine();
//writer.newLine();//写入换行符,具有平台兼容性
String line = null;
while((line = reader.readLine()) != null){
writer.write(line);
writer.newLine();
writer.flush();
}
/* while (true) {
String s = reader.readLine();
if (s == null) {
break;
}
writer.write(s);
//writer.write("\r\n");
//写入换行符,具有平台兼容性
writer.newLine();
writer.flush();
}*/
writer.close();
reader.close();
}