Java笔记_18
- 一、IO流
- 1.1、IO流的概述
- 1.2、IO流的体系
- 1.3、字节输出流基本用法
- 1.4、字节输入流基本用法
- 1.5、文件拷贝
- 1.6、IO流中不同JDK版本捕获异常的方式
- 二、字符集
- 2.1、GBK、ASCII字符集
- 2.2、Unicode字符集
- 2.3、为什么会有乱码
- 2.4、Java中编码和解码的代码实现
- 2.5、字符输入流
- 2.5、字符输出流
- 2.6、字符流输入流原理解析
- 2.7、字符流输出流原理解析
- 三、字节流字符流综合案例
- 3.1、拷贝文件夹
- 3.2、文件加密
- 3.3、修改文件中的数据
- 四、缓冲流
- 4.1、字节缓冲流
- 4.2、字节缓冲流提升效率的原理
- 4.3、字符缓冲流
- 4.4、练习-四种拷问方式效率对比
- 4.5、练习-修改文本顺序
- 4.6、练习-软件运行的次数
- 五、转换流
- 5.1、转换流的基本用法
- 5.2、转换流练习
一、IO流
1.1、IO流的概述
IO流:存储和读取数据的解决方案
- 用于读写文件中的数据(可以读写文件,或网络中的数据…)
纯文本文件: - 用windows系统自带的记事本打开并且能读懂的文件
1.2、IO流的体系
1.3、字节输出流基本用法
FileoutputStream
- 操作本地文件的字节输出流,可以把程序中的数据写到本地文件中。
书写步骤:
- 创建字节输出流对象
- 细节1:参数是字符串表示的路径或者是File对象都是可以的
- 细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的。
- 细节3:如果文件已经存在,则会清空文件
- 写数据
- 细节: write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符
- 释放资源
- 每次使用完流之后都要释放资源
FileOutputStream写数据的3种方式:
方法名称 | 说明 |
---|---|
void write(int b) | 一次写一个字节数据 |
void write(byte[ ] b) | 一次写一个字节数组数据 |
void write(byte[ ] b, int off, int len) | 一次写一个字节数组的部分数据 |
package IO;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Dome2 {
public static void main(String[] args) throws IOException {
File f = new File("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\a.txt");
FileOutputStream fos = new FileOutputStream(f);
//第一种写法
fos.write(97);
fos.write(98);
//第二种写法
byte[] bytes = {97,98,99,100,101,102,103};
fos.write(bytes);
//第三种写法
fos.write(bytes,0,6);
}
}
FileOutputStream写数据换行写和续写:
换行:
- Windows操作系用下,换行符是
\r\n
- Linux操作系用下,换行符是
\n
- Mac操作系统下,换行符是
\r
- 细节:
在windows操作系统当中,java对回车换行进行了优化。虽然完整的是\r\n
,但是我们写其中一个\r
或者\n
,java也可以实现换行,因为java在底层会补全。 - 建议:
不要省略,还是写全了。
续写:
- 如果想要续写,打开续写开关即可开关
- 位置:创建对象的第二个参数
- 默认
false
:表示关闭续写,此时创建对象会清空文件 - 手动传递
true
:表示打开续写,此时创建对象不会清空文件
- 默认
package IO;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Dome3 {
public static void main(String[] args) throws IOException {
/*
* Windows操作系用下,换行符是\r\n
* Linux操作系用下,换行符是\n
* Mac操作系统下,换行符是\r
*
*细节:
在windows操作系统当中,java对回车换行进行了优化。虽然完整的是\r\n,
但是我们写其中一个\r或者\n,java也可以实现换行,因为java在底层会补全。
建议:
不要省略,还是写全了。
续写:
* 如果想要续写,打开续写开关即可开关
位置:创建对象的第二个参数
默认false:表示关闭续写,此时创建对象会清空文件
手动传递true:表示打开续写,此时创建对象不会清空文件
* */
FileOutputStream fos = new FileOutputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\a.txt"
,true);
String str = "woshiyigeliangzai";
byte[] bytes1 = str.getBytes();
fos.write(bytes1);
String str2 = "\r\n";
byte[] bytes2 = str2.getBytes();
fos.write(bytes2);
String str3 = "666";
byte[] bytes3 = str3.getBytes();
fos.write(bytes3);
fos.close();
}
}
1.4、字节输入流基本用法
操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中来。
书写步骤:
- 创建字节输入流对象
- 如果文件不存在,就直接报错
- 读数据
- 一次读一个字节,读出来的是数据在ASCIl上对应的数字
- 读到文件末尾了,read方法返回-1。
- 释放资源
- 每次使用完流之后都要释放资源
package IO;
import java.io.FileInputStream;
import java.io.IOException;
public class Dome4 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\a.txt");
//读取第一个数据
int read = fis.read();
System.out.println((char) read);
//读取第二数据
int read1 = fis.read();
System.out.println((char) read1);
//...
int read2 = fis.read();
System.out.println((char) read2);
int read3 = fis.read();
System.out.println((char) read3);
int read4 = fis.read();
System.out.println((char) read4);
//如果当前读取的数据不存在,则会返回-1
int read5 = fis.read();
System.out.println((char) read5);//-1
fis.close();
}
}
FileInputStream循环读取:
- 每执行一次
read()
方法,就会移动一次指针
package IO;
import java.io.FileInputStream;
import java.io.IOException;
public class Dome5 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\a.txt");
while (true) {
//每执行一次read()方法,就会移动一次指针
//所以在代码里面只能进行一次read()方法
int read = fis.read();
if(read==-1){
break;
}
System.out.print((char) read);
}
fis.close();
}
}
1.5、文件拷贝
文件拷贝的基本用法
package IO;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Dome6 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\copy.txt");
FileInputStream fis = new FileInputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\a.txt");
long startTime = System.currentTimeMillis();
while (true){
int read = fis.read();
if(read == -1){
break;
}
fos.write(read);
}
long endTime = System.currentTimeMillis();
//获取程序运行的时间
System.out.println(endTime-startTime);
//后创建的对象,先结束
fis.close();
fos.close();
}
}
文件拷贝的弊端:
FileInputStream一次读多个字节
方法名称 | 说明 |
---|---|
public int read() | 一次读一个字节数据 |
public int read(byte[ ] buffer) | 一次读一个字节数组数据 |
注意: 一次读一个字节数组的数据,每次读取会尽可能把数组装满
package IO;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//"""
public class Dome8 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\高数\\讲课视频\\2023-02-17 08-40-40.mkv");
FileOutputStream fos = new FileOutputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\copy.mkv");
byte[] bytes = new byte[1024*1024*5];
int len;
while ((len = fis.read(bytes))!=-1){
fos.write(bytes,0,len);
}
/*
while (true){
int read = fis.read(bytes);
if(read ==-1){
break;
}
fos.write(bytes,0,read);
}
*/
fos.close();
fis.close();
}
}
1.6、IO流中不同JDK版本捕获异常的方式
- JDK7方案必须要有
AutoCloseable
接口
JDK7 抛出异常处理
package IO;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//"""
public class Dome9_JDK7_try_catch {
public static void main(String[] args){
byte[] bytes = new byte[1024*1024*5];
try (FileInputStream fis = new FileInputStream("D:\\高数\\讲课视频\\2023-02-17 08-40-40.mkv");
FileOutputStream fos = new FileOutputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\copy.mkv");
){
int len;
while ((len = fis.read(bytes))!=-1){
fos.write(bytes,0,len);
}
}catch (IOException e){
e.printStackTrace();
}
}
}
JDK9 抛出异常处理
package IO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//JDK9 抛出异常练习
public class Dome10_JDK9_try_catch {
public static void main(String[] args) throws FileNotFoundException {
byte[] bytes = new byte[1024*1024*5];
FileInputStream fis = new FileInputStream("D:\\高数\\讲课视频\\2023-02-17 08-40-40.mkv");
FileOutputStream fos = new FileOutputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\copy.mkv");
try (fis;fos){
int len;
while ((len = fis.read(bytes))!=-1){
fos.write(bytes,0,len);
}
}catch (IOException e){
e.printStackTrace();
}
}
}
二、字符集
2.1、GBK、ASCII字符集
- GB2312字符集: 1980年发布,1981年5月1日实施的简体中文汉字编码国家标准。收录7445个图形字符,其中包括6763个简体汉字
- BIG5字符集: 台湾地区繁体中文标准字符集,共收录13053个中文字,1984年实施。
- GBK字符集: 2000年3月17日发布,收录21003个汉字。
包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的所有汉字。
Windows系统默认使用的就是GBK。系统显示:ANSI
4. Unicode字符集∶国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换。
计算机的储存规则(汉字)(GBK)
- 汉字两个字节存储
- 高位字节二进制一定以1开头,转成十进制之后是个负数
计算机的储存规则(英文)(GBK)
- 英文一个字节存储,兼容ASCII,二进制前面补0
2.2、Unicode字符集
- 研发方:统一码联盟(也叫Unicode组织)
- 总部位置:美国加州
- 研发时间:1990年
- 发布时间:1994年发布1.0版本,期间不断添加新的文字,
最新的版本是2022年9月13日发布的15.0版本。 - 联盟组成:世界各地主要的电脑制造商、软件开发商、数据库开发商、政府部门、研究机构、国际机构、及个人组成
UTF:Unicode Transfer Format
- UTF-16编码规则:用2~4个字节保存
- UTF-32编码规则:固定使用四个字节保存
- UTF-8编码规则:用1~4个字节保存
- 一个英文占一个字节,二进制第一位是0,转成十进制是正数
- 一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数
2.3、为什么会有乱码
原因1:读取数据时未读完整个汉字
原因2:编码和解码的规则不相同
如何不产生乱码?
- 不要用字节流读取文本文件
- 编码解码时使用同一个码表,同一个编码方式
2.4、Java中编码和解码的代码实现
Java中编码的方法
String类中的方法 | 说明 |
---|---|
public byte[ ] getBytes() | 使用默认方式进行编码 |
public byte[] getBytes(String charsetName) | 使用指定方式进行编码 |
Java中解码的方法
String类中的方法 | 说明 |
---|---|
String(byte[ ] bytes) | 使用默认方式进行解码 |
String(byte[ ] bytes, String charsetName) | 使用指定方式进行解码 |
package IO_charset;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Dome1 {
public static void main(String[] args) throws UnsupportedEncodingException {
//编码
String str = "this一行文字";
byte[] bytes1 = str.getBytes();
System.out.println(Arrays.toString(bytes1));//[116, 104, 105, 115, -28, -72, -128, -24, -95, -116, -26, -106, -121, -27, -83, -105]
byte[] bytes2 = str.getBytes("GBK");
System.out.println(Arrays.toString(bytes2));//[116, 104, 105, 115, -46, -69, -48, -48, -50, -60, -41, -42]
//解码
//采用相同的规则进行解码
String s1 = new String(bytes1);
System.out.println(s1);//this一行文字
//采用不用的规则进行解码
String s2 = new String(bytes1,"GBK");
System.out.println(s2);//this涓�琛屾枃瀛�
String s3 = new String(bytes2,"GBK");
System.out.println(s3);//this一行文字
}
}
2.5、字符输入流
字符流底层其实就是字节流
字符流 = 字节流+字符集
特点:
- 输入流:一次读一个字节,遇到中文时,一次读多个字节
- 输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中
使用场景
对于纯文本文件进行读写操作
FileReader
- 创建字符输入流对象
构造方法 | 说明 |
---|---|
public FileReader(File file) | 创建字符输入流关联本地文件 |
public FileReader(string pathname) | 创建字符输入流关联本地文件 |
细节1:如果文件不存在,就直接报错
- 读取数据
成员方法 | 说明 |
---|---|
public int read() | 读取数据,读到末尾返回-1 |
public int read(char[ ] buffer) | 读取多个数据,读到末尾返回-1 |
细节1:按字节进行读取。遇到中文,一次读多个字节,读取后解码,返回一个整数
细节2:读到文件末尾了, read方法返回-1。
细节3:
- 如果遇到中文就会一次读取多个,GBK一次读两个字节,UTF-8一次读三个字节。
- 在读去之后,方法底层还会进行解码并转成十进制
- 释放资源
成员方法 | 说明 |
---|---|
public int close() | 释放资源/关流 |
空参read()方法
package IO_charset;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Dome2 {
public static void main(String[] args) throws IOException {
//创建对象
FileReader fr = new FileReader("a.txt");
//循环遍历出文件中的字符
int len;
while ((len=fr.read())!=-1){
System.out.print((char)len);
}
//关流
fr.close();
}
}
带参read()方法
package IO_charset;
import java.io.FileReader;
import java.io.IOException;
public class Dome3 {
public static void main(String[] args) throws IOException {
//定义一个数组,一次性查找3个元素
char[] chars = new char[3];
//定义一个变量来记录数组存储数据的长度
int ch;
FileReader fr = new FileReader("a.txt");
//循环遍历出每一个数据
//read(chars):读取数据,解码,强转三步合并了,把强转之后的字符放到数组当中
//空参的read +强转类型转换
while ((ch = fr.read(chars))!=-1){
//使用系统默认的编码规则
System.out.print(new String(chars,0,ch));
}
fr.close();
}
}
2.5、字符输出流
FileWriter构造方法
构造方法 | 说明 |
---|---|
public Filewriter(File file) | 创建字符输出流关联本地文件 |
public Filewriter(String pathname) | 创建字符输出流关联本地文件 |
public Filewriter(File file,boolean append) | 创建字符输出流关联本地文件,续写 |
public Filewriter(String pathname,boolean append) | 创建字符输出流关联本地文件,续写 |
成员方法
成员方法 | 说明 |
---|---|
void write(int c) | 写出一个字符 |
void write(String str) | 写出一个字符串 |
void write(string str, int off, int len) | 写出一个字符串的一部分 |
void write(char[ ] cbuf) | 写出一个字符数组 |
void write(char[ ] cbuf, int off, int len) | 写出字符数组的一部分 |
- 创建字符输出流对象
- 细节1:参数是字符串表示的路径或者File对象都是可以的
- 细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
- 细节3:如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关
- 写数据
- 细节:如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集上对应的字符
- 释放资源
- 每次使用完流之后都要释放资源
package IO_charset;
import java.io.FileWriter;
import java.io.IOException;
public class Dome4 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("a.txt",true);
fw.write("\n这是第六段中文");
char[] chars = {'\n','这','是','第','七','段','中','文'};
fw.write(chars);
fw.write(chars,0,3);
fw.write("\n这是第八段中文",4,4);
fw.write(97);
fw.close();
}
}
2.6、字符流输入流原理解析
-
创建字符输入流对象
底层:关联文件,并创建缓冲区(长度为8192的字节数组)
-
读取数据
底层:
1. 判断缓冲区中是否有数据可以读取
2. 缓冲区没有数据:就从文件中获取数据,装到缓冲区中,每次尽可能装满缓冲区,如果文件中也没有数据了,返回-1
3. 缓冲区有数据:就从缓冲区中读取。
空参的read方法:一次读取一个字节,遇到中文一次读多个字节,把字节解码并转成十进制返回
有参的read方法:把读取字节,解码,强转三步合并了,强转之后的字符放到数组中
2.7、字符流输出流原理解析
成员方法 | 说明 |
---|---|
public void flush() | 将缓冲区中的数据,刷新到本地文件中 |
public void close() | 释放资源/关流 |
- flush刷新:刷新之后,还可以继续在文件中写出数据
- close关流:断开通道,无法再往文件中写出数据
package IO_charset;
import java.io.FileWriter;
import java.io.IOException;
public class Dome4 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("a.txt",true);
fw.write("\n这是第六段中文");
char[] chars = {'\n','这','是','第','七','段','中','文'};
fw.write(chars);
fw.flush();
fw.write(chars,0,3);
fw.write("\n这是第八段中文",4,4);
fw.write(97);
fw.close();
}
}
三、字节流字符流综合案例
字节流和字符流的使用场景
- 字节流
- 拷贝任意类型的文件
- 字符流
- 读取纯文本文件中的数据
- 往纯文本文件中写出数据
3.1、拷贝文件夹
package IO_Test;
import java.io.*;
public class Test1 {
public static void main(String[] args) throws IOException {
// aaa
// aac
File f1 = new File("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\aac");
File f2 = new File("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\aad");
CopyFile(f1,f2);
}
public static void CopyFile(File f1,File f2) throws IOException {
f2.mkdirs();
//进入数据源
File[] files = f1.listFiles();
//遍历数组
for (File file : files) {
if (file.isFile()){
//判断文件,拷贝
FileInputStream fis = new FileInputStream(f1);
FileOutputStream fos = new FileOutputStream(new File(f2,file.getName()));
byte[] bytes = new byte[2];
int len;
while ((len = fis.read(bytes)) != -1){
fos.write(bytes,0,len);
}
fos.close();
fis.close();
}else {
//判断文件夹,递归
CopyFile(file,new File(f2,file.getName()));
}
}
}
}
3.2、文件加密
^
:异或
两边相同:false
两边不同:true
package IO_Test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test2 {
public static void main(String[] args) throws IOException {
//创建对象关联原始文件
FileInputStream fis = new FileInputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\src\\IO_Test\\zxc.txt");
//创建对象关联加密文件
FileOutputStream fos = new FileOutputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\src\\IO_Test\\asd.txt");
//加密处理
int b;
while ((b=fis.read())!=-1){
fos.write(b^2);
}
fos.close();
fis.close();
}
}
3.3、修改文件中的数据
方法一:
package IO_Test;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
public class Test3 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\src\\IO_Test\\aaab.txt");
FileReader fr = new FileReader("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\src\\IO_Test\\aaaa.txt");
//提取出了aaaa里面的数据
StringBuilder sb = new StringBuilder();
int len;
while ((len = fr.read())!= -1){
sb.append((char) len);
}
fr.close();
System.out.println(sb);
//排序
Integer[] integers = Arrays.stream(sb.toString()
.split("-"))
.map(Integer::parseInt)
.sorted()
.toArray(Integer[]::new);
//写出
String s = Arrays.toString(integers).replace(", ","-");
String result = s.substring(1,s.length()-1);
System.out.println(result);//1-2-4-7-8-9
fw.write(result);
fw.close();
}
}
方法二:
package IO_Test;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
public class Test4 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("src\\IO_Test\\aaaa.txt");
//得到字符串
StringBuilder sb = new StringBuilder();
int len;
while ((len=fr.read())!=-1){
sb.append((char) len);
}
System.out.println(sb);
//排序
String s = sb.toString();
String[] str = s.split("-");
ArrayList<Integer> list = new ArrayList<>();
for (String s1 : str) {
int i = Integer.parseInt(s1);
list.add(i);
}
list.sort((o1,o2)->o1-o2);
System.out.println(list);
//写出
FileWriter fw = new FileWriter("src\\IO_Test\\aaab.txt");
for (int i = 0; i < list.size(); i++) {
if (i==list.size()-1){
fw.write( list.get(i)+"");
}else {
fw.write(list.get(i)+"-");
}
}
fw.close();
fr.close();
}
}
- 细节:在使用系统其他文件夹下的文件时,要查看是否有BOM头
如果有BOM头的文件,idea在读取时,前三个字节会被BOM头占用
在idea中创建的文件默认不带BOM头
四、缓冲流
4.1、字节缓冲流
方法名称 | 说明 |
---|---|
public BufferedInputstream( InputStream is) | 把基本流包装成高级流,提高读取数据的性能 |
public BufferedOutputStream(OutputStream os) | 把基本流包装成高级流,提高写出数据的性能 |
package IO.IO_BufferedStream;
import java.io.*;
public class Dome1 {
public static void main(String[] args) throws IOException {
//创建两个缓冲流
BufferedInputStream bip = new BufferedInputStream(new FileInputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\src\\IO_Test\\aaaa.txt"));
BufferedOutputStream bop = new BufferedOutputStream(new FileOutputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\src\\IO_Test\\aaab.txt"));
//进行遍历数据
int len;
while ((len = bip.read())!=-1){
bop.write(len);
}
//关流
bop.close();
bip.close();
}
}
- 底层会创建一个8192大的字节数组
4.2、字节缓冲流提升效率的原理
- 缓冲流可以使两个缓冲区的数据来回交换,加快了两边缓冲区的交换速度
4.3、字符缓冲流
方法名称 | 说明 |
---|---|
public BufferedReader(Reader r) | 把基本流变成高级流 |
public BufferedWriter(Writer r) | 把基本流变成高级流 |
特有方法:
字符缓冲输入流特有方法 | 说明 |
---|---|
public string readLine() | 读取一行数据,如果没有数据可读了,会返回null |
字符缓冲输出流特有方法 | 说明 |
---|---|
public void newLine() | 跨平台的换行 |
package IO.IO_BufferedStream;
import java.io.*;
public class Dome2 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("src\\IO_Test\\aaaa.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("src\\IO_Test\\aaab.txt"));
//一次性输入一行
//String s = br.readLine();
//System.out.println(s);
String s ;
while ((s = br.readLine())!=null){
//输出的时候需要打印换行
bw.write(s);
bw.newLine();
}
bw.close();
br.close();
}
}
4.4、练习-四种拷问方式效率对比
package IO_Test;
import java.io.*;
public class Text5 {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
File f1 = new File("src\\IO_Test\\aaaa.txt");
File f2 = new File("src\\IO_Test\\aaab.txt");
method4(f1,f2);
long end = System.currentTimeMillis();
System.out.println("用了"+ (end - start)+"毫秒");
}
public static void method1(File f1, File f2) throws IOException {
FileInputStream fis = new FileInputStream(f1);
FileOutputStream fos = new FileOutputStream(f2);
int len;
while ((len= fis.read())!=-1){
fos.write((char)len);
}
fos.close();
fis.close();
}//用了9931毫秒
public static void method2(File f1,File f2) throws IOException {
FileInputStream fis = new FileInputStream(f1);
FileOutputStream fos = new FileOutputStream(f2);
byte[] b = new byte[8129];
int len;
while ((len= fis.read(b))!=-1){
fos.write(b,0,len);
}
fos.close();
fis.close();
}//用了19毫秒
public static void method3(File f1,File f2) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f1));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(f2));
int len;
while ((len=bis.read())!=-1){
bos.write((char)len);
}
bos.close();
bis.close();
}//用了136毫秒
public static void method4(File f1,File f2) throws IOException{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f1));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(f2));
int len;
byte[] b = new byte[8129];
while ((len = bis.read(b))!=-1){
bos.write(b,0,len);
}
bos.close();
bis.close();
}//用了8毫秒
}
4.5、练习-修改文本顺序
package IO_Test;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Test6 {
public static void main(String[] args) throws IOException {
//先获取到文本数据
File f1 = new File("src\\IO_Test\\aaaa.txt");
File f2 = new File("src\\IO_Test\\aaab.txt");
BufferedReader br = new BufferedReader(new FileReader(f1));
BufferedWriter bw = new BufferedWriter(new FileWriter(f2));
//将数据添加到集合中
String line;
ArrayList<String> list = new ArrayList<>();
while ((line = br.readLine()) != null){
list.add(line);
}
br.close();
//排序
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//获取o1和o2的序号
int i1 = Integer.parseInt(o1.split("\\.")[0]);
int i2 = Integer.parseInt(o2.split("\\.")[0]);
return i1-i2;
}
});
//写出来
for (String s : list) {
bw.write(s);
bw.newLine();
}
bw.close();
}
}
4.6、练习-软件运行的次数
- IO流原则:随用随创建,什么时候不用什么时候关闭
package IO_Test;
import java.io.*;
public class Test7 {
public static void main(String[] args) throws IOException {
//count需要声明到外部文件中,每次启用代码都会刷新count值
//引入文件
BufferedReader br = new BufferedReader(new FileReader("src\\IO_Test\\Test7.txt"));
String s = br.readLine();
int count = Integer.parseInt(s);
count++;
br.close();
//判断count
if (count<=3){
System.out.println("欢迎使用本软件,第"+count+"次使用免费!");
}else {
System.out.println("本软件只能免费试用3次,欢迎您注册会员后继续使用");
}
BufferedWriter bw = new BufferedWriter(new FileWriter("src\\IO_Test\\Test7.txt"));
bw.write(count+"");
bw.close();
}
}
五、转换流
5.1、转换流的基本用法
转换流的名字:
转换输出流:InputStreamReader
转换输入流:OutputStreamWriter
- 是字符流和字节流之间的桥梁
作用:
- 指定字符集读写(淘汰了)
- 字节流想要使用字符流中的方法
- 把GBK编码规则的文件在UTF-8的环境中打印出来
package IO.IO_ConverStream;
import java.io.*;
import java.nio.charset.Charset;
public class Dome1 {
public static void main(String[] args) throws IOException {
/*
JDK11之后就淘汰了
把GBK编码规则的文件在UTF-8的环境中打印出来
//"C:\Users\20265\Desktop\ConverDome1.txt"
InputStreamReader isr =new InputStreamReader(new FileInputStream("C:\\Users\\20265\\Desktop\\ConverDome1.txt"),"GBK");
//得到里面的数据
int len;
while ((len = isr.read())!=-1){
System.out.print((char) len);
}
isr.close();
*/
//JDK11之后使用的方式
FileReader fr = new FileReader(new File("C:\\\\Users\\\\20265\\\\Desktop\\\\ConverDome1.txt"), Charset.forName("GBK"));
//得到里面的数据
int len;
while ((len = fr.read())!=-1){
System.out.print((char) len);
}
fr.close();
}
}
- 利用转换流按照指定字符编码写出
package IO.IO_ConverStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
public class Dome2 {
public static void main(String[] args) throws IOException {
//利用转换流按照指定字符编码写出
FileWriter fw = new FileWriter("C:\\\\Users\\\\20265\\\\Desktop\\\\ConverDome2.txt", Charset.forName("GBK"));
fw.write("你好你好");
fw.close();
}
}
- 将本地里的GBK文件转换成UTF-8文件
package IO.IO_ConverStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
public class Dome3 {
package IO.IO_ConverStream;
import java.io.*;
import java.nio.charset.Charset;
public class Dome3 {
public static void main(String[] args) throws IOException {
/*
*
InputStreamReader isr = new InputStreamReader(new FileInputStream("src\\IO\\IO_ConverStream\\a.txt"),"GBk");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("src\\IO\\IO_ConverStream\\b.txt"),"UTF-8");
* */
FileReader fr = new FileReader("src\\IO\\IO_ConverStream\\a.txt", Charset.forName("GBK"));
FileWriter fw = new FileWriter("src\\IO\\IO_ConverStream\\b.txt",Charset.forName("UTF-8"));
int len;
while ((len= fr.read())!=-1){
fw.write((char)len);
}
fw.close();
fr.close();
}
}
5.2、转换流练习
- 字节流在读取中文的时候,会出现乱码,但是字符流可以搞定
- 字节流里面是没有读一整行的方法的,只有字符缓冲流才可以搞定
package IO.IO_ConverStream;
import java.io.*;
public class Dome4 {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\src\\IO_Test\\aaab.txt"));
BufferedReader br = new BufferedReader(isr);
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\Java\\IDEA\\代码文件\\After_pintu_again\\src\\IO\\IO_ConverStream\\b.txt"));
BufferedWriter bw = new BufferedWriter(osw);
String len;
while ((len = br.readLine())!= null){
bw.write(len);
bw.newLine();
}
br.close();
bw.close();
}
}