Java IO

Java中的输入是指从数据源等读到Java程序中,这里的数据源可以是文件,内存或网络连接,输出则是指从Java程序中写到目的地。

输入输出流可以分为以下几种类型(暂时不考虑File类)

类名 中文名
InputStream 字节输入流
OutputStream 字节输出流
Reader 字符输入流
Writer 字符输出流

Java IO共涉及40多个类,下图是字节流各个类之间的关系

abstract int read()

abstract int write()

read方法和Write方法在执行时都将阻塞

InputStream

InputStream、OutputStream、Reader、Writer都实现了Closeable接口,该接口拥有close()

OutputStream、Writer还实现了Flushable接口,该接口有flush()

InputStream

InputStream的子类及其说明有如下所示

名称 说明
BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。
ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。
DataInputStream 数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。
FileInputStream 从文件系统中的某个文件中获得输入字节。
FilterInputStream 包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。
ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。
PipedInputStream 管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。
PushbackInputStream 为另一个输入流添加性能,即“推回 (push back)”或“取消读取 (unread)”一个字节的能力。
SequenceInputStream 表示其他输入流的逻辑串联。

组合流过滤器

FileInputStream

FileOutputStream

提供一个磁盘文件的输入输出流,只支持字节级别的读写

FileInputStream fin = new FileInputStream("test.txt");

byte by =(byte) fin.read();

蕴含着装饰着模式的设计思想

嵌套过滤器来实现多重功能

文本输入输出

PrintWriter以文本格式打印字符串和数字,

PrintWriter out = new PrintWriter("test.txt");

out.print("hello ");

out.println(123);

将hello 123写入文本文件test.txt

OutputStream

OutputStream的子类及其说明有如下所示

名称 说明
BufferedOutputStream 该类实现缓冲的输出流。
ByteArrayOutputStream 此类实现了一个输出流,其中的数据被写入一个 byte 数组。
DataOutputStream 数据输出流允许应用程序以与机器无关方式将基本 Java 数据类型写入输出流中。
FileOutputStream 文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。
FilterOutputStream 此类是过滤输出流的所有类的超类。
ObjectOutputStream ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。
PipedOutputStream 可以将管道输出流连接到管道输入流来创建通信管道。
PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。

对于类中方法的熟悉不详述了,可以参照JDK文档,或者可以试着在IDE中,实例化上面的类,使用此类对象时,按下.之后,会出现提示框,再一个一个熟悉就好了。

简单示例

下面以文件数据的输入输出说明以上类的使用。

1.在java程序中生成1~20的平方数,并输出到文件中。


