关于流的概念

Java 由流来完成具体的IO操作,虽然面对的是不同的外设(网络、鼠标、键盘)IO流使用与全部的外设,在底层Java已经将具体与物理设备交互的细节都处理好了。

流的分类:

从功能上

  输入流:从外部到程序

  输出流:从程序到外部

  注意所谓的输入以及输出是相对于程序而言的,这一点很关键,在流类互相嵌套的时候千万要把握好这一点。

从结构上

  字节流和字符流(字符流实际上是对字节流的封装)

  字节流最低层的两个抽象类是 inputStream 以及 outputStream

  字符流最低层的两个抽象类是 Reader 以及 Writer

还可以有其他的分类方式

  节点流:从特定的地方进行读写的流,直接与目标进行交互。例如从磁盘或者内存的一块区域来进行读写。

  过滤流:使用节点流或者过滤流作为输入或者输出,使用一个已经存在的输入或者是输出创建的流类。

  通常的数据读写的相关逻辑:

  1、 open a stream

  2、 while more information(一边进行读写操作一边进行判断)

  3、 read(write) information

  4、 close information(比较重要 易忽略)

字节流相关

  抽象类inputStream以及outputStream定义了实现其他类的关键方法,最主要的是read以及write方法,两种方法分别在inputStream以及outputStream中被定义,并且被派生类所重写,这些从inputStream与outputStream派生出来的类会针对不同的外设来进行处理。

  三个主要的read方法

  1、abstract int read()

  2、int read(byte[]b)

  3、int read (byte[]b,int offset,int len)

  2,3 两个read 方法通过继承1 的read方法来实现,具体不同的类会有不同的read实现方法。

  FileinputStream的演示(输入流的最一般的组普通的表示形式):

package com.file.fileInputStream;

import java.io.*;

public class fileInputStreamtest {
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("F:\\filetest.txt");
// 一次取200个字符
byte[] buffer = new byte[200];
int length;
// read(Byte[]b (字节数组即目标数组),int offset(目标数组起始偏移),int len(每次读取的字字节的长度))
// 注意read方法 要是流已经读完了 就会返回-1 要是没读完就会返回读入buffer的字节数目
while (-1 != (length = is.read(buffer, 0, 200))) {
// 将字符数组转化为子付串
String str = new String(buffer, 0, length);
System.out.println(str); }
// 关闭流
is.close(); } }

这里要注意buffer指定的大小的问题,因为汉字的情况下,按照默认的编码方式(GBK)是两个字节表示一个汉字,要是把buffer的大小设置成一个比较小的奇数比如 3 最后输入汉字的时候 很容易出现乱码,一般把大小设置成1024 2048 这个样子的,都是2的倍数。

字符流inputstream的所有的子类:

AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream

字符流outputstream的所有的子类:

ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream

字符流中的节点流与过滤流:

节点流 直接与目标文件打交道 比如 FileOutputstream

过滤流 用于对节点流进行包装 减少IO的次数

下面的一个例子是用节点流将数据读入文件再用过滤流将数据从文件中读出:

package com.bytestream.bufferinput;
import java.io.*;
public class bufferTest {
public static void main(String[] args) throws Exception {
OutputStream os=new FileOutputStream("F:\\filetest.txt");
String str="helloworld ";
//将字符串转化为字符数组
byte[]buffer=str.getBytes();
os.write(buffer);
//想要追加内容 后面的true 表示以append的方式进行追加
OutputStream os2=new FileOutputStream("F:\\filetest.txt",true);
String str2="this is added information by append way";
os2.write(str2.getBytes());
os.close();
os2.close(); //利用过滤流 将文件中的内容写入到程序中
InputStream is=new FileInputStream("F:\\filetest.txt");
InputStream bis=new BufferedInputStream(is); byte[]b=new byte[200];
int length;
while(-1!=(length=bis.read(b, 0, 128))){
//注意这里不能使用toString函数 只能是使用newstring生成一个新的string否则会是乱码
//具体的原因还不是太清楚
String bstr1=b.toString();
String bstr2=new String(b,0,length);
System.out.println(bstr1);
System.out.println(bstr2);
} is.close();
bis.close(); } }
输出:
[B@777d57d6
helloworld this is added information by append way

注意直接用toString转化byte数组再打印出来会出现乱码问题

其他的一些过滤流

ByteArrayInputStream以及ByteArrayoutputStream是将字节数组当做源实现输入和输出。

具体例子:

package com.bytestream.ByteArrayinputstreamtest;

import java.io.*;

public class bytearratInputstreamtest {
public static void main(String[] args) throws Exception {
String tmp="the test of bytearraystream";
byte[] b=tmp.getBytes();
ByteArrayInputStream bai=new ByteArrayInputStream(b);
int c;
for(int i=0;i<2;i++){
//采用这种方式是每次读一个字节
while(-1!=(c=bai.read())){
if(i==0)
System.out.print((char)c);
else
//只能是英文情况下
System.out.print(Character.toUpperCase((char)c));
} //将一个流重读了一次 默认指向流最开始的位置
//相当于将bai流重置了 要是不加这个 即使设置了循环两次也还是无效的
bai.reset();
System.out.println();
}
bai.close(); //利用bytearrayoutput将信息写入一个字符串 再利用fileoutputstream将信息写入
//注意与FileOutputStream区别 这个写入的目标对象是一个字符串而不是一个文件
ByteArrayOutputStream bao=new ByteArrayOutputStream();
String strout="test the ByteArrayOutputStream";
//将strout中的内容写入到这个ByteArayOutputStream输出流当中
//这个ByteArrayoutputstream中此时就已经存放了strout的信息 bao.write(strout.getBytes());
//将输出流转化成一个数组对象
byte[]result=bao.toByteArray();
for(int i=0;i<result.length;i++){
System.out.print((char)result[i]);
} OutputStream os=new FileOutputStream("F:\\filetest.txt");
//将ByteArrayOutputstream中的内容写入到一个文件输出流当中
bao.writeTo(os); os.close();
bao.close(); }
} 输出结果:
the test of bytearraystream
THE TEST OF BYTEARRAYSTREAM
test the ByteArrayOutputStream
对应的文件中(F:\filetest.txt)也有了对应的信息

DataInputStream和DataOutputStream可以写入或者写出多种不同的数据类型的数据

package com.bytestream.DataStream;

import java.io.*;

public class DataStream {
public static void main(String[] args) throws Exception {
//通常的过滤流的定义方式
//以缓存的方式 将不同的数据写到一个文件中
DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(new FileOutputStream("F:\\filetest.txt")));
byte b=3;
int i=12;
char c='a';
float f=3.3f;
//每种数据类型都有对应着的不同写入模式
dos.writeByte(b);
dos.writeInt(12);
dos.writeChar(c);
dos.writeFloat(f);
dos.close();
//此时 filetest.txt中的内容肯定是乱码 因为每中类型的byte数目是不一样的
DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream("F:\\filetest.txt")));
//注意读出来的顺序应该与读进去的书序一样 这样才能保证正确恢复
System.out.println(dis.readByte()+" "+dis.readInt()+" "+dis.readChar()+" "+dis.readFloat());
}
} 输出结果:
3 12 a 3.3

