计算机I/O

理解IO先要知道计算机对数据的输入输出是怎么处理的,下面一张图可以大致理解:

可以看出所谓输入是外部数据向CPU输入,而输出是CPU将数据输出到我们可见的地方,例如文件、屏幕等。而计算机通常是通过流来传递数据。

Java I/O

Java中的IO包中的类可以处理不同类型的流,例如:字节流(byte[])、字符流(character)、文件流、对象流等。

java.io中的抽象类:

  • 处理字节流的抽象类:InputStream和OutputStream
  • 处理过滤流的抽象类:FilterOutputStream和FilterInputStream
  • 处理字符流的抽象类:Reader和Writer
  • 处理压缩流的抽象类:InflaterInputStream和DeflaterOutputStream

    它们之间的关系如下:

字符流

输入流Reader

基本的字符输入流的类结构如下,每个类的作用从类名大致可以猜出:

这里想强调的是出现的设计模式————装饰器模式:

例如其中BufferedReader是对Reader接口的其他子类的一个装饰器,封装了其他Reader接口实现类,提供更方便的方法调用。

BufferedReader的构造器如下,初始化时需要传入一个对Reader接口的实现类的对象:

public BufferedReader(Reader in){}

实例代码,读取指定路径的文件内容并输出:

public class ReaderTest {
public static String read(String path) throws IOException {
//装饰器模式,BufferedReader包装了FileReader
BufferedReader reader = new BufferedReader(new FileReader(path));
String s;
StringBuilder sb = new StringBuilder();
while ((s = reader.readLine()) != null) {
sb.append(s + "\n");
}
reader.close();
return sb.toString();
} public static void main(String[] args) throws IOException {
System.out.println(read("D:/test.txt"));
}
}

可以看出BufferedReader封装了FileReader来提供更方便的文件输入功能。

输出流Writer

类比输出流,输出流很容易理解,类关系如下:

同样也用到了装饰器模式,下面直接用代码来说明问题,这段代码目的是将in.txt的内容写到out.txt中:

public class WriterTest {
public static void main(String[] args) throws IOException{
String inFile = "D:/in.txt";
String outFile = "D:/out.txt";
BufferedReader in = new BufferedReader(new StringReader(ReaderTest.read(inFile)));
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(outFile)));
String s;
int line = 1;
while ((s = in.readLine()) != null) {
out.println(line++ + ":" + s);
}
in.close();
out.close();
System.out.println(ReaderTest.read(outFile));
}
}

我们可以看出BufferedReader封装了StringReader,BufferedWriter封装了FileWriter。

字符流就说这么多吧,具体的类用的时候再去了解也不迟。

字节流

输入流InputStream

InputStream是以字节流来读取文件的,如果文件是图片或二进制等格式,则不能以字符流来读,需要InputStream来读取。

InputStream的子类关系如下图:

值得注意的是,字节流也可以转换成字节流,利用的是InputStreamReader类,该类封装了InputStream。下面的实例代码通过两种不同的方式来读取文件内容。其中readByStream是通过字节流,而readByReader是字符流。

