Java:IO流与文件基础

说明:

  本章内容将会持续更新,大家可以关注一下并给我提供建议,谢谢啦。

走进流

什么是流

  流:指的是从源到目的地的字节的有序序列。

  

  在Java中,可以从其中读取一个字节序列的对象称作 输入流,可以向其中写入一个字节序列的对象称作 输出流
    ☑ 这些字节序列的来源可以是:文件、网络连接、内存块等。
    ☑ 抽象类InputStream和OutputStream是构成输入/输出(I/O)的基础。
    ☑ 因为面向字节的流不便于处理以Unicode形式存储的信息(字符),所以从抽象类Reader 和 Writer中继承出来一个专门处理字符流的类层次结构。
    ☑ 适配器类InputStreamReader将InputStream转换为Reader,OutputStreamWriter将OutputStream转换为Writer

IO流家族体系

对流的分类

☑ 依据流相对于程序的另一个端点的不同:
  
☐ 节点流(全黄):以特定源(如磁盘文件、内存某区域或线程之间的管道)为端点构造的输入/输出流
  ☐ 过滤流(半黄):以其他已存在的流为端点构造的输入/输出流。
☑ 依据流中的数据单位不同:
  
☐ 字节流:流中的数据以8位字节为单位进行读写,以InputStream和OutputStream为共同父类
  ☐ 字符流:流中的数据以16位字符为单位进行读写,以Reader和Writer为共同父类

家族体系图(原创)

  

家族体系的顶层方法

  顶层方法不是很多,但是需要我们去记住,下面列出了所有的顶层方法,遇到问题是结合上图和下表可以清理思路。

  A.abstract class OutputStream

返回类型 方法及解释
 void close()            关闭此输出流并释放与此流有关的所有系统资源。
 void flush()            刷新此输出流并强制写出所有缓冲的输出字节。
 void write(byte[] b)            将 b.length 个字节从指定的 byte 数组写入此输出流。
 void write(byte[] b, int off, int len)            将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract  void write(int b)            将指定的字节写入此输出流。

  B.abstract class InputStream

返回类型 方法及解释
 int available()            返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。
 void close()            关闭此输入流并释放与该流关联的所有系统资源。
 void mark(int readlimit)            在此输入流中标记当前的位置。
 boolean markSupported()            测试此输入流是否支持 mark 和 reset 方法。
abstract  int read()            从输入流中读取数据的下一个字节。
 int read(byte[] b)            从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
 int read(byte[] b, int off, int len)            将输入流中最多 len 个数据字节读入 byte 数组。
 void reset()            将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。
 long skip(long n)            跳过和丢弃此输入流中数据的 n 个字节。

  C.abstract class Reader

返回类型 方法及解释
abstract  void close()            关闭该流并释放与之关联的所有资源。
 void mark(int readAheadLimit)            标记流中的当前位置。
 boolean markSupported()            判断此流是否支持 mark() 操作。
 int read()            读取单个字符。
 int read(char[] cbuf)            将字符读入数组。
abstract  int read(char[] cbuf, int off, int len)            将字符读入数组的某一部分。
 int read(CharBuffer target)            试图将字符读入指定的字符缓冲区。
 boolean ready()            判断是否准备读取此流。
 void reset()            重置该流。
 long skip(long n)            跳过字符。

  D.abstract class Writer  

返回类型 方法及注释
 Writer append(char c)            将指定字符添加到此 writer。
 Writer append(CharSequence csq)            将指定字符序列添加到此 writer。
 Writer append(CharSequence csq, int start, int end)            将指定字符序列的子序列添加到此 writer.Appendable。
abstract  void close()            关闭此流,但要先刷新它。
abstract  void flush()            刷新该流的缓冲。
 void write(char[] cbuf)            写入字符数组。
abstract  void write(char[] cbuf, int off, int len)            写入字符数组的某一部分。
 void write(int c)            写入单个字符。
 void write(String str)            写入字符串。
 void write(String str, int off, int len)            写入字符串的某一部分。

输出输入流的嵌套

说明

  单独使用节点流的情况在程序中较少出现。
  一般常通过过滤流将多个流套接在一起,利用各种流的特性共同处理数据,套接的多个流构成了一个流链   

  优点:

    方便数据的处理并提高处理的效率。

  

着重介绍的几个过滤流

  ☑ BufferedInputStream
    ☐ 在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。
    ☐ 在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。
  ☑ BufferedOuputStream
    ☐ 该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
  ☑ BufferedReader和BufferedWriter同样也是提供缓存区。
  ☑ DataInputStream
    ☐ 包含用于读取基本类型数据的全部接口

  说明:所有的这些在下面我们都会重新强调并实现。