package com.songpu; import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream; public class MyFileOutputStream { public static void main (String[] args) throws IOException{
try{
FileOutputStream fos = new FileOutputStream("F:\\test1.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos,1024);
PrintStream ps = new PrintStream(bos,false);
System.setOut(ps);
for(int i= 0;i<20;i++){
System.out.println(i*i);
}
ps.close();
}catch(IOException e){
e.printStackTrace();
}
} }

2.将刚才生成的文件中的数据输入到程序,并将其打印到屏幕

package com.songpu;

import java.io.*;

public class MyFlieInputStream {

	public static void main(String[] args) throws IOException {
File file = new File("F:\\test1.txt");
FileInputStream in = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(in);
byte[] bytes = new byte[(int) file.length()]; do {
bis.read(bytes);
System.out.println(new String(bytes)); }while (bis.read() != -1);
bis.close();
in.close(); }
}

再以序列化与反序列化的例子说明ObjectInputStream和ObjectOutputStream的使用

Java序列化是将对象变成二进制形式的一连串字符描述的过程,反序列化就是序列化的相反过程,把这些字符重建为对象。

序列化和反序列化的作用,是保存对象到文件或数据库中,使对象能够传输,序列化的要求是实现Serializable接口,代码如下所示

package com.songpu.serial;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
/*
* 待序列化的类,实现序列化接口
*/
class Person implements Serializable{
public String name;
public int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
} /*
* 测试类
*/
public class SerialTest{ public static void main(String[] args) throws IOException, ClassNotFoundException{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\test.txt"));
Person p0 = new Person("tangsong",21);
oos.writeObject(p0);
oos.flush();
oos.close();
deserial();
} public static void deserial() throws ClassNotFoundException, IOException{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\test.txt"));
Person p1 = (Person)ois.readObject();
ois.close();
System.out.println("Name="+p1.getName()+";Age="+p1.getAge());
}
}

前面的博文介绍了字节流,那字符流又是什么流?从字面意思上看,字节流是面向字节的流,字符流是针对unicode编码的字符流,字符的单位一般比字节大,字节可以处理任何数据类型,通常在处理文本文件内容时,字符流可以一个一个字符的读取,也可以一行一行字符的读取。

字符流类型包括Writer和Reader及其子类如图所示

Writer的子类

名称 说明
BufferedWriter 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
CharArrayWriter 此类实现一个可用作 Writer 的字符缓冲区。
FileWriter 用来写入字符文件的便捷类。
FilterWriter 用于写入已过滤的字符流的抽象类。
OutputStreamWriter OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。
PipedWriter 传送的字符输出流。
PrintWriter 向文本输出流打印对象的格式化表示形式。
StringWriter 一个字符流,可以用其回收在字符串缓冲区中的输出来构造字符串。

Reader的子类

名称   |      说明

--------------|---------

BufferedReader | 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

CharArrayReader | 此类实现一个可用作字符输入流的字符缓冲区。

FileReader |用来读取字符文件的便捷类。

FilterReader |用于读取已过滤的字符流的抽象类。

InputStreamReader | InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。

LineNumberReader |跟踪行号的缓冲字符输入流。

PipedReader | 传送的字符输入流。

PushbackReader|允许将字符推回到流的字符流 reader。

StringReader | 其源为一个字符串的字符流。

下面的例子是FileWriter将字符输出到流中,再冲刷到文件中,文件中的字符通过FileReader读入到Java程序,然后显示在屏幕。

package com.songpu.io;
import java.io.*;
public class MyWriter {
/*
* 将字符输出到文本文件中
* 并将文本文件中的字符输入到屏幕
*
*/
public static void main(String[] args) throws IOException{
File f = new File("F:\\test3.txt");
FileWriter fw =new FileWriter(f);
fw.write("hahahahahahahaha\n");
fw.write("xixixixixixixi\n");
//将流中的信息冲刷到文件中
fw.flush();
fw.close();
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
String s =null;
while((s = br.readLine()) != null){
System.out.println(s);
}
fr.close();
br.close();
}
}

字节流和字符流的连接

InputStreamReader、OutputStreamWriter是连接字节流和字符流的桥梁以一个简单的例子来说明InputStreamReader的用法。


package com.songpu.io;
import java.io.*;
public class ByteToChar {
public static void main(String[] args) throws IOException{
File f = new File("H:\\Programming\\Java\\JavaTest\\src\\com\\songpu\\io\\ByteToChar.java");
FileInputStream fis = new FileInputStream(f);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String s = null;
while((s = br.readLine()) != null){
System.out.println(s);
}
br.close();
isr.close();
fis.close();
}
}

File类

File类直接继承至Object类,并且实现了Serializable和Comparable接口。对于File类只需知道它的方法,熟悉这些方法,可以参照我们平时操作文件或目录时候

做法

  • 包含的方法

    • 创建方法
    • 删除方法
    • 判断方法
    • 获取方法
    • 设置方法
    • 文件过滤

创建方法

方法 说明
boolean createNewFile() 当且仅当不存在具有此抽象路径名指定名称的文件时,创建一个新的空文件
boolean mkdir() 创建此抽象路径名指定的目录
boolean mkdirs() 创建此抽象路径名指定的目录,包括所有必需的父目录(不存在)
static File createTempFile(String prefix, String suffix) 在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。
static File createTempFile(String prefix, String suffix, File directory) 在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称
boolean renameTo(File dest) 重新命名此抽象路径名表示的文件

删除方法

方法 说明
boolean delete() 删除此抽象路径名表示的文件或目录
void deleteOnExit() 在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。

判断方法

方法 说明
boolean canExecute() 判断应用程序是否可以执行此抽象路径名表示的文件。
boolean canRead() 判断 应用程序是否可以读取此抽象路径名表示的文件。
boolean canWrite() 判断应用程序是否可以修改此抽象路径名表示的文件。
boolean exists() 判断此抽象路径名表示的文件或目录是否存在。
boolean isAbsolute() 判断此抽象路径名是否为绝对路径名。
boolean isDirectory() 判断此抽象路径名表示的文件是否是一个目录。
boolean isFile() 判断此抽象路径名表示的文件是否是一个标准文件。
boolean isHidden() 判断此抽象路径名指定的文件是否是一个隐藏文件。

获取方法

方法 说明
String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串。
File getCanonicalFile() 返回此抽象路径名的规范形式。
String getCanonicalPath() 返回此抽象路径名的规范路径名字符串。
long getFreeSpace() 返回此抽象路径名指定的分区中未分配的字节数。
String getName() 返回由此抽象路径名表示的文件或目录的名称。
String getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。
File getParentFile() 返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null
String getPath() 将此抽象路径名转换为一个路径名字符串。
long getTotalSpace() 返回此抽象路径名指定的分区大小。
long getUsableSpace() 返回此抽象路径名指定的分区上可用于此虚拟机的字节数。
File getAbsoluteFile() 返回此抽象路径名的绝对路径名形式。
long lastModified() 返回此抽象路径名表示的文件最后一次被修改的时间。
long length() 返回由此抽象路径名表示的文件的长度。
String[] list() 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
String[] list(FilenameFilter filter) 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。

设置方法

方法 说明
boolean setExecutable(boolean executable) 设置此抽象路径名所有者执行权限的一个便捷方法。
boolean setExecutable(boolean executable, boolean ownerOnly) 设置此抽象路径名的所有者或所有用户的执行权限。
boolean setLastModified(long time) 设置此抽象路径名指定的文件或目录的最后一次修改时间。
boolean setReadable(boolean readable) 设置此抽象路径名所有者读权限的一个便捷方法。
boolean setReadable(boolean readable, boolean ownerOnly) 设置此抽象路径名的所有者或所有用户的读权限。
boolean setReadOnly() 标记此抽象路径名指定的文件或目录,从而只能对其进行读操作。
boolean setWritable(boolean writable) 设置此抽象路径名所有者写权限的一个便捷方法。
boolean setWritable(boolean writable, boolean ownerOnly) 设置此抽象路径名的所有者或所有用户的写权限。
String toString() 返回此抽象路径名的路径名字符串。

文件过滤

方法 说明
File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
File[] listFiles(FileFilter filter) 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。
File[] listFiles(FilenameFilter filter) 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。
static File[] listRoots() 列出可用的文件系统根。

随机访问文件

RandomAccessFIle类

可以在文件中的任何位置查找或写入数据

Java IO之字符流和文件的更多相关文章

  1. Java IO: 其他字符流(下)

    作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) 本小节会简要概括Java IO中的PushbackReader,LineNumberReader,St ...

  2. java IO之 字符流 (字符流 = 字节流 + 编码表) 装饰器模式

    字符流 计算机并不区分二进制文件与文本文件.所有的文件都是以二进制形式来存储的,因此, 从本质上说,所有的文件都是二进制文件.所以字符流是建立在字节流之上的,它能够提供字符 层次的编码和解码.列如,在 ...

  3. [Java IO]03_字符流

    Java程序中,一个字符等于两个字节. Reader 和 Writer 两个就是专门用于操作字符流的类. Writer Writer是一个字符流的抽象类.  它的定义如下: public abstra ...

  4. Java IO编程——字符流与字节流

    在java.io包里面File类是唯一 一个与文件本身有关的程序处理类,但是File只能够操作文件本身而不能够操作文件的内容,或者说在实际的开发之中IO操作的核心意义在于:输入与输出操作.而对于程序而 ...

  5. java 21 - 4 字符流的文件复制操作以及简化

    既然字节流可以复制文件,那么字符流当然也有. 同样的思路: 数据源: a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader目的地: b.txt -- 写出数据 -- ...

  6. Java——IO类 字符流概述

    body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...

  7. Java IO(四--字符流基本使用

    在上一节,介绍了字节流的基本使用,本节介绍一下字符流的使用 Reader: public abstract class Reader implements Readable, Closeable { ...

  8. Java IO系统--字符流

    字符流:尽管字节流提供了处理任何类型输入/输出操作的足够功能,它们补鞥呢直接操作Unicode字符.字符流层次结构的顶层是Reader和Writer抽象类.类似于InputStream和OutputS ...

  9. Java IO之字符流

    public static void main(String[] args) { FileWriter fw = null; try { fw = new FileWriter("/User ...

随机推荐

  1. Java中常用集合操作

    一.Map 名值对存储的. 常用派生类HashMap类 添加: put(key,value)往集合里添加数据 删除: clear()删除所有 remove(key)清除单个,根据k来找 获取: siz ...

  2. 游走 bzoj 3143

    游走(2s 128MB)walk [问题描述] [输入格式] [输出格式] [样例输入] 3 3 2 3 1 2 1 3 [样例输出] 3.333 [样例说明] 题解: 主要算法:贪心:高斯消元: 题 ...

  3. Take into Action!

    很久没有认真地写文字了. 刚毕业一两年断断续续在csdn上写过一些当时的工作记录,然后没有坚持下去.有时候是觉得自己不牛,记录的东西旁人看起来也许不值一提:有时候觉得结婚生娃了,然后时间不够用(确实是 ...

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

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

  5. Ubuntu下配置apache开启https

    一.HTTPS简述随着网络的日常,信息安全越来越重要,传统的网站都是http协议明文传输,而HTTPS协议是由SSL+HTTP协议构建的可进行加密传输.身份认证的网络协议,比http协议安全. 那ht ...

  6. 【AI开发第一步】微软认知服务API应用

    目录 介绍 API分类 使用‘视觉’API完成的Demo 点击直接看干货 介绍 从3月份Google家的阿尔法狗打败韩国围棋冠军选手李世石,到之后微软Build2016大会宣布的“智能机器人”战略.种 ...

  7. Linux 桌面系统字体配置要略

    字体显示效果测试 这一段是为了测试宋体字的显示效果,包括宋体里面自带的英文字体,“This is english,how does it look like?”.这一行是小字.后面几个字是加粗的宋体. ...

  8. 重学hadoop技术

    最近因为做了些和hadoop相关的项目(虽然主要是运维),但是这段经历让我对hadoop的实际运用有了更加深入的理解. 相比以前自学hadoop,因为没有实战场景以及良好的大数据学习氛围,现在回顾下的 ...

  9. 写自己的Socket框架(三)

    在通信写完了以后,应用层接收到Socket抛上来的byte[],这个时候对于实际的写逻辑的开发者来说,这样的数据并不友好,我们就需要在应用层统一一个包的规则(应用层协议),处理完以后,然后再传给实际的 ...

  10. Java 8函数编程轻松入门(四)方法引用

    C#中系统提供了许多IEnumerable的扩展方法.同样在Java 8中新引入了Collector类. 1.方法引用 定义: 简而言之:就是一个Lambda表达式.在Java 8中,我们我们会使用L ...