Java基础之IO流(持续更新中)
IO流字符流的读写
因为不断向上抽取,所以功能变得不具体了,很抽象,形成了抽象类。所以要看父类,一看就知道是做什么用的。用子类,子类有很多具体的功能。
import java.io.FileWriter; import java.io.IOException; public class FileWriterDemo {private static final String LINE_SEPARATOR = System.getProperty("line.separator");//解决不同操作平台写入换行问题 public static void main(String[] args) throws IOException {FileWriter fileWriter = new FileWriter("abc.txt",true);//创建FileWriter对象,构造函数填写目的地,true代表可以续写,不覆盖 fileWriter.write("456" + LINE_SEPARATOR + "789");//写到缓存区中一个字符串 fileWriter.flush();//刷出缓冲区,写到硬盘中 fileWriter.close();//关闭,关闭前会调用一次flush方法。因为写的功能调用的是windows的系统资源,所以用完了要关了,但关了再写就不能写了 //想象一下记事本 //write就像写了后没保存,断电后就没了 //flush就相当于保存操作,把你写到内存的东西保存到了硬盘 //close就相当于关闭了记事本,但是关闭时候提示了你保存(关闭前保存) } }
执行完成后,看一下
写完事了,在玩一下读。读的话用的哪个类,猜也能猜的差不多。FileReader
首先是一个字符一个字符读,这个比较简单,就是读到了就返回,都不到就返回-1
public class FileReaderDemo {public static void main(String[] args) throws IOException {FileReader fileReader = new FileReader("abc.txt");//读这个文件 int c;//用于接收单个字符 while((c = fileReader.read()) != -1)//如果当前读到的字符不是-1,就一直读。-1是规定的没读到的标识 {System.out.print((char)c);//读到后转一下显示 }} }
一个一个读不爽?一堆一堆读!
这是我们要读取的文件
这是读的源码
FileReader fileReader = new FileReader("abc.txt");//读这个文件 char[] c = new char[3]; int len; //一次读满数组,如果读到了,返回读了几个,如果没读到返回-1 while((len = fileReader.read(c)) != -1) {//输出每次读到的数组转换成字符串 System.out.print(new String(c,0,len));//new String(char[] c,start,length)重新构造一个字符串,start作为开始索引,length是要获取几个 }
看一下过程,首先我们声明了一个数组c,利用fileReader.read(c)读取。
第一次就把数组读满了,结果为123,返回的是读到的个数,是3
第二次在读的时候,读到了456,也是读满了数组
第三次读的时候,读到了换行符,可以看到在windows下,换行符是\r\n(这不是重点。。)
以此类推还是依此类推?不管了,反正再往下读,就是89J,最后一次读到QK的时候,发现读不满数组了,读到的长度为2,数组的前两个位置被替换变成了QK,最后一个元素由于没有读到被替换,所以还是上回读到的值
最后一次读不到了,返回读到的长度为-1,不进循环,程序结束!
读写都会了后,来个小practice试一试。拷贝D盘的abc.txt到E盘
public class CopyFileDemo {public static void main(String[] args) throws IOException {//拷贝文件的原理就是先读在写 FileReader fileReader = new FileReader("D:/abc.txt"); FileWriter fileWriter = new FileWriter("E:/abc.txt"); char[] c = new char[3]; int len; while((len = fileReader.read(c)) != -1){fileWriter.write(c,0,len);//每次读几个就写几个 }fileWriter.flush(); fileWriter.close(); fileReader.close(); } }
--------------------------------------------------------------------------
缓冲区
缓冲区怎么理解呢?就比如你吃瓜子,毛嗑,向日葵,其实是一个东西。你拨一个吃一个肯定不爽,你有空就拨出来,然后放在一个盒子里面,想吃的时候直接拿,就非常海皮。在比如说,你去超市买东西,你推了一个购物车,买一个扔进去一个,到结账的时候,你还得一个一个拿出来,不如在购物车里面加个框,最后把筐给它就完事了(学到没有?)。计算机里面也是,读一次写一次效率肯定不高,可以先读到一个缓冲区里面,然后最后缓冲区装满了,一次性把缓冲区的内容写完,这样效率就得到了提高。缓冲区的出现用于提高流的效率。
BufferedWriter
public static void main(String[] args) throws IOException {FileWriter fileWriter = new FileWriter("abc.txt"); BufferedWriter bw = new BufferedWriter(fileWriter);//缓冲区只是作为缓冲对象,真正的写操作还是FileWriter来操作的 bw.write("123");//写入数据到缓冲区 bw.flush();//刷到硬盘 bw.close();//bw关闭,底层关闭的是fileWriter }
BufferedReader
这个方法有个readLine()方法,可以一次读一行,如果读不到就返回null,你也可以选择一个一个读,也是用read方法,只不过重写了父类的read方法。为什么要重写呢?这就需要分析一下原理了。
public static void main(String[] args) throws IOException {FileReader reader = new FileReader("abc.txt"); BufferedReader br = new BufferedReader(reader); String str = null; while((str = br.readLine()) != null){System.out.print(str); } }
BufferedReader中read()方法实现原理
public class MyBufferedReader {FileReader fileReader; public MyBufferedReader(FileReader fileReader)构造函数传递需要被缓冲的对象 {this.fileReader = fileReader; }char[] cArr = new char[1024];//缓冲区 int count;//缓冲区里面元素的数量 int pos;//用于获取缓冲区的角标 //自定义read方法 public int read() throws IOException {//筐里面没有馒头,去厨房取 if(count == 0) {count = fileReader.read(cArr);//如果缓冲区没有了,就去拿 pos = 0;//重新获取之后,要把角标重新设置为0 }//厨房也没有馒头了 //如果没有数据,拿不到了,返回-1 if(count < 0){return -1; }//在筐里拿馒头吃 char c = cArr[pos++];//每次自增变量获取 count--;//缓冲区数量减少 return c; }//自定义readLine方法 public String readLine() throws IOException {StringBuffer sb = new StringBuffer(); //判断/r/n int c; while((c = this.read()) != -1)//循环读 {if(c == '\r')//如果是/r就跳过去,不追加到字符串中 {continue; }if(c == '\n')//如果是/n,就代表读到了换行符,返回一行的字符串 {return sb.toString(); }sb.append(c);//日常追加字符串 }return sb.toString(); } }
字符流说完了,总结一下把,首先要了解字符流的两个抽象父类,Writer和Reader,下面有一些子类,其中FileReader是读文件用的(输入),常用的方法有int read(),int read(char)。FileWriter是写文件用的(输出),常用的方法有writer(); flush(); close(); 还有给这两位缓冲用的对象,BufferedWriter和BufferedReader,BufferWriter不用多说了,BufferWriter常用的方法有int read();和 String readLine();这两个方法都是重写过的。还有一个LineNumberReader对象没有说,就是读到后加行号,一般用不上,非常简单,自己看下就行了。
-----------------------------------------------------------------------------------------------------
字节流
接下来看字节流,字节流相比字符流就比较万能了,但是对于处理文本来说还是要优先考虑字符流的。可以说字节流能处理任何类型的文件,比如.txt的,jgp的,mp3,mp4,mp5的,mp6有嘛?avi视频文件等等。
InputStream -> FileInputStream,用字节流玩一玩文件,见名知意,写文件用的。
public class FileInputStreamDemo {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("abc.txt"); //一个一个读 int i; while((i = fis.read()) != -1){System.out.print((char)i); }//一堆一堆读 byte[] c = new byte[1024]; int len; while((len = fis.read(c)) != -1){System.out.print(new String(c,0,len)); }//读小文件用,慎用 byte[] c2 = new byte[fis.available()];//fis.available文件字节数 int len2 = fis.read(c2); System.out.print(new String(c2,0,len2)); } }
和字符流都差不多,只不过接受用的是byte字节,还多了一个fis.available()方法,大批量读不建议使用。
读完事了,来一个写。用到了FileOutputStream
public class FileOutputStreamDemo {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("abc.txt"); fos.write("123456".getBytes()); fos.flush();//字节流不需要调用flush方法,不需要先写到缓冲区,直接和文件打交道。可以看到继承了父类的flush,并没有重写, fos.close();//关闭还是要调用的,子类也进行了重写 } }
都是和字符流用法差不多,非常简单。
来一个拷贝mp3的练习,顺便用一下缓冲区,和字符流也差不多,不过多解释。
public class CopyMP3Demo {public static void main(String[] args) throws IOException {FileInputStream is = new FileInputStream("River flows in you.mp3"); BufferedInputStream bis = new BufferedInputStream(is); FileOutputStream os = new FileOutputStream("abc.mp3"); BufferedOutputStream bos = new BufferedOutputStream(os); byte[] c = new byte[1024]; int len; while((len = bis.read(c)) != -1){bos.write(c,0,len); bos.flush(); }bos.close(); bis.close(); } }
----------------------------------------------------------------------------------------------------------------------------
转换流
需求:让用户输入一段话,按回车结束。如果不是over就输出,是over结束程序。
如果不用转换流,InputStream不存在字符流中的readLine()方法,所以自己写要判断换行符,非常麻烦。这时候就需要将字节流转换成字符流解码
InputStreamReader
InputStream is = System.in; InputStreamReader isr = new InputStreamReader(is);//将字节流转换成字符流,放入一个字节流 BufferedReader br = new BufferedReader(isr);//缓冲区高效读取 String line; while((line = br.readLine()) != null) {if(line.equals("over"))break; System.out.print(line.toString()); }
OutputStreamWriter编码
----------------------------------------------------------------------
学了这么多流对象?到底怎么实战?
1.首先明确源和目的地
源:InputStream Reader
目的地:OutputStream Writer
2.明确数据是否是纯文本
源
|--是,Reader
|--否,InputStream
目的地:
|--是,Writer
|--否,OutputStream
3.明确具体的设备
源设备:硬盘File,键盘System.in,内存Array,网络Socket
目的地设备:硬盘File,控制台System.out,内存Array,网络Socket
4.是否需要额外功能
高效缓冲区,转换流
-----------------------------------------------------------------------------------------------------------------
明确了这四点之后,来看几个需求
1.复制一个文本文件
首先是纯文本,选择Reader和Writer,具体设备是硬盘,选择FileReader和FileWriter,再看是否需要额外功能,需要缓冲区高效读写,那么选择BufferedReader和BufferedWriter
2.读取键盘录入的数据写到硬盘中
首先也是纯文本,选择Reader和Writer,具体设备是控制台System.in和硬盘File,选择InputStream is = System.in;
和FileWriter,需要额外功能吗?考虑读取到的数据需要转换成字符会更好操作,所以选择转换流,字节转换成字符选用
InputStreamReader,需要高效吗?需要!
那就BufferedReader br = new BufferedReader(new InputStreamReader(System));
BufferedWriter bw = new BufferedWriter(new FileWriter("abc.txt"));
3.将一个文本上的数据显示在控制台上
首先是纯文本,选择Reader和Writer,具体设备是硬盘和控制台,选择FileReader和OutputStream os = System.out;
需要额外功能嘛?需要转换流,OutputStreamWriter(System.out),需要高效嘛?需要!
BufferedReader br = new BufferedReader(new FileReader("abc.txt"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
4.将控制台输入的文本,输出在控制台上
纯文本,Reader和Writer,具体设备控制台,选择InputStream is = System.in;和OutputStream os = System.out;
需要额外功能?转换和高效
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
ok,只要明确了对象,使用的话就比较简单了。
---------------------------------------------------------------------------------------------------
到这里,IO的基本对象就学的差不多了
字节流FileInputStream,FileOutputStream,BufferedInputStream,BufferedOutputStream
字符流FileReader,FileWriter,InputStreamReader,OutputStreamWriter,BufferedReader,BufferedWriter
但是这些对象都是操作的数据,操作不了属性。比如获取文件名称,文件大小,操作文件夹等等。
这时候就出现了File类
File类将文件和文件夹封装成了对象,更方便的操作文件和文件夹。没有什么技术含量,就写API的Demo了
//-----------------File构造的几种方式--------------- File f1 = new File("abc.mp3"); File f2 = new File("c:\\","abc.txt"); File f = new File("c:\\"); File f3 = new File(f,"abc.txt"); File f4 = new File("c:" + File.separator + "abc.txt"); //----------------File常用获取------------------ String name = f1.getName();//获取文件名称 String path = f1.getPath();//获取相对路径 String absPath = f1.getAbsolutePath();//获取绝对路径 long len = f1.length();//获取长度 long time = f1.lastModified();//获取最后修改时间 //看上去爽一点的 最后修改时间 Date date = new Date(time); DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); String timeStr = df.format(date); System.out.println(name); System.out.println(path); System.out.println(absPath); System.out.println(len); System.out.println(time); System.out.println(timeStr); //-----------------------创建与删除-------------------------- //和输出流不同的是,如果没有就创建,有就不做操作 File f5 = new File("abc.txt"); boolean b = f5.createNewFile();//创建一个新的文件 File f6 = new File("abc"); boolean b2 = f6.mkdir();//创建文件夹 File f7 = new File("abc\\def"); boolean b3 = f7.mkdirs();//创建多个文件夹 File f8 = new File("abc\\def"); boolean b4 = f8.delete();//删除,如果文件夹里面有内容,是不可以删除的 f8.deleteOnExit();//在程序退出后删除,比如IO流读取完文件,把文件删除 //----------------------------判断-------------------------------- File f9 = new File("abc.txt"); boolean bb = f9.exists();//判断文件或文件夹之前一定要判断文件是否存在 boolean b5 = f9.isDirectory(); boolean b6 = f9.isFile(); //----------------------------替换--------------------------------- File f10 = new File("123.txt"); f10.renameTo(new File("456.txt")); //---------------------系统根目录获取容量---------------------------- File[] files = File.listRoots();//获取所有盘符 for(File fx : files) {System.out.print(fx); }File fJ = new File("c:\\"); System.out.println(fJ.getFreeSpace());//可用 System.out.println(fJ.getTotalSpace());//总共 System.out.println(fJ.getUsableSpace());//已用 //--------------------------获取目录内容------------------------------------ File fQ = new File("c:\\"); String[] list = fQ.list(); for(String s : list) {System.out.println(s); }//--------------------------------过滤目录内容----------------------------------- //找到所有.java的文件 File fK = new File("c;\\"); fK.list(new FilenameFilter() {@Override public boolean accept(File dir, String name) {return name.endsWith(".java"); } });
深度遍历文件夹 -- 递归思想
使用递归时,要注意两点
1.结束条件
2.递归次数,小心内存溢出(光压栈不弹栈)
public static void main(String[] args) {depthDir(new File("d:\\123"),0); }public static void depthDir(File f,int level) {System.out.println(printSpace(level) + f.getName()); level++; File[] files = f.listFiles(); for(int x = 0; x < files.length; x++){//如果当前是文件夹,就在进去遍历 if(files[x].isDirectory()){depthDir(files[x],level); }else {System.out.println(printSpace(level)+ files[x].getName()); }} }private static String printSpace(int level) {StringBuffer sb = new StringBuffer(); for(int x = 0; x < level; x++){sb.append(" "); }return sb.toString(); }
遍历删除文件夹,Windows下删除文件只能从里往外删
public static void main(String[] args) {File f = new File("d:\\123"); deleteDir(f); }private static void deleteDir(File f) {//遍历,如果不是文件夹就删除,是就继续进去,等到进到最后一个了开始删除 File[] files = f.listFiles(); for(int x = 0; x < files.length; x++){if(files[x].isDirectory()){deleteDir(files[x]); }else {files[x].delete(); }}f.delete(); }
Java基础之IO流(持续更新中)相关推荐
- 【Java基础】· IO流习题详解
写在前面 Hello大家好, 我是[麟-小白],一位软件工程专业的学生,喜好计算机知识.希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正!谢谢大家!!! ...
- 阿里最新面试必备项之Java的String类,持续更新中!
最新腾讯面试必备项之Java的String类,持续更新中! 1.1 String的特性 String类:代表字符串.Java程序中的所有字符串字面值(如"abc")都作为此类的实例 ...
- Java基础学习—— IO流
Java基础学习-- IO流 1 文件 1.1 文件的创建 1.2 文件常用的方法 2 IO流 2.1 FileInputStream 2.2 FileOutputStream 2.3 文件的拷贝 2 ...
- Java基础:IO 流中的 flush
无意中发现了一个巨牛的人工智能教程,忍不住分享一下给大家.教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家.点 这里 可以跳转到教程. 内容概要 Java IO ...
- java面试知识迷你版--持续更新中
**部分知识来源JavaGuide等网络学习资源. java基础 内部类:静态内部类.成员内部类.局部内部类.匿名内部类. 重写(override)要求子类的返回值小于父类(类型相同),修饰符使用范围 ...
- Java基础之IO流
IO流用来处理设备间数据传输,java对数据的操作是通过流的方式,而这些操作流的对象被封装在IO包中.流可以分为字符流和字节流.字符流可以设置编码方式,这就使得处理文本更加方便. IO常用基类 字节流 ...
- Java基础知识——IO流
简介 IO是指Input/Output,即输入和输出.以内存为中心: Input指从外部读入数据到内存,例如,把文件从磁盘读取到内存,从网络读取数据到内存等等 Output指把数据从内存输出到外部,例 ...
- 【java基础】IO流是啥?有啥用?(上)
今天我们说说java代码中对文件的操作,比如新建删除文件,读取文件内容等. File类 File类用于操作文件和目录,可对文件或目录进行新建,删除和重命名等操作.但是如果要访问文件内容本身,就需要用到 ...
- Java基础之IO流(一)
IO流(一) IO流:输入输出的流动 IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的对象都在IO包中 流按操作数据分为两种:字节流与字符流 . 流按流向分为 ...
最新文章
- php9宫格抽奖程序_php抽奖算法(适用于九宫格、大转盘)
- 学习视觉和语言的多粒度对齐?字节提出新多模态预训练方法 X-VLM:代码已开源!...
- scheduledthreadpoolexecutor使用_ScheduledThreadPoolExecutor详解
- js 逆向分析的神器 --- v_jstools
- 做一个项目,平时都用到哪些工具提高效率(上)[转]
- inventor弧度怎么标注_家里房间太大,WiFi信号覆盖不了怎么办?网件新作:分身术...
- 区块链:关键阻力的突破会带来持续的积极情绪
- 如何进行 JVM 调优
- html——页面内跳转
- 中文维基百科数据处理
- ICE for Linux
- excel countifs 计算包含了空白单元格,结果错误,不对,特别大。
- android如何实现环形缓冲区
- 团队管理之领导力阅读感悟
- 清理计算机磁盘碎片,如何清理磁盘碎片
- android 微信评论功能,Android仿微信朋友圈点击评论自动定位到相关行功能
- 教你在线翻译PDF文档的方法
- javax.servlet.ServletException: Could not resolve view with name 'destination/isOtherExist' in servl
- 金蝶BOS是什么,能给您带来什么价值?
- python量化实战 顾比倒数线_顾比倒数线 主图源码
热门文章
- 基于Python/Capl脚本 对通信矩阵报文(Flexray/Can)的周期检测(二)
- 编程之美之一摞烙饼的排序1
- 老罗的《Android系统源代码情景分析》翻了10遍还看不懂?因为你用错了
- CCD CMOS传感器基本工作原理
- 远程linux还原本地bak文件,Linux -- 服务器数据备份恢复策略
- 解密阿里巴巴加密技术: 爬虫JS逆向实践-1688 【JS混淆加密解析】
- 阿里云centos6静默安装oracle11G
- 第二证券|钠离子电池将迎来量产 22股净利有望高增长
- 新飞飞不显示服务器,《新飞飞》官方网站-新资料片《异域远征军》-网易Q萌战斗网游...
- BI Publisher(rtf)模板开发语法大全(转)