public class InputStreamTest {
public static void readByStream(String path) {
File f = new File(path);
try {
InputStream in = new FileInputStream(f);
int b;
while ((b=in.read()) != -1) {
char c = (char)b;
System.out.printf("%c", c);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} public static void readByReader(String path) {
File f = new File(path);
try {
InputStream in = new FileInputStream(f);
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
String string;
StringBuilder sb = new StringBuilder();
while ((string = reader.readLine()) != null) {
sb.append(string);
}
System.out.println(sb.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
String path = "D:/test.txt";
readByReader(path);
readByStream(path);
}
}

另外,值得注意的是,如果要读取中文,建议使用字符流,因为一个汉字占两个字节,而InputStream每次只会读取一个字节,因此会乱码。而InputStreamReader有一个构造函数可以设置文件编码,如上述代码中的new InputStreamReader(in, "utf-8")指定了文件编码问utf-8,因此可以很好的解决中文乱码问题。

输出流OutputStream

输出流OutputStream的作用类比于Writer,也非常容易理解,即通过字节流来把数据输出到文件、磁盘等设备中。关系如下图。

同InputStream一样,也有一个OutputStreamWriter包装了OutputStream,代码很简单我就不举例了。

RandomAccessFile 随机存取

上面这两大类IO,虽然结构清晰,但是多少还是复杂了点,于是乎,Java封装了一个文件随机存取类————RandomAccessFile。

RandomAccessFile实现了两个接口,DataInput和DataOutput,因此它同时拥有读和写两个功能,方便了我们的使用。使用时需要指定打开文件的模式,可以是“r”只读,“rw”读写等。下面是实例代码:

public class RandomAccessTest {
public static void main(String[] args) {
String filePath = "D:" + File.separator + "test.txt";
File f = new File(filePath);
try {
RandomAccessFile write = new RandomAccessFile(f, "rw");
String str = "abc, hello, randomAccess!";
//把byte[]中的字节写入文件
write.write(str.getBytes());
System.out.println("写入文件完成..."); RandomAccessFile read = new RandomAccessFile(f, "rw");
String strRead;
StringBuilder sb = new StringBuilder();
while ((strRead = read.readLine()) != null) {
sb.append(strRead);
}
System.out.println("读取文件内容:" + sb.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} }
}

【Java】基本I/O的学习总结的更多相关文章

  1. 要学Java,怎么高效地学习,怎么规划

    要学Java,怎么高效地学习,怎么规划?   题主是一个个例,99%的人(包括我自己)都没有题主这样的经历,也很难提出具有很强参考性的java学习建议.我倒是之前面试过一个跟题主有点类似的人,拿出来分 ...

  2. Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析

    经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...

  3. Java并发包源码学习之AQS框架(三)LockSupport和interrupt

    接着上一篇文章今天我们来介绍下LockSupport和Java中线程的中断(interrupt). 其实除了LockSupport,Java之初就有Object对象的wait和notify方法可以实现 ...

  4. Java并发包源码学习之AQS框架(一)概述

    AQS其实就是java.util.concurrent.locks.AbstractQueuedSynchronizer这个类. 阅读Java的并发包源码你会发现这个类是整个java.util.con ...

  5. 20145213《Java程序设计》第九周学习总结

    20145213<Java程序设计>第九周学习总结 教材学习总结 "五一"假期过得太快,就像龙卷风.没有一点点防备,就与Java博客撞个满怀.在这个普天同庆的节日里,根 ...

  6. 20145213《Java程序设计》第四周学习总结

    20145213<Java程序设计>第四周学习总结 教材学习内容总结 本周任务是学习面向对象的继承.接口以及之后的如何活用多态.(还真是路漫漫其修远兮啊!)教材也是延续上周艰深晦涩的语言风 ...

  7. 20145213《Java程序设计》第二周学习总结

    20145213<Java程序设计>第二周学习总结 教材学习内容总结 本周娄老师给的任务是学习教材的第三章--基础语法.其实我觉得还蛮轻松的,因为在翻开厚重的书本,一股熟悉的气息扑面而来, ...

  8. 20145213《Java程序设计》第一周学习总结

    20145213<Java程序设计>第一周学习总结 教材学习内容总结 期待了一个寒假,终于见识到了神秘的娄老师和他的Java课.虽说算不上金风玉露一相逢,没有胜却人间无数也是情理之中,但娄 ...

  9. 21045308刘昊阳 《Java程序设计》第九周学习总结

    21045308刘昊阳 <Java程序设计>第九周学习总结 教材学习内容总结 第16章 整合数据库 16.1 JDBC入门 16.1.1 JDBC简介 数据库本身是个独立运行的应用程序 撰 ...

  10. 20145330《Java程序设计》第四周学习总结

    20145330<Java程序设计>第四周学习总结 一周两章新知识的自学与理解真的是很考验和锻炼我们,也对前面几章我们的学习进行了检测,遇到忘记和不懂的知识就再复习前面的,如此巩固也让我对 ...

随机推荐

  1. 2018-2019-2 网络对抗技术 20165227 Exp1 PC平台逆向破解

    2018-2019-2 网络对抗技术 20165227 Exp1 PC平台逆向破解 实验内容及步骤 实验一:直接修改程序机器指令,改变程序执行流程 知识要求:Call指令,EIP寄存器,指令跳转的偏移 ...

  2. SHA算法:签名串SHA算法Java语言参考(SHAHelper.java)

    SHAHelper.java package com.util; /** * @author wangxiangyu * @date:2017年10月16日 上午9:00:47 * 类说明:SHA签名 ...

  3. Oracle实体化视图

    1.减轻网络负担:通过MV将数据从一个数据库分发到多个不同的数据库上,通过对多个数据库访问来减轻对单个数据库的网络负担.  2.搭建分发环境:通过从一个中央数据库将数据分发到多个节点数据库,达到分发数 ...

  4. linux系统编译安装软件的通用步骤

    编译安装的步骤: 1.下载源代码,并解压     tar -xf package-version.tar.{gz|bz2|xz} 注意:展开后的目录通常为package-version 2.切换至源码 ...

  5. 源码编译安装nginx1.4.7

    传统上基于进程或线程模型架构的web服务通过每进程或每线程处理并发连接请求,这势必会在网络和I/O操作时产生阻塞,其另一个必然结果则是对内存或CPU的利用率低下.生成一个新的进程/线程需要事先备好其运 ...

  6. FreeSWITCH与PSTN对接

    FreeSWITCH与PSTN电话系统对接设定 一.环境介绍 我们目前使用模拟的话机连接到电信运营商,购买他们配套的电话总机,勉强实现了公司的基本通话.但是客户电话总机系统以及升级添加新的应用不但费用 ...

  7. 在try-catch机制优化IO流关闭时,OutputStreamWriter 数据流被截断

    1.前言 try-catch常规的格式是try{……}catch(){……}finallly{……},如果优化成try(……){……}catch(){……}finallly{……},此时流就可以自动关 ...

  8. gulp自动化构建教程

    gulp及gulpfile.js编写示例    本文主要记录一个gulpfile.js示例,以免以后用的时候遗忘.但首先还是要了解gulp是什么以及如何使用. 一.什么是gulp 简单来说:就是压缩前 ...

  9. JVM内存管理概述

    1.概述 java不在需要开发人员显示的分配内存和回收内存,而是由JVM自动管理内存的分配和回收(又称为垃圾回收-GC),这简化了编程难度,但同时可能使得程序员在不知不觉中浪费了很多内存,导致JVM花 ...

  10. 性能测试二十二:环境部署之Nginx

    由于单纯用tomcat只能通过ip+端口号的形式访问,这样只能访问一个tomcat,而真实项目中又不可能只用一两个tomcat,所以就需要Nginx来进行分配访问请求, Nginx本身性能非常好,据官 ...