常用流

思维导图

  

文件流

文件流包括

    ☐ FileReader/FileWriter类
    ☐ FileInputStream/FileOutputStream类

创建文件流

    ☐FileInputStream(File file) 
            通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
    ☐FileInputStream(String name) 
            通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

实例

public class FileCopy{
public static void main(String[] args) throws IOException{
FileInputStream in=new FileInputStream("FileCopy.java");
FileOutputStream out=new FileOutputStream("FileCopy.txt");
int c;
while( (c=in.read())!=-1)
out.write(c);
in.close();
out.close();
}
}

缓存流

  说明:

    缓存流是过滤流,以InputStream/OutputStream为前端流,并可指定缓冲区大小,如:
      public BufferedInputStream(InputStream in)
      public BufferedInputStream(InputStream in, int size)
    BufferedReader增加readLine()
    BufferedWriter增加newLine():写入一个换行符。  

  演示:

public class BufferedIO{
public static void main(String[] args) throws IOException{
BufferedReader in=new BufferedReader(
new FileReader("BufferedIO.java"));
PrintWriter out=new PrintWriter( new BufferedWriter(
new FileWriter("BufferedIO.txt")));
String s;
int linecnt=1;
StringBuilder sb=new StringBuilder();
while((s=in.readLine())!=null){
sb.append(linecnt+":"+s+"\n");
out.println(linecnt+":"+s);
linecnt++;
}
in.close();
out.close();
System.out.print(sb.toString());
}
}

说明:

  PrintWriter
  向文本输出流打印对象的格式化表示形式,即在写入的同时可以对写入的数据进行格式化。

数据流

数据流包括:

  DataInputStream/DataOutputStream类

读写基本数据类型的接口方法:

  

演示:

public class DataIO{
public static void main(String[] args) throws IOException{
DataOutputStream out=new DataOutputStream(
new BufferedOutputStream(new FileOutputStream("data.txt")));
out.writeBoolean(false); out.writeChar('c');
out.writeByte(1); out.writeShort(2);
out.writeInt(3); out.writeLong(4L);
out.writeFloat(5.0f); out.writeDouble(6.0);
out.writeUTF("hello world!"); out.close(); DataInputStream in=new DataInputStream(
new BufferedInputStream( new FileInputStream("data.txt")));
System.out.println(in.readBoolean()+";"+in.readChar()+";");
System.out.println(in.readByte()+";"+in.readShort()+";");
System.out.println(+in.readInt()+";"+in.readLong());
System.out.println(in.readFloat()+";"+in.readDouble()+";");
System.out.println(in.readUTF()); in.close();
}

  说明:

