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. 为C# as 类型转换及Assembly.LoadFrom埋坑!

    背景: 不久前,我发布了一个调试工具:发布:.NET开发人员必备的可视化调试工具(你值的拥有) 效果是这样的: 之后,有小部分用户反映,工具用不了(没反应或有异常)~~~ 然后,建议小部分用户换个电脑 ...

  2. log4net使用手册

    1. log4net简介 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.Java平台下,它还 ...

  3. Tomcat常见问题及常用命令

    很长时间不用tomcat好多命令都忘记了,所以准备自己记录下来,以便参考.刚好也希望可以开始养成记博客的好习惯. 1.查看java的版本号 进入java的安装目录后,使用命令:java -versio ...

  4. Spring注解

    AccountController .java Java代码   1.        /** 2.         * 2010-1-23 3.         */ 4.        packag ...

  5. React Native Android gradle下载慢问题解决

    很多人会遇到 初次运行 react-native run android的时候 gradle下载极慢,甚至会失败的问题 如下图 实际上这个问题好解决的 首先 把对应版本的gradle下载到本地任意一个 ...

  6. linux-centos在VM中的网络配置

    1.自动获取IP地址 虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分配IP地址. #dhclient 自动获取ip地址命令 #ifconfig 查询系统里网卡信息,i ...

  7. 机器学习之sklearn——EM

    GMM计算更新∑k时,转置符号T应该放在倒数第二项(这样计算出来结果才是一个协方差矩阵) from sklearn.mixture import GMM    GMM中score_samples函数第 ...

  8. Python3中的字符串函数学习总结

    这篇文章主要介绍了Python3中的字符串函数学习总结,本文讲解了格式化类方法.查找 & 替换类方法.拆分 & 组合类方法等内容,需要的朋友可以参考下. Sequence Types ...

  9. ReactNative&weex&DeviceOne对比

    React Native出来有一段时间了,国内的weex和deviceone是近期发布的,我可以说从2011年就开始关注快速开发的跨平台平台技术了,接触过phoneGap.数字天堂.appcan等早期 ...

  10. Redux初见

    说到redux可能我们都先知道了react,但我发现,关于react相关的学习资料很多,也有各种各样的种类,但是关于redux简单易懂的资料却比较少. 这里记录一下自己的学习理解,希望可以简洁易懂,入 ...