IO流
作用:
用于读写文件中的数据
分类:
图来自黑马程序员网课
纯文本文件:Windows自带的记事本打开能读懂的文件,word excel不是纯文本文件
图来自黑马程序员网课
FileOutputStream:
操作本地文件的字节输出流,可以把程序中的数据写到本地文件中
书写步骤:
1)创建字节输出流对象
参数是字符串表示的路径或者File对象都是可以的
如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
如果文件已经存在,则会清空文件
2)写数据
write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII码上对应的字符
97--》a
3)释放资源
每次使用完流之后都要释放资源
package com.lazyGirl.iodemo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStreamDemo {
public static void main(String[] args) throws IOException {
File file = new File("a.txt");
FileOutputStream fos = new FileOutputStream("a.txt");
fos.write(97);
fos.close();
}
}
输出:
写数据的3种方式:
图来自黑马程序员网课
package com.lazyGirl.iodemo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStreamDemo2 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("a.txt");
byte[] bytes = {98,99,100,101,102,103,104,105};
fos.write(bytes,1,2);
}
}
输出:
写数据的两个小问题:
换行写和续写
package com.lazyGirl.iodemo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class ByteStreamDemo2 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("a.txt",true);
// byte[] bytes = {98,99,100,101,102,103,104,105};
String str = "hhhhhhhhhhh";
byte[] bytes = str.getBytes();
// System.out.println(Arrays.toString(bytes));
fos.write(bytes);
//换行 windows: \r\n Linux : \r mac: \r
String wrap = "\r\n";
byte[] wrapBytes = wrap.getBytes();
fos.write(wrapBytes);
String str2 = "6666666666666666";
byte[] bytes2 = str2.getBytes();
fos.write(bytes2);
fos.close();
}
}
输出:
FileInputStream:
操作本地文件的字节输入流,可以把本地文件中的数据读到程序中来
书写步骤:
1)创建字节输入流对象
细节一:如果文件不存在,就直接报错
2)读数据
细节一:一次读一个字节,读出来的数数据在ASCII上对应的数据
细节二:读到文件末尾,read方法返回-1 空格对应的是32
3)释放资源
package com.lazyGirl.iodemo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class InputStreamDemo1 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
//按字符读,读不到返回-1
int b1 = fis.read();
System.out.println((char)b1);
fis.close();
}
}
输出:
循环读取:
package com.lazyGirl.iodemo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class InputStreamDemo1 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
//按字符读,读不到返回-1
// while (fis.read() != -1){
System.out.print((char)fis.read());
// }
// System.out.println();
int b;
while ((b = fis.read()) != -1){
System.out.print((char)b);
}
fis.close();
}
}
输出:
文件拷贝:
package com.lazyGirl.iodemo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class InputDemo2 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("copy.txt");
int b;
while ((b = fis.read()) != -1)
fos.write(b);
fos.close();
fis.close();
}
}
输出:
文件读取的问题:
弊端:FileInputStream一次读写一个字节,速度太慢了
图来自黑马程序员网课
注意:一次读一个字节数组的数据,每次读取会尽可能把数组装满
图来自黑马程序员网课
文件拷贝:
package com.lazyGirl.iodemo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class InputStreamDemo2 {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("copy.txt");
byte[] buf = new byte[1024 * 1024 * 5];
int len = fis.read(buf);
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
fis.close();
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
提升速度
输出:
try...catch异常处理:
try ...catch...finally 特点:finally里面的代码一定会执行,除非虚拟机停止
接口:AutuCloseable 在特定的情况下,可以自动释放资源
package com.lazyGirl.iodemo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class InputStreamDemo2 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("copy.txt");
try(fis;fos) {
long start = System.currentTimeMillis();
byte[] buf = new byte[1024 * 1024 * 5];
int len;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节流读取文件的时候,文件中不要有中文
计算机的存储规则:
字符集:
ASCII 字符集:存储英文,一个字节就足以 128个字符 0~127
图来自黑马程序员网课
GB2312字符集:
图来自黑马程序员网课
1980年发布,1981年5月1日起实施简体中文汉字编码国家标准,收录7445个图形字符,其中包括6763个简体汉字
BIG5字符集:
台湾地区繁体中文标准字符集,共收录13053个中文字,1984年实施
GBK字符集:
2000年发布,收录21003个汉字,包括国家标准GB13000-1中的全部中日韩汉字和BIG5编码中的所有汉字
windows系统默认使用的是GBK,系统显示ANSI
一个汉字使用两个字节存储
图来自黑马程序员网课
Unicode字符集:
国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言,跨平台的文本信息转换。
以上3个图来自黑马程序员网课
乱码:
原因1:读取数据时未读完整个汉字
图来自黑马程序员网课
原因2:编码和解码不统一
避免乱码:
1. 不要用字节流读取文本文件
2. 编码解码时使用同一个码表,同一个编码方式
扩展:字节流读取中文会乱码,但是拷贝不会乱码(信息不会丢失)
package com.lazyGirl.iodemo;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class CharSetDemo1 {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "爱你ai";
byte[] bytes = str.getBytes();
System.out.println(Arrays.toString(bytes));
byte[] bytes2 = str.getBytes("GBK");
System.out.println(Arrays.toString(bytes2));
//解码
String str2 = new String(bytes, "GBK");
String str3 = new String(bytes);
System.out.println(str2);
}
}
输出:
字符流:
字符流的底层就是字节流
字符流 = 字节流 + 字符集
特点:
输入流:一次读一个字节,遇到中文时,一次读多个字节
输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中
使用场景:
对于纯文本文件进行读写操作
以上2张图来自黑马程序员网课
FileReader:
书写步骤:
1)创建字符输入流对象
图来自黑马程序员网课
2)读取数据
图来自黑马程序员网课
3)释放资源
空参read方法:
package com.lazyGirl.iodemo;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo1 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("a.txt");
int ch;
while ((ch = fr.read()) != -1) {
System.out.print(ch + " ");
}
fr.close();
}
}
有参read方法:
有参的read方法:读取数据,解码,强制转换三步合并
package com.lazyGirl.iodemo;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamDemo1 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("a.txt");
// int ch;
// while ((ch = fr.read()) != -1) {
// System.out.print(ch + " ");
// }
// fr.close();
//
char[] chars = new char[2];
int len;
while ((len = fr.read(chars)) != -1) {
System.out.print(new String(chars, 0, len) + " ");
}
}
}
输出:
FileWriter构造方法:
成员方法:
书写步骤:
1)创建字符输出流对象
细节一:参数是字符串表示的路径或者File对象都是可以的
细节二:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
细节三:如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关
2)写数据
如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集上对应的字符
3)释放资源
原理解析:
图来自黑马程序员网课
图来自黑马程序员网课
总结:
字节流和字符流的使用场景:
字节流:拷贝任意类型的文件
字符流:读取纯文本文件中的数据 往纯文本文件中写出数据