    ☑readUTF()与writeUTF()
      writeBytes(String)和writeChars(String)方法在DataInputStream中没有对应的方法恢复出String
      用DataOutputStream写字符串并使得DataInputStream能恢复出字符串的方法是使用writeUTF()和readUTF()
    ☑ UTF-8
      ASCII字符→单字节形式;非ASCII字符→多字节形式
      字符串长度→UTF-8字符串的前两字节中
      Java中使用的是UTF-8的变体,UTF-8只是读写过程中的字符串形式,程序中Unicode

标准IO:

标准输入:键盘
标准输出:加载Java程序的命令窗口
  Java在System类中定义了三个标准I/O流,是System类的三个静态变量
    ☐System.in(public static final InputStream in):标准输入流
    ☐System.out(public static final PrintStream out):标准输出流
    ☐System.err(public static final PrintStream err):标准错误输出流
  
程序从键盘读入数据:
  ☐ int ch=System.in.read();
  ☐ System.in.read()从键盘缓冲区读入一个字节的数据,返回的是整型值(低位字节为输入数据,高位字节全为零)
  ☐ System.in.read()的执行使得整个程序被挂起,直到用户从键盘输入数据才继续运行
  ☐ 从键盘逐行读入:嵌套BufferedReader和InputStreamReader

实例:

public class StandardIO {
public static void main(String[] args) {
String s;
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Please input: ");
try {
s = in.readLine();
while (!s.equals("exit")) {
System.out.println(" read: " + s);
s = in.readLine();
}
System.out.println("End of Inputting");
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

java.util.Scanner类:从控制台读取输入

说明

  Scanner sc=new Scanner(System.in);
    Scanner将控制台输入按照分隔符模式进行分割,分隔符模式默认为匹配空格
  扫描结果通过各种next*()方法转化为不同类型的值
    next() 获取一个字符串
    nextByte() 获取一个byte类型的整数
    nextShort() 获取一个short类型的整数
    nextInt() 获取一个int类型的整数
    nextLong() 获取一个long类型的整数
    nextFloat() 获取一个float类型的数
    nextDouble() 获取一个double类型的数
    nextLine() 获取一行文本(即以回车键为结束标志)

输入输出的重定向

  System.setIn(InputStream)
  System.setOut(PrintStream)
  System.setErr(PrintStream)

  

随机存取文件

说明

    到目前为止所学习的Java流式输入/输出都是顺序访问流,即流中的数据必须按顺序进行读写当需要随机读写磁盘文件中的内容时,用RandomAccessFile类(既可对文件读,又可对文件写)

RandomAccessFile与其他顶层类的关系

  

  

构造方法

  

构造方法摘要
RandomAccessFile(File file, String mode)            创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。
RandomAccessFile(String name, String mode)            创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。
mode值 含意
"r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
"rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
"rws" 打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。
"rwd"   打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到底层存储设备。

操作

文件指针操作
    long getFilePointer() //返回当前文件指针
    void seek(long pos) //文件指针定位到指定位置
    long length() //返回文件长度
    int skipBytes(int n) //从当前位置开始跳过n字节
读操作(实现了DataInput接口)
    readBoolean(), readChar(), readInt(), readLong(), readFloat(), readDouble(), readLine(), readUTF()等
写操作(实现了DataOutput接口)
    writeBoolean(), writeChar(), writeUTF(), writeInt(), writeLong(), writeFloat(), writeDouble()等

实例

public class RandomAccessTest {
public static void main(String[] args) throws IOException {
long filePoint = 0;
String s;
RandomAccessFile file = new RandomAccessFile(
"RandomAccessTest.java", "r");
long fileLength = file.length(); // 获取文件长度
while (filePoint < fileLength) {
s = file.readLine(); // 读一行字符,并移动文件指针
System.out.println(s); // 输出显示读入的一行字符
file.skipBytes(5);
filePoint = file.getFilePointer(); // 获取当前文件指针
}
file.close();
}
}

对象的串行化

  将对象保存到外存,称为对象的永久化。对象永久化的关键是将对象的状态以一种串行格式表示出来,以便以后读取能够将该对象重构出来。对Java对象的这一读写过程称为对象的串行化

常在下列情况下使用

  1.Java远程方法调用(Remote Method Invocation)
  2.Java Bean / EJB
  3.对象永久化

实现串行化

  • 用ObjectOutputStream/ObjectInputStream实现对象的串行化
    ◇ 通过ObjectOutputStream的writeObject方法将一个对象写入到流中
      ▪ public final void writeObject(Object obj) throws IOException
    ◇ 通过ObjectInputStream的readObject方法将一个对象从对象流中读出
      ▪ public final Object readObject() throws IOException, ClassNotFoundException
    ◇ ObjectOutputStream实现了java.io.DataOutput接口
    ◇ ectInputStream实现了java.io.DataInput接口

实例

/*输出对象*/
public class SerializeDate {
SerializeDate( ){
Date d = new Date( );
try {
ObjectOutputStream s= new ObjectOutputStream(
new FileOutputStream(“date.ser”));
s.writeObject(d);
s.close( );
}catch( IOException e){
e.printStackTrace( );
}
}
public static void main(String args[]){
SerializeDate b = new SerializeDate();
}
}
/*输入对象*/
public class UnSerializeDate {
Date d = null;
UnSerializeDate() {
try {
ObjectInputStream s = new ObjectInputStream(
new FileInputStream("date.ser"));
Object o=s.readObject();
if(o instanceof Date)
d = (Date) o;
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
UnSerializeDate us = new UnSerializeDate();
System.out.println(us.d.toString());
}
}

注意:
  一个类只有实现了Serializable接口,其对象才是可串行化的

(未完待续.....)

Java:IO流与文件基础的更多相关文章

  1. Java基础教程:IO流与文件基础

    Java:IO流与文件基础 说明: 本章内容将会持续更新,大家可以关注一下并给我提供建议,谢谢啦. 走进流 什么是流 流:从源到目的地的字节的有序序列. 在Java中,可以从其中读取一个字节序列的对象 ...

  2. java io流 对文件夹的操作

    java io流 对文件夹的操作 检查文件夹是否存在 显示文件夹下面的文件 ....更多方法参考 http://www.cnblogs.com/phpyangbo/p/5965781.html ,与文 ...

  3. java io流 创建文件、写入数据、设置输出位置

    java io流 创建文件 写入数据 改变system.out.print的输出位置 //创建文件 //写入数据 //改变system.out.print的输出位置 import java.io.*; ...

  4. java IO流 Zip文件操作

    一.简介 压缩流操作主要的三个类 ZipOutputStream.ZipFile.ZipInputStream ,经常可以看到各种压缩文件:zip.jar.GZ格式的压缩文件 二.ZipEntry   ...

  5. java IO流 对文件操作的代码集合

    Io流 按照分类 有两种分类 流向方向: 有输入流和输出流 按照操作类型有:字节流和字符流 按照流向方向 字节流的一些操作 //读文件 FileInputStream fis = new FileIn ...

  6. java IO流之文件切割两例(含Properties 用法)

    package cn.itcast.io.p1.splitfile; import java.io.File;import java.io.FileInputStream;import java.io ...

  7. java Io流更新文件内容

    package com.hp.io; import java.io.FileOutputStream; import java.io.IOException; public class FileOut ...

  8. java io流 对文件操作

    检查文件是否存在 获取文件路径 获取文件大小 ...... 更多参考手册 //对文件的操作 //检查文件是否存在 //获取文件路径 //获取文件大小 //文件是否可读 //文件是否可写 //.... ...

  9. 161228、Java IO流读写文件的几个注意点

    平时写IO相关代码机会挺少的,但却都知道使用BufferedXXXX来读写效率高,没想到里面还有这么多陷阱,这两天突然被其中一个陷阱折腾一下:读一个文件,然后写到另外一个文件,前后两个文件居然不一样? ...

随机推荐

  1. 【.net 深呼吸】细说CodeDom(5):类型成员

    前文中,老周已经厚着脸皮介绍了类型的声明,类型里面包含的自然就是类型成员了,故,顺着这个思路,今天咱们就了解一下如何向类型添加成员. 咱们都知道,常见的类型成员,比如字段.属性.方法.事件.表示代码成 ...

  2. VisualVM通过jstatd方式远程监控远程主机

    配置好权限文件 [root@test bin]# cd $JAVA_HOME/bin [root@test bin]# vim jstatd.all.policy grant codebase &qu ...

  3. 学点HTTP知识

    不学无术 又一次感觉到不学无术,被人一问Http知识尽然一点也没答上来,丢人丢到家了啊.平时也看许多的技术文章,为什么到了关键时刻就答不上来呢? 确实发现一个问题,光看是没有用的,需要实践.看别人说的 ...

  4. ASP.NET Aries 入门开发教程5:自定义列表页工具栏区

    前言: 抓紧时间,继续写教程,因为发现用户期待的内容,都在业务处理那一块. 不得不继续勤劳了. 这节主要介绍工具栏区的玩法. 工具栏的默认介绍: 工具栏默认包括5个按钮,根据不同的权限决定显示: 添加 ...

  5. jQuery学习之路(5)- 简单的表单应用

    ▓▓▓▓▓▓ 大致介绍 接下来的这几个博客是对前面所学知识的一个简单的应用,来加深理解 ▓▓▓▓▓▓ 单行文本框 只介绍一个简单的样式:获取和失去焦点改变样式 基本结构: <form actio ...

  6. mysql进阶之存储过程

    往往看别人的代码会有这样的感慨: 看不懂 理还乱 是离愁 别是一番滋味在心头 为什么要使用存储过程? 在mysql开发中使用存储过程的理由: 当希望在不同的应用程序或平台上执行相同的函数,或者封装特定 ...

  7. Javascript实现HashTable类

    散列算法可以尽快在数据结构中找出指定的一个值,因为可以通过Hash算法求出值的所在位置,存储和插入的时候都按照Hash算法放到指定位置. <script> function HashTab ...

  8. Java程序员:工作还是游戏,是该好好衡量一下了

    前阵子我终于下定决心,删掉了硬盘里所有的游戏. 身为一个程序猿,每天都要和各种新技术打交道,闲暇时间,总还得看一下各大论坛,逛逛博客园啥的,给自己充充电.游戏的话,其实我自小就比较喜欢,可以算是一种兴 ...

  9. SQL SERVER导入数据到ORACLE的方法总结

    我们偶尔会有将数据从SQL SERVER导入到ORACLE当中的这种需求,那么这种跨数据库导数有那些方法呢?这些方法又有那些利弊呢? 下面比较肤浅的总结了一些可行的方法. 1:生成SQL脚本然后去OR ...

  10. Linux设备管理(一)_kobject, kset,ktype分析

    Linux内核大量使用面向对象的设计思想,通过追踪源码,我们甚至可以使用面向对象语言常用的UML类图来分析Linux设备管理的"类"之间的关系.这里以4.8.5内核为例从kobje ...