目录
一,流结构分析
1,字节流
1.InputStream
1.FileInputStream
2.OutputStream
1.FileOutputStream
3.边读边写俗称---拷贝
1.拷贝单个文件
2.拷贝文件夹
4.字节缓冲输入流
1.BufferedInputStream
1.缓冲流拷贝
2.readLine()
3.newLine()
--------------------字符流四种拷贝方式代码------------------------
2.字符流
1.Reader
1.BufferedReader
2.InputStreamReader
FileReader
2.Writer
1.BufferedWriter
2.OutputStreamWriter
FileWriter
3.序列化流
1.ObjectOutputStream
2.ObjectInputStream
3. 细节
4.打印流
1.字节打印流
2.字符打印流
5.解压缩流
ZipStream
6.爬取数据
注:标红为警告,标蓝为解释,后期想到的细节持续更新中!!!
对IO---非常非常非常非常非常---的两个工具包的安装方式在下面,能省去很多不必要的代码,详细解释里面也有
这两个包真的非常有用,一定要安装!!!https://blog.csdn.net/m0_71149935/article/details/134659863?spm=1001.2014.3001.5501
(所有编译时期异常直接抛出)
FileInputStream可以做到单个字节的读取和写入,也可以定义一个byte数组来设置自己想要的速度如下:(这里需要注意,一定要关闭释放资源,否则会有各种小麻烦)
这里的lon是记录读取的值,为什么要记录呢?原因如下:
read方法会在读取时光标移动到读取到的末尾,如果再次在循环体里面打印fr.read系统会读取两次,单只打印sout里面的也就是偶数次。
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class dome6 {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("IO\\a.txt");
int lon;
char[] c=new char[2];
while ((lon=fr.read(c))!=-1) {
System.out.print(new String(c,0,lon));
}
fr.close();
}
}
FileOutputStream也可以一次写入多个字节,方法同上类似!
写入这里有个注意点:没写入的父级路径必须存在,自己路径可以没有,没有的话系统会自己创建。
特别注意!!!
有的话系统会先清空再写入!!!!!!!!!!!!
第一次设置为true写入
第二次写入时第一次的9未被清空
如果想不清空就得在bool参数里面设置true
一定要先关后开的,后关先开的,只要用不到了就马上释放资源!!!!!!
举例如下:
(不用考虑空的清空,因为文件不可能为空,直接边读边写就完事了)
注意:1.为这里会解释IO模块下的一个txt文件,IO是相对路径。
2.拷贝时我用了上面提到的设置每次读取的字节数,我设置为5兆每次
3.及时关闭资源,先开后关原则
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Cope {
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("IO\\a.txt");
FileOutputStream fos=new FileOutputStream("IO\\f.txt");
int len;
byte[] b=new byte[1024*1024*5];
while ((len=fis.read())!=-1){
fos.write(b,0,len);
}
fos.close();
fis.close();
}
}
(需要考虑文件夹是否为空,为空的话拷贝会有异常,所以要做非空判断)
这里有一个递归算法,如果是文件夹的话就得进入文件夹再次判断,递归出口是:直到读取到文件return
import java.io.*;
public class Cope1 {
public static void main(String[] args) throws IOException {
//此处路径可自行修改为自己路径
//创建要拷贝的对象
File api=new File("D:\\API");
//创建要拷贝到的对象
File dest=new File("D:\\dest");
cope(api,dest);
}
//设置方法拷贝文件夹
public static void cope(File API, File dest) throws IOException {
//如果文件不存在就创建
dest.mkdirs();
//得到file里面的所有文件和文件夹
File[] files = API.listFiles();
for (File file : files) {
//判断是不是文件,分情况讨论
if (file.isFile()) {
//创建要拷贝的对象
FileInputStream fis = new FileInputStream(file);
//创建要拷贝到的对象
FileOutputStream fos = new FileOutputStream(new File(dest, file.getName()));
//这里设置读取速度,以字节为单位,可自行设置,不建议太快,容易卡爆内存
byte[] b = new byte[1024];
int lon;
while ((lon = fis.read(b)) != -1) {
fos.write(b, 0, lon);
}
fos.close();
fis.close();
} else {
cope(file, new File(dest, file.getName()));
}
}
}
}
他是在底层对字节输入输出流做了改进,让读取效率提高,通过源码可以看出Java在底层自己定义了一个大小为8192字节的byte数组(一定是字节,因为后面的字符缓冲流是字符,一字符是两个字节)
因为他和字节流很像,这里就用一个简单拷贝来理解
BufferedInputStream的参数是一个字节输入输出流的对象,也可以定义在外面让代码方便阅读,定义在里面简化代码都可以
import java.io.*;
public class BufferedStreamDome1 {
public static void main(String[] args) throws IOException {
BufferedInputStream bsi=new BufferedInputStream(new FileInputStream("IO\\a.txt"));
BufferedOutputStream bso=new BufferedOutputStream(new FileOutputStream("IO\\f.txt"));
int i;
while ((i=bsi.read())!=-1) {
bso.write(i);
}
bso.close();
bsi.close();
}
}
它里面有一个独特的方法可以一次读取一整行数据且不读取换行符。
我a.txt里面提亲写入了一首歌词,
姑娘别哭泣 (懒羊羊版) - 懒大王
词:柯柯柯啊
曲:柯柯柯啊
突来的消息 那个人是你
这么多年 你杳无音讯
时间的橡皮 擦掉了记忆
但我迟迟 都没有忘记你
秒针的声音 嘀嗒转不停
我的心里 住着一个你
流过的泪滴 全都因为你
原来迟迟都 不曾放下你
或许我们 就不该有段因果
或许我不该 一味求施舍
如果有天 我离开了你的生活
如果有天 你还爱着我
姑娘为何你要放声哭泣
我在路那旁小河等你
你心里到底藏了什么秘密
我想紧紧的抱住你
你说遇到的人全都像你
找不到失去你的意义
你说你克制着不再想起
可是我就在你心里
秒针的声音 嘀嗒转不停
我的心里 住着一个你
流过的泪滴 全都因为你
原来迟迟都 不曾放下你
或许我们就不该有段因果
或许我不该 一味求施舍
如果有天我离开了 你的生活
如果有天 你还爱着我
姑娘为何你要放声哭泣
我在路那旁小河等你
你心里到底藏了什么秘密
我想紧紧的抱住你
你说遇到的人全都像你
找不到失去你的意义
你说你克制着不再想起
可是我就在你心里
两条打印语句运行结果
最后循环读取所有数据
它就是一个可以检测你电脑系统的方法,根据你的电脑系统帮你配置你的换行符\r\n,\r和\n
import java.io.*;
public class dome9 {
public static void main(String[] args) throws IOException {
// Cope1();
// Cope2();
// Cope3();
// Cope4();
}
public static void Cope1() throws IOException {
FileInputStream fis = new FileInputStream("IO\\a.txt");
FileOutputStream fos = new FileOutputStream("IO\\c.txt");
int i;
while ((i = fis.read()) != -1) {
fos.write(i);
}
fos.close();
fis.close();
}
public static void Cope2() throws IOException {
FileInputStream fis = new FileInputStream("IO\\a.txt");
FileOutputStream fos = new FileOutputStream("IO\\c.txt");
int i;
byte[] bytes = new byte[8192];
while ((i = fis.read(bytes)) != -1) {
fos.write(bytes, 0, i);
}
fos.close();
fis.close();
}
public static void Cope3() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("IO\\a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("IO\\c.txt"));
int i;
while ((i = bis.read()) != -1) {
bos.write(i);
}
bos.close();
bis.close();
}
public static void Cope4() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("IO\\a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("IO\\c.txt"));
int i;
byte[] bytes = new byte[8192];
while ((i = bis.read(bytes)) != -1) {
bos.write(bytes, 0, i);
}
bos.close();
bis.close();
}
}
简称:字符缓冲输入流
由于他和字节缓冲流基本一致,这里不过多赘述,上代码理解即可下面BufferedWriter和这里一样
代码可以检测文件运行次数和限制文件运行次数
这里要保证c.txt里面有一个数据是0且没有任何换行
import java.io.*;
public class dome10 {
public static void main(String[] args) throws IOException {
BufferedReader br=new BufferedReader(new FileReader("IO\\c.txt"));
String string = br.readLine();
int i = Integer.parseInt(string);
i++;
if (i<=3) {
System.out.println("第"+i+"次运行");
}else {
System.out.println("运行已经超过三次,请充值会员");
}
BufferedWriter bw=new BufferedWriter(new FileWriter("IO\\c.txt"));
bw.write(i+"");
bw.close();
br.close();
}
}
简称:转换流
就是把字节流转换成字符流进行读取,属于中间加工的一个类
注:为了可读性更强,我把对象的创建都写在了外面,也可以写在里面,上面三行一句搞定
BufferedReader br2=new BufferedReader(new InputStreamReader(new FileInputStream("IO\\a.txt")));
import java.io.*;
public class dome11 {
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("IO\\a.txt");
InputStreamReader isr=new InputStreamReader(fis);
BufferedReader br=new BufferedReader(isr);
String str;
while ((str=br.readLine())!=null){
System.out.println(str);
}
br.close();
}
}
转换流,可以指定转换的编码格式
用对应的编码格式读取,再用你想要的编码格式写入
import java.io.*;
import java.nio.charset.Charset;
public class dome_转换流 {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("IO\\\\b.txt", Charset.forName("UTF-8"));
int i;
while ((i=fr.read())!=-1){
System.out.print((char) i);
}
fr.close();
FileWriter fw=new FileWriter("IO\\\\d.txt", Charset.forName("UTF-8"));
fw.write("你好你好");
fw.close();
}
}
---------------------------------同BufferedReader(2.1.1)----------------------------------------
可以写入一整行数据,也可以选择一整行数据里面的一部分
1write里面的1和2分别表示开始写入的索引和要写入的字符数
import javax.imageio.IIOException;
import java.io.FileWriter;
import java.io.IOException;
public class dome7 {
public static void main(String[] args) throws IOException {
FileWriter fw=new FileWriter("IO\\a.txt",true);
String str="大家都是高手。。";
fw.write(str,1,2);
fw.close();
}
}
序列化流可以序列化对象,把对象当做数据存入文件中实现永久保存,(可以运用到主页的学生管理系统和拼图游戏的注册和登录实现数据的存储)
Java的面向对象里面万物皆对象,该类可以把对象写到文件当中保存
实例如下:(老规矩,异常直接抛出,及时释放资源!!!)
这里我已经事先创建了学生类对象
注意:ObjectOutputStream里面创建的FileOutputSrteam对象不需要释放资源,因为在关闭ObjectOutputStream的时候Java底层会帮我们一起关闭。
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
public class dome1 {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("IO\\e.txt"));
Student student1=new Student("zhangsan",23);
Student student2=new Student("lisi",23);
Student student3=new Student("gsan",23);
ArrayList list= new ArrayList<>();
list.add(student1);
list.add(student2);
list.add(student3);
oos.writeObject(list);
oos.close();
}
}
写进去的目的就是保存方便以后读取,所以这里ObjectInputStream就是用来读的。
他的返回值是一个Object类,我强转成student类存入集合打印输出,如下:
import java.io.*;
import java.util.ArrayList;
public class dome2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("IO\\e.txt"));
ArrayList list = (ArrayList) ois.readObject();
for (Student student : list) {
System.out.println(student);
}
ois.close();
}
}
这里被序列的类需要有序列号,不然后期修改之后会不可使用而出现异常,比如在类里面添加一个新的属性就不行,序列号可以手动添加,语句是(
private static final long serialVersionUID = 1L;
)但不推荐。
推荐使用系统计算出来的,方法如下:(我这是中文版,英文版需要的话私我即可,不在此处添加了)
注意:打印流只有输出流,只能写不能读,并且他是原样写出,
特点:自动刷新,换行
printStream自动刷新,不换行
printlnStream:自动刷新,自动换行
printfStream:自动刷新,不换行
printWriter
和字节打印流类似,不过多了一个缓冲区,缓冲区前面缓冲记过,就是底层定义了一个char[8192]数组,自动刷新需要自己开启
参数同上字节打印流。
(他只认识.zip结尾的压缩文件)
ZipInputStream
首先,你得有一个.zip的压缩文件
然后可以通过ZipInputStream对象来获取文件里的所有文件夹和文件并打印他们
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
public class ZipInputStream {
public static void main(String[] args) throws IOException {
File file1=new File("C:\\Users\\86199\\Desktop\\super mario.zip");
File file2=new File("D:\\");
Zip(file1,file2);
}
public static void Zip(File file1,File file2) throws IOException {
java.util.zip.ZipInputStream zis = new java.util.zip.ZipInputStream(new FileInputStream(file1));
ZipEntry nextEntry ;
while ((nextEntry=zis.getNextEntry())!=null){
System.out.println(nextEntry);
}
zis.close();
}
}
注:此处路径可以修改 (可以当做一个小练习做着玩)
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
public class ZipInputStream {
public static void main(String[] args) throws IOException {
File file1=new File("C:\\Users\\86199\\Desktop\\super mario.zip");
File file2=new File("D:\\解压缩流");
Zip(file1,file2);
}
public static void Zip(File file1,File file2) throws IOException {
java.util.zip.ZipInputStream zis = new java.util.zip.ZipInputStream(new FileInputStream(file1));
ZipEntry nextEntry ;
while ((nextEntry=zis.getNextEntry())!=null){
System.out.println(nextEntry);
//是文件夹
if (nextEntry.isDirectory()) {
//要存放的文件路径和被读取的文件夹路径
File file=new File(file2,nextEntry.toString());
//直接在该路径下创建文件夹
file.mkdirs();
}else {
//不是文件夹,直接拷贝
FileOutputStream fos=new FileOutputStream(new File(file2,nextEntry.toString()));
int i;
while ((i=zis.read())!=-1) {
fos.write(i);
}
fos.close();
//在压缩包中一个文件处理完毕
zis.closeEntry();
}
}
zis.close();
}
}
URL可以跟网址建立联系只要建立一个URL的对象就可以了
(这里要用到正则表达式,后面文章具体讲解,先用着)
我爬取的是百家姓的姓氏:(网址可以自己修改,爬取是必须网址能够访问,且设备有网络连接)
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class UIR {
public static void main(String[] args) throws IOException {
String str1="https://hanyu.baidu.com/shici/detail?from=aladdin&pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&showPinyin=1";
String regex="(.{4})(,|。)";
ArrayList data = getData(str1, regex,1);
System.out.println(data);
}
public static ArrayList getData(String str,String regex,int index) throws IOException {
ArrayList list=new ArrayList<>();
String url = Url(str);
Pattern compile = Pattern.compile(regex);
Matcher matcher = compile.matcher(url);
while (matcher.find()){
list.add(matcher.group(index));
}
return list;
}
public static String Url(String s) throws IOException {
URL url=new URL(s);
URLConnection urlConnection = url.openConnection();
InputStreamReader isr=new InputStreamReader(urlConnection.getInputStream());
StringBuilder sb=new StringBuilder();
int i;
while ((i= isr.read())!=-1){
sb.append((char) i);
}
isr.close();
return sb.toString();
}
}
=============================后续持续更新中================================
有空闲时间可以在这里跳转到拼图小游戏,里面会涉及IO的账户存储https://blog.csdn.net/m0_71149935/article/details/134591997?spm=1001.2014.3001.5502https://blog.csdn.net/m0_71149935/article/details/134591997?spm=1001.2014.3001.5502
既然都看到这里了,留个点赞关注再走吧铁子,相信对你有用!!!!!!!!!!!!!!!