本篇接上篇:Java中的字符流,流的读写的细节参考上篇
本篇讲述字节流相关话题,包括字节流的读取与写出,字节流转化为字符流
1.明确是否是纯文本:纯文本 ? 字符流: 字节流
2.明确数据来源
( 输入流 I )和数据流向
( 输出流 O )
3.I流和O流对接,数据传输
另外:需要字符编码转换,使用字节流转换字符流
数据来源( 输入流 I ):内存、磁盘、网络、键盘
数据流向( 输出流 O ): 内存、磁盘、网络、控制台
1.最常见的几种流

2.流与流之间的相互作用:转换与包装

一、FileOutputStream与FileInputStream
1.FileOutputStream:输出流,写出操作
FileOutputStream fos = null;
try {
String fileName = "I:\\Java\\Base\\Thinking\\src\\IOTest\\FileInputStream.txt";
fos = new FileOutputStream(fileName);
fos.write("Line1 第一行".getBytes());//不需要刷新缓冲
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}

2.FileInputStream:输入流,读进操作
public static void main(String[] args) {
try {
String fileName = "I:\\Java\\Base\\Thinking\\src\\IOTest\\FileInputStream.txt";
FileInputStream fis = new FileInputStream(fileName);
//readOneByOne(fis);
//readByByteArrayByWhile(fis);
} catch (IOException e) {
e.printStackTrace();
}
}
1)一个一个字节
读
private static void readOneByOne(FileInputStream fis) throws IOException {
int ch = 0;
while ((ch = fis.read()) != -1) {
System.out.println(ch + "=" + (char) ch);
}
}
一共输出了15个字节,和
Line1 第一行
有出入,原因:
在utf-8编码下,一个中文字符占三个字节
76=L 105=i 110=n 101=e 49=1 32= 231=ç 172=¬ 172=¬ 228=ä 184=¸ 128=� 232=è 161=¡ 140=�
2)字节数组方式:
private static void readByByteArrayByWhile(FileInputStream fis) throws IOException {
//字符数组循环读取
byte[] buf = new byte[8];
int len = 0;
while ((len = fis.read(buf)) != -1) {
System.out.println(new String(buf, 0, len));
}
}
可见buf一次装个字节,
第
由三个字节表示,被分成了两半,所以读出了乱码
//Line1 �
//�一行
文件字节数
System.out.println(fis.available());//15
二、使用字节流拷贝
视频大小:576M
1.使用FileInputStream和FileInputStream拷贝
耗时:6.162444569秒
private static void copy() {
FileOutputStream fos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream("I:\\Java\\Base\\Thinking\\src\\IOTest\\video.avi");
fos = new FileOutputStream("F:\\javaTest\\IO\\video.avi");
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
2.使用包装类BufferedOutputStream和BufferedInputStream拷贝:
方法耗时:33.478968503秒
private static void copyByBuf() {
BufferedOutputStream bfos = null;
BufferedInputStream bfis = null;
try {
FileInputStream fis = new FileInputStream("I:\\Java\\Base\\Thinking\\src\\IOTest\\video.avi");
bfis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("F:\\javaTest\\IO\\video.avi");
bfos = new BufferedOutputStream(fos);
int b = 0;
while ((b = bfis.read()) != -1) {
bfos.write(b);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bfis != null) {
bfis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bfos != null) {
bfos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
三、字节流转化为字符流
场景一:将键盘录入写入到本地磁盘
分析:键盘录入是一个字节输入流: InputStream in = System.in;
由于输入的都是字符,使用字符流将比较方便(当然字节流也可以,不过麻烦一点)
1.用字符流InputStreamReader将字节流转化
2.再用字符包装流BufferedReader包装一下(当然也可以不包装,不过麻烦一点)

public class Save2File {
public static void main(String[] args) throws Exception {
//数据源----键盘录入字节流转化为字符流后包装成BufferedReader
BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入";
//数据流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入" 文件
BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path)));
String line = null;
while ((line=bfr.readLine())!=null){
if ("over".equals(line)) {
break;
}
brw.write(line);
brw.newLine();
brw.flush();
}
bfr.close();
brw.close();
}
}

场景二:将键盘录入写入到本地磁盘:指定字符编码
默认字符编码为utf-8,这里使用GBK测试
public class Save2File {
public static void main(String[] args) throws Exception {
//数据源----键盘录入字节流转化为字符流后包装成BufferedReader
BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入-GKB";
//数据流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入" 文件
BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path),"GBK"));
String line = null;
while ((line=bfr.readLine())!=null){
if ("over".equals(line)) {
break;
}
brw.write(line);
brw.newLine();
brw.flush();
}
bfr.close();
brw.close();
}
}

可见两者的字节数不同,一个GBK的汉字占2个字节
(2*5+\r\n=12)
,一个UTF-8汉字占3个字节(3*5+\r\n=17)
场景3:读取文件输出到控制台
分析:控制台输出是一个字节输出流:PrintStream out = System.out;
由于输出的都是字符,使用字符流将比较方便(当然字节流也可以,不过麻烦一点)
1.用字符流OutputStreamWriter将字节流转化
2.再用字符包装流BufferedWriter包装一下(当然也可以不包装,不过麻烦一点)
public class ReadFile2Console {
public static void main(String[] args) throws Exception {
//数据源----本地文件
String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\Activity.md";
BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
//数据流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入" 文件
BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while ((line = bfr.readLine()) != null) {
if ("over".equals(line)) {
break;
}
brw.write(line);
brw.newLine();
brw.flush();
}
bfr.close();
brw.close();
}
}

场景4:改变系统流的流向
可以改变系统的录入流(数据来源),和控制台输出流(数据流向)
System.setIn(InputStream 输入流); 自定义System.in数据来源(默认键盘录入)
System.setOut(PrintStream 输出流);自定义System.out数据流向(默认控制台)
public class ReadFile2Console {
public static void main(String[] args) throws Exception {
//数据源----本地文件
String path = "I:\\Java\\Base\\Thinking\\src\\IOTest\\Activity.md";
System.setIn(new FileInputStream(path));//将键盘源改为了磁盘文件源
System.setOut(new PrintStream("F:\\hell.txt"));//将流向控制台改为流向磁盘文件
BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
//数据流向 :"I:\\Java\\Base\\Thinking\\src\\IOTest\\键盘录入" 文件
BufferedWriter brw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while ((line = bfr.readLine()) != null) {
if ("over".equals(line)) {
break;
}
brw.write(line);
brw.newLine();
brw.flush();
}
bfr.close();
brw.close();
}
}
后记:捷文规范
1.本文成长记录及勘误表
项目源码 | 日期 | 备注 |
---|---|---|
V0.1--无 | 2018-10-10 | Java中的字节流与字符流转化 |
V0.2--无 | - | - |
2.更多关于我
笔名 | 微信 | 爱好 | |
---|---|---|---|
张风捷特烈 | 1981462002 | zdl1994328 | 语言 |
我的github | 我的简书 | 我的CSDN | 个人网站 |
3.声明
1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持
网友评论