结果显示与输入的是一致的,要是不想这么麻烦,就将输入信息全转化为字符串,之后再输出。

Java IO(2)的更多相关文章

  1. java.IO输入输出流:过滤流:buffer流和data流

    java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? ...

  2. Java:IO流与文件基础

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

  3. Java IO之字符流和文件

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

  4. java Io流向指定文件输入内容

    package com.hp.io; import java.io.*; public class BufferedWriterTest{ public static void main(String ...

  5. java Io文件输入输出流 复制文件

    package com.hp.io; import java.io.FileInputStream; import java.io.FileNotFoundException; import java ...

  6. java Io流更新文件内容

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

  7. java IO流详解

    流的概念和作用 学习Java IO,不得不提到的就是JavaIO流. 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...

  8. java.io.NotSerializableException: test.io.file.Student

    java.io.NotSerializableException: test.io.file.Student    at java.io.ObjectOutputStream.writeObject0 ...

  9. java.io.IOException: mark/reset not supported

    java.io.IOException: mark/reset not supported at java.io.InputStream.reset(InputStream.java:348) at ...

  10. Java IO流学习总结

    Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输 ...

随机推荐

  1. React.memo

    介绍React.memo之前,先了解一下React.Component和React.PureComponent. React.Component React.Component是基于ES6 class ...

  2. EF6 MySQL错误之“Specified key was too long; max key length is 767 bytes”

    由于 MySQL Innodb 引擎表索引字段长度的限制为 767 字节,因此对于多字节字符集的大字段(或者多字段组合索引),创建索引会出现上面的错误. 以 utf8mb4 字符集 字符串类型字段为例 ...

  3. 12-jQuery获取相关尺寸

    # 相关尺寸 **获取元素相对于文档的偏移量** > var pos = $('#small').offset(); >> // console.log(pos.left);// c ...

  4. 深入JavaScript之获取cookie以及删除cookie

    cookie存在哪? 存在document.cookie中 ookie长啥样? cookie是一个字符串,长下面这样:“name=xxx; age=22;” 注意:分号后面有个空格,记住这一点,下面的 ...

  5. Python之列表、元组、字典、集合及字符串的详细使用

    1.列表 列表相当与C++中的数组,是有序的项目, 通过索引进行查找,但使用起来却方便很多,具体的操作看代码,自己实践一次就非常简单了. 注:列表一般用中括号“[ ]” #列表(数组) name_li ...

  6. Express 2015 RC for Windows 10 安装

    支持的操作系统 Windows 10 Technical Preview 硬件要求 1.6 GHz 或更快的处理器 1 GB RAM(如果在虚拟机上运行,则为 1.5 GB) 4 GB 可用硬盘空间 ...

  7. JavaScript实现生成指定范围随机数和一个包含不重复数的随机数组

    目前JavaScript里面还没有现成的方法可以实现这个简单地需求,我们就需要自己写代码了. 在js中有个函数:Math.random() 这个函数可以生成 [0,1) 的一个随机数. 我们的简单的改 ...

  8. Taro -- 微信小程序登录

    Taro微信小程序登录 1.调用Taro.login()获取登录凭证code: 2.调用Taro.request()将code传到服务器: 3.服务器端调用微信登录校验接口(appid+appsecr ...

  9. 【LeetCode】二叉查找树 binary search tree(共14题)

    链接:https://leetcode.com/tag/binary-search-tree/ [220]Contains Duplicate III (2019年4月20日) (好题) Given ...

  10. 【串线篇】spring boot自动配置精髓

    一.SpringBoot启动会加载大量的自动配置类即绿色部分 二.我们看我们需要的功能有没有SpringBoot默认写好的自动配置类: 比如HttpEncodingAutoConfiguration ...