黑马程序员—Java中的IO流
来源:互联网 发布:webshell密码破解 编辑:程序博客网 时间:2024/05/01 10:35
11. IO流
11.1IO流概述
IO流用来处理设备之间的数据传输。流按操作数据分为两种:字节流与字符流。
流按流向分为:输入流,输出流。
字节流的抽象基类:InputStream OutputSream
字符流的抽象基类:Reader Writer
11.2字符流
1)FileWriter
import java.io.*;class FilerWriterDemo {public static void main(String[] args) throws IOException{/*创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件 而且该文件会被创建到指定目录下,如果该目录下已有同名文件,将被覆盖。 其实该步就是在明确数据要存放的目的地*/FileWriter fw = new FileWriter("demo.txt");//调用write方法,将字符串写入到流中fw.write("abcde");//刷新流对象中的缓冲中的数据,将数据刷到目的地中fw.flush();/*关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据,将数据刷到目的地 和flush区别:flush刷新后,流可以继续使用。close刷新后,会将流关闭。*/fw.close();}}
IO异常处理方式:
import java.io.*;class FilerWriterDemo2 {public static void main(String[] args) {FileWriter fw = null;try{//在此处进行fw初始化,以免出现异常时,finally语句无法读取到fw对象fw = new FileWriter("demo.txt");fw.write("abcdefg");}catch (IOException e){System.out.println(e.toString());}finally{try{/*当上述语句出现异常时,fw不会创建,fw.close()语句将会出现fw类 文件不存在的异常,因此进行一次判定来解决*/if(fw!=null)fw.close();}catch (IOException e){System.out.println(e.toString());}}}}
对已有文件的数据续写:
import java.io.*;class FilerWriterDemo3 {public static void main(String[] args) {FileWriter fw = null;try{/*传递一个true参数,代表不覆盖已有的文件, 并在已有文件的末尾处进行数据的续写*/fw = new FileWriter("demo.txt",true);fw.write("\r\nhaha");}catch (IOException e){System.out.println(e.toString());}finally{try{if(fw!=null)fw.close();}catch (IOException e){System.out.println(e.toString());}}}}
2)FileReader
import java.io.*;class FileReaderDemo {public static void main(String[] args) {/*创建一个文件读取流对象,和指定名称的文件相关联要保证该文件 是已经存在的,如果不存在会发生异常FileNotFoundException*/FileReader fr = null;try{fr = new FileReader("demo.txt");/*读取方法一:调用读取流对象的read方法 read()方法一次读一个字符,而且会自动往下读,已到末尾返回-1*/int ch = 0;while ((ch=fr.read())!=-1)System.out.println((char)ch);/*读取方法二:定义一个字符串数组,用于存储读到字符。该read(char[]) 返回的是读到字符个数*/char[] buf = new char[1024];int num = 0; while ((num=fr.read(buf))!=-1){System.out.println("num="+num+"..."+new String(buf,0,num));}}catch (IOException e){System.out.println(e.toString());}finally{try{if(fr!=null)fr.close();}catch (IOException e){System.out.println(e.toString());}}}}
3)拷贝文本文件
import java.io.*;class CopyText {public static void main(String[] args) {copy_2();}//复制方式一:从C盘读一个字符,就往D盘写一个字符public static void copy_1(){//创建目的地FileWriter fw = null;//与已有文件关联FileReader fr = null;try{fw = new FileWriter("RuntimeDemo_copy.txt");fr = new FileReader("RuntimeDemo.java");int ch = 0;while ((ch = fr.read())!=-1){fw.write(ch);}}catch (IOException e){throw new RuntimeException("读写失败");}finally{try{if(fr!=null)fr.close();}catch (IOException e){throw new RuntimeException("读取关闭失败");}finally{try{if(fw!=null)fw.close();}catch (IOException e){throw new RuntimeException("写入关闭失败");}}}}//复制方式二:从C盘读取一段,再存到D盘中public static void copy_2(){//创建目的地FileWriter fw = null;//与已有文件关联FileReader fr = null;try{fw = new FileWriter("SystemDemo_copy.txt");fr = new FileReader("SystemDemo.java");char[] buf = new char[1024];int len = 0;while ((len = fr.read(buf))!=-1){fw.write(buf,0,len);}}catch (IOException e){throw new RuntimeException("读写失败");}finally{try{if(fr!=null)fr.close();}catch (IOException e){throw new RuntimeException("读取关闭失败");}finally{try{if(fw!=null)fw.close();}catch (IOException e){throw new RuntimeException("写入关闭失败");}}}}}
11.3字符流的缓冲区
缓冲区的出现提高了对数据的读写效率,缓冲区要结合流才可以使用,在创建缓冲区之前,必须要先有流对象
1) BufferedWriter
该缓冲区中提供了一个跨平台的换行符:newLine();
import java.io.*;class BufferedWriterDemo {public static void main(String[] args) throws IOException{//创建一个字符写入流对象FileWriter fw = new FileWriter("buf.txt");/*为了提高字符写入流效率,加入缓冲技术,只要将需要被提高效率的流对象 作为参数传递给缓冲区的构造函数即可*/BufferedWriter bufw = new BufferedWriter(fw);for (int x = 1;x<5 ;x++ ){bufw.write("abcd"+x);bufw.newLine();bufw.flush();}//只要用到缓冲区,就要记得刷新bufw.flush();//关闭缓冲区就是在关闭缓冲区中的流对象bufw.close();}}
2) BufferedReader
该缓冲区提供了一个一次读一行的方法,方便于对文本数据的获取:readLine()。当返回null时表示读到文件末尾,返回的时候只返回回车符之前的数据内容。
import java.io.*;class BufferedReaderDemo {public static void main(String[] args) throws IOException{//创建一个读取流对象和文件相关联FileReader fr = new FileReader("buf.txt");/*为了提高效率,加入缓冲技术,将字符读取流对象 作为参数传递给缓冲对象的构造函数*/BufferedReader bufr = new BufferedReader(fr);String line = null;while ((line = bufr.readLine())!=null){System.out.println(line);}bufr.close();}}
LineNumberReader类:是BufferedReader类的子类,有两个新方法
getLineNumber():获得当前行号
setLineNumber():设置当前行号
11.4装饰设计模式
当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能,那么自定义的该类称为装饰类
装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
装饰模式比继承更灵活,避免了继承体系的臃肿,而且降低了类与类之间的关系。装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常都属于一个体系中。
装饰类和被装饰类都是,被装饰类父类的一个子类。创建自定义装饰类时,要继承父类,那么需要复写父类中的抽象方法
11.5字节流
1) FileInputSream (读)
public static void readFile_3() throws IOException{FileInputStream fis = new FileInputStream("fos.txt");//定义一个刚刚好的缓冲区,不用再循环了,数据不大时使用。byte[] buf = new byte[fis.available()]; //该文件可使用的容量fis.read(buf);System.out.println(new String(buf));fis.close();}public static void readFile_2() throws IOException{FileInputStream fis = new FileInputStream("fos.txt");byte[] buf = new byte[1024];int len = 0;while((len=fis.read(buf))!=-1){System.out.println(new String(buf,0,len));}fis.close();}
2) FileOutputSream (写)
public static void writeFile() throws IOException{FileOutputStream fos = new FileOutputStream("fos.txt");//字节流不能写入字符串,通过String.getBytes()方法将字符串转成byte数组写入fos.write("abcde".getBytes());/*不需要flush()。因为字符流也是写入字节,但是需要将写入的字节先临时缓存。 查完表后通过flush()再写入字符。而字节流不需要缓存,直接就将字节写入*/fos.close();}
11.6字节流的缓冲区
BufferedOutputStream
BufferedInputStream
//通过缓冲区拷贝mp3文件:import java.io.*;class CopyMp3 {public static void main(String[] args) throws IOException{long start = System.currentTimeMillis();copy_1();long end = System.currentTimeMillis();System.out.println((end-start)+"毫秒");}//通过字节流缓冲区完成复制public static void copy_1() throws IOException{BufferedInputStream bufis = <span style="white-space:pre"></span>new BufferedInputStream(new FileInputStream("mp3.mp3"));BufferedOutputStream bufos = <span style="white-space:pre"></span>new BufferedOutputStream(new FileOutputStream("mp3_copy.mp3"));int by = 0; while ((by=bufis.read())!=-1){bufos.write(by);}bufos.close();bufis.close();}}
11.7读取键盘录入
System.in:对应的标准输入设备:键盘
1) InputStreamReader
是字节流通向字符流的桥梁,将字节流对象转成字符流对象。
2) OutputStreamWriter
字符流通向字节流的桥梁。
/*通过键盘录入数据,当录入一行数据后,就将该行数据进行打印 如果录入的数据是over,那么停止录入*/import java.io.*;class ReadIn {public static void main(String[] args) throws IOException{//获取键盘录入对象InputStream in =System.in;//将字节流对象转成字符流对象,使用转换流InputStreamReaderInputStreamReader isr = new InputStreamReader(in);//为了提高效率,将字符流进行缓存区技术高效操作,使用BufferedReaderBufferedReader bufr = new BufferedReader(isr);//获取输出对象OutputStream out = System.out;//将字节流对象转成字符流对象,使用转换流OutputStreamWriterOutputStreamWriter osw = new OutputStreamWriter(out);BufferedWriter bufw = new BufferedWriter(osw);String line = null;while ((line=bufr.readLine())!=null){if("over".equals(line))break;bufw.write(line.toUpperCase());bufw.newLine();bufw.flush();}bufr.close();bufw.close();}}
11.8流操作规律
1) 明确源和目的
源:输入流。InputStream Readerr
目的:输出流 OutputStream Writer
2) 操作的数据是否是纯文本
是:字符流
不是:字节流
3) 当体系明确后,再明确要使用哪个具体的对象
通过设备来进行区分
源设备:内存ArrayStream,硬盘 FileStream,键盘 System.in
目的设备:内存 ArrayStream,硬盘 FileStream,控制台 System.out
改变标准输入输出设备:
//将输入设备由键盘改成PersonDemo.java文件,需要建立一个字节流对象FileInputStream
System.setIn(new FileInputStream(“PersonDemo.java”))
//将输出设备由控制台改成zz.txt文件,需要建立一个字节输出流子类对象PrintStream
System.setOut(new PrintStream(“zz.txt”))
11.9File类
用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作
File类常见方法:
1) 创建
boolean mkdir():创建文件夹,只能创建一级目录
boolean mkdirs():创建多级目录,包括所有必需但不存在的父目录
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样,输出流对象一建立就会创建文件,而
且文件已经存在,会覆盖。File类要调用方法才创建文件。
2) 删除
boolean delete():如果此句前出现异常将不会执行到,文件就无法删除
void deleteOnExit():在程序退出时删除。在程序运行出现异常的时候也能删除文件。
3) 判断
boolean canExecute():判断文件是否可执行
boolean exists():判断文件是否存在
boolean isDirectory(): 判断文件对象是否是文件或者目录时,必须要先判断
boolean isFile(): 该文件对象封装的内容是否存在,通过exists判断
boolean isHidden():判断文件是否隐藏
4) 获取信息
getName()
getPath()
getParent() 该方法返回的是绝对路径中的父目录,如果File对象封装的是相对路径,返回null。如果相对路径中有上一层目录那么该目录就是返回结果
getAbsolutePath() 获取绝对路径
long lastModified() 获取文件最后被修改的时间
long length()
boolean renameTo() f1.renameTo(f2),变更文件名,还会将文件剪切到指定目录下
File[] listRoots() 列出可用的系统盘符
String[] list() 列出目录下的文件和子目录。调用list方法的file对象必须是封装了一个目录,该目录还必须存在
File[] listFiles() 列出目录下的文件,返回的是File对象的数组
列出指定目录下文件或者文件夹,包含子目录中的内容(带层次):import java.io.*;class FileDemo3 {public static void main(String[] args) {File file = new File("c:\\java001");showDir(file,0);}public static void showDir(File dir,int level ){System.out.println(getLevel(level)+dir.getName());//level只对应于调用的函数中,递归调用时对应的是函数中相应的值level++;File[] files = dir.listFiles();for (int x = 0; x<files.length;x++ ){//如果是文件夹,可以调用方法本身继续遍历文件夹if(files[x].isDirectory())showDir(files[x],level);elseSystem.out.println(getLevel(level)+files[x].getName());}}public static String getLevel(int level){StringBuilder sb = new StringBuilder();//文件夹及文件名前带|--sb.append("|--");for (int x=0;x<level ;x++ ){//子级目录缩进sb.insert(0," ");}return sb.toString();}}
函数自身调用自身,这种表现形式称为递归。使用时需要注意:
1)限定条件
2)要注意递归的次数,尽量避免内存溢出
11.10Properties类
Properties是hashtable的子类,具备map集合的特点,它里面存储的键值对都是字符串。是集合中和IO技术相结合的集合容器。该对象的特点:可以用于键值对形式的配置文件。
Properties中的方法:
setProperty(String key, String value) 向集合中存入键值对
String getProperty(String key) 获取对应键的值
Set<String> stringPropertyNames() 获取Properties对象中键的集合
list(PrintStream out)
list(PrintWriter out)
load(InputStream inStream)
load(Reader reader)
store(OutputStream out, String comments) 将Properties中的键值对存储到配置文件中
store(Writer writer, String comments) 并且加入注释信息comments。
import java.io.*;import java.util.*;class PropertiesDemo{public static void main(String[] args) throws IOException{//method_1();PropertiesMethod();}//load,list,store方法应用public static void PropertiesMethod() throws IOException{FileInputStream fis = new FileInputStream("Info.txt");Properties prop = new Properties();//将流中的数据加载进集合prop.load(fis);//设置配置文件中的信息prop.setProperty("wangwu","39");FileOutputStream fos = new FileOutputStream("Info.txt");prop.store(fos,"haha");//将集合中的数据输出到流中prop.list(System.out);fos.close();fis.close();}//load方法原理:将info.txt中键值数据存到集合中进行操作。public static void method_1() throws IOException{BufferedReader bufr = new BufferedReader(new FileReader("Info.txt"));String line = null;Properties prop = new Properties();while ((line=bufr.readLine())!=null){//利用=将键与值分割String[] arr = line.split("=");//调用方法将键和值存入到集合中prop.setProperty(arr[0],arr[1]);}bufr.close();}//设置和获取元素public static void setAndGet(){Properties prop = new Properties();prop.setProperty("zhangsan","30");prop.setProperty("lisi","39");String value = prop.getProperty("lisi");System.out.println(value);Set<String> names = prop.stringPropertyNames();for(String s : names){System.out.println(s);}}}
11.11打印流
为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。该流提供了打印方法,可以将各种数据类型的数据都原样打印
字节打印流:
PrintStream
构造函数可以接收的参数类型:
1. file对象 File
2. 字符串路径 String
3. 字节输出流 OutputStream
字符打印流:
PrintWriter
构造函数可以接收的参数类型:
1. file对象 File
2. 字符串路径 String
3. 字节输出流 OutputStream
4. 字符输出流 Writer
PrintWriter(OutputStream out, booleanautoFlush) autoFlush为true时,println方法会
PrintWriter(Writer out, boolean autoFlush) 自动刷新缓存
11.12 序列流SequenceInputStream
SequenceInputStream
表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
import java.io.*;import java.util.*;class SequenceDemo{public static void main(String[] args) throws IOException{Vector<FileInputStream> v = new Vector<FileInputStream>();v.add(new FileInputStream("1.txt"));v.add(new FileInputStream("2.txt"));v.add(new FileInputStream("3.txt"));Enumeration<FileInputStream> en = v.elements();SequenceInputStream sis = new SequenceInputStream(en);FileOutputStream fos = new FileOutputStream("4.txt");byte[] buf = new byte[1024];int len = 0;while ((len=sis.read(buf))!=-1){fos.write(buf,0,len);}fos.close();sis.close();}}
11.13对象的序列化
ObjectInputStream ObjectOutputStream
将堆内存中的对象存入的文件当中,对象内的变量数据也被保存;读取文件的可以读取到所存储的对象,直接调用之前的数据。实现了Serializable接口的对象才能被序列化。
在需要序列化的对象中添加static final long serialVersionUID = 42L语句,即使本地的该对象有所修改,也可以读取被序列化的对象,否则会报出InvalidClassException异常。
static 修饰的变量不能被序列化,因为static修饰的内容存在于方法区;transient修饰的变量也不能被序列化,即使变量存在于堆内存中。
11.14管道流
PipedInputStream PipedOutputStream
管道输入流和管道输出流通过不同线程运行。管道流是多线程和IO流的结合应用
import java.io.*;class Read implements Runnable{private PipedInputStream in;Read(PipedInputStream in){this.in = in;}public void run(){try{byte[] buf = new byte[1024];//当没有读取到数据时read方法会阻塞,即线程等待。int len = in.read(buf);String s = new String(buf,0,len);System.out.println(s);in.close();}catch (IOException e){throw new RuntimeException("管道读取流失败");}}}class Write implements Runnable{private PipedOutputStream out;Write(PipedOutputStream out){this.out = out;}public void run(){try{out.write("piped lai le".getBytes());out.close();}catch (IOException e){throw new RuntimeException("管道输出流失败");}}}class PipedStreamDemo{public static void main(String[] args) throws IOException{PipedInputStream in = new PipedInputStream();PipedOutputStream out = new PipedOutputStream();in.connect(out);Read r = new Read(in);Write w = new Write(out);new Thread(r).start();new Thread(w).start();}}
11.15RandomAccessFile
该类不是IO体系中的子类,而是直接继承自Object。但是它是IO包中的成员,因为它具备读和写功能,内部封装了一个数组,而且通过指针对数组中的元素进行操作。可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。
能够完成读写的原理就是内部封装了字节输入流和输出流。该类只能操作文件,操作模式通常有只读r和读写rw。
如果模式为只读r,不会创建文件,会去读取一个已存在的文件,如果该文件不存在,则会出现异常。
如果模式为rw,操作的文件不存在,会自动创建;如果存在,则不会覆盖。
该类可以通过多个线程同时对一个文件进行读写操作,下载就是利用此原理
import java.io.*;class RandomAccessFileDemo {public static void main(String[] args) throws IOException{//writeFile2();//writeFile();//readFile();}public static void readFile() throws IOException{RandomAccessFile raf = new RandomAccessFile("ran.txt","r");//调整对象中的指针,来读取想要读取的内容,往前往后都能调整//raf.seek(8);//跳过指定的字节数,来读取想要读取的内容,只能往后跳//raf.skipBytes(8);byte[] buf = new byte[4];raf.read(buf);String name = new String(buf);//从此文件读取一个有符号的 32 位整数int age = raf.readInt();System.out.println("name="+name);System.out.println("age="+age);raf.close();}//向指定位置写入数据public static void writeFile2() throws IOException{//创建对象时与输出流不同,不会覆盖已有文件RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");raf.seek(8*3);raf.write("周期".getBytes());raf.writeInt(103);raf.close();}public static void writeFile() throws IOException{RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");raf.write("李四".getBytes());//按4个字节写入int数字raf.writeInt(97);raf.write("王五".getBytes());raf.writeInt(99);raf.close();}}
11.16DataStream
可以用于操作基本数据类型的数据的流对象
11.17ByteArrayStream
ByteArrayInputStream : 在构造的时候,需要接收数据源,而且数据源是一个字节数组
ByteArrayOutputStream : 在构造的时候,不用定义数据目的,因为该对象中已经内部封
装了可变长度的字节数组,这就是数据目的地
因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭
ByteArrayStream是用流的思想来操作数组
import java.io.*;class ByteArrayStream{public static void main(String[] args) {//数据源ByteArrayInputStream bis = new ByteArrayInputStream("ABCDE".getBytes());//数据目的ByteArrayOutputStream bos = new ByteArrayOutputStream();int by = 0;while ((by=bis.read())!=-1){bos.write(by);}System.out.println(bos.toString());//将字节数组输出流中的数据写入到一个文件当中bos.writeTo(new FileOutputStream("a.txt"));}}
- 黑马程序员—Java中的IO流
- 黑马程序员--java中的io流
- 黑马程序员--java中的IO流
- 黑马程序员----java中的IO流基础
- 黑马程序员----Java中的其他IO流
- 黑马程序员——Java中的IO流
- 【黑马程序员】java中的IO
- 黑马程序员——Java基础---io流(io中的其他对象)
- 黑马程序员--Java基础五(Java中的IO流)
- 黑马程序员——java IO流
- 黑马程序员—java—IO流
- 黑马程序员——Java IO流
- 黑马程序员——Java IO流
- 黑马程序员——java-IO流
- 黑马程序员java学习—IO流
- 黑马程序员java 基础之io流中的字符流
- 黑马程序员java基础之IO流中的字节流
- 黑马程序员java基础之io流中的其他流
- httpclient总结
- 解决 PHPEXCEL 纯数字 科学计数的问题
- 黑马-C语言-枚举
- Java 多线程面试问题汇总
- 欢迎使用CSDN-markdown编辑器
- 黑马程序员—Java中的IO流
- Windows 集群
- Xcode键盘快捷键
- 济南装修
- 初识teamtoy的lazyPHP3
- Wolf and Rabbit(欧几里得)
- python中的列表(list),字典(dict),字符串(str)的基本操作
- java 构造函数的解析
- SQL Server T-SQL高级查询