---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
IO(Input Output)流
一、IO流作用
IO流用来处理设备之间的数据传输
java对数据的操作是通过流的方式
java用于操作流的对象都在IO包中
二、流的分类
流按操作数据分为两种:字节流和字符流。字节流可以融入编码表,可以自己指定编码表。字节流是通用的,字符流是基于字节流的。
流按流向分为:输入流和输出流。
三、编码表
ASCII(一个字节):美国编码表
GBK(两个字节):中国编码表
UnCode(两个字节表示):国际编码表 后来优化成UTF-8(所占字节自动分配)
乱码:一个格式的编码方式进行存储,然后以另一种编码方式进行读取,这样会导致乱码
四、IO流常用基类
·字节流的抽象基类:
InputStream (读) OutputStream(写)
·字符流的抽象基类:
Reader(读) Writer(写)
注: 由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。前缀名是对象的功能。如:
InputStream 的子类 FileInputStream
Reader 的子类 FileReader。
五、FileWriter
1,方法 (这些方法都会抛出IOException异常):
void writer(int ch);写入单个的字符
void writer(char[] arr);写入一个字符数组
void writer(char[] ,int off,int len);将指定字符数组中的一部分进行写入
void writer (String str);写入一个字符串
vois writer (String str,int off,int len);将字符串的指定部分进行写入
void flush()刷新该流的缓冲
void close()关闭此流,但要先刷新它(其实就是先调用flush()方法刷新一次,然后又调用底层关闭流的方法)
既然IO流是用于操作数据的,那么数据的最常见体现形式是:文件。
2,子类 FileWriter
创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件,而且该文件会被创建到指定目录下,
如果该目录下已有同名文件,将被覆盖。
如:
1,FileWriter fileWriter = new FileWriter("Demo.txt");
jvm执行完此语句时,会在堆内存中建立一个FileWriter对象,并在当前目录下建立一个Demo.txt文件如果些文件存在
将会被覆盖。 其实该步就是在明确数据要存放的目的地
2,调用write方法,将字符串写入到流中。
fileWriter.write("abcde");
3, 刷新流对象中的缓冲中的数据,将数据刷到目的地中
fileWriter.flush();
4,关闭流资源,但关闭之前会刷新一次内部的缓冲区中的数据,将数据刷到指定的位置
fileWriter.close();
六,对IO异常的处理
对其进行捕捉和处理。如下程序:
public class FileWriterDemo{
public static void main(String[] args){
//在try外面建立对象的引用
FileWriter fw = null;
try{
fw = new FileWriter("Test.txt");
fw.write("heihie");
}
catch(IOException io){
System.out.println(io);
}
//一定要执行的动作关闭资源
finally{
try{
if(fw != null)
fw.close();
}
catch(IOException io){
System.out.println(io);
}
}
}
}
七、文本数据的续写
构造函数:
FileWriter(String name,boolean apped): 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
当传递一个true参数,代表不覆盖已有的文件,并在已有文件的未尾处进行数据续写
换行: ·在window中换行用:\r\n (wind中的记事本只能识别\r\n)
·在Linux中换行用:\n
八、文本文件读取方式:
1,Reader中的方法:
abstract
void close():关闭该流并释放与之关联在所有资源
void mark(int readAheadLimit) 标记流中的当前位置
boolean markSupported()判断此流是否支持mark()操作
int read()读取单个字符。返回字符的ASCII值,如果已到达流的未尾时,则返回-1
int read(char[] buf)将字符读入数组
abstract int read(char[] buf,int off,int len)将字符读入数组的某一部分
int read(CharBuffer target) 将字符读入指定的字符缓冲区
boolean ready():判断是否准备读取此流
void reset():重置该流
long skip(long n)路过字符
注:read()方法一次读一个字符,而且会自动向下读
2,FileReader
·构造函数 :
FileReader(String name)
FileReader(File file)
·建立读取流步骤
方法一(read()方法):
public static void main(String[] args){
//在try块的外面建立读取流的引用
FileReader fr = null;
try{
//让读取流与一个文件进行关联
fr = new FileReader("hehe.txt");
int ch = 0;
//循环的来读取文件中的字符
while((ch = fr.read()) != -1){
System.out.println((char)ch);
}
catch(FileNotFoundException ex){
System.out.println("没有找到要读取的文件");
throw new RuntimeException();
}
catch(IOException e){
throw new RuntimeException();
}
finalyy{
try{
//判断此引用是不是为空,如不为null关闭资源
if(fr != null)
fr.close();
}
catch(IOException io){
throw new RuntimeException("流资源关闭失败");
}
}
}
}
方法二,使用read(char[] buf)来读取
public static void readMethodTwo(){
FileReader fr = null;
try{
//与文件进行关联
fr = new FileReader("Test.txt")
;
char[] buf = new char[1024];
int num = 0;
while((num = fr.read(buf)) != -1){
System.out.println(new String(buf,0,num))
;
}
}
catch(IOException io)
{
throw new RuntimeException("出问题")
;
}
finally{
try{
//先判断下是否为空,如不为空关闭流资源
if(fr != null)
fr.close();
}
catch(IOException io){
throw new RuntimeException();
}
}
}
3,复制的原理:
其实就是将某盘(c盘)下的文件数据存储到另一个盘(d盘)的一个文件中
步骤:
1,在d盘下创建一个文件,用于存储c盘文件中的数据。
2,定义读取流和c盘文件进行关联。
3,通过不断的读写完成数据的存储。
4,关闭流资源
九、字符流的缓冲区
1,缓冲区的出现提高了流对数据的读写效率,而出现的,所有在创建缓冲区之前,必须要先有流对象
2,对应类
BufferedWriter
中的newLine()是一个跨平台的换行符
BufferedReader
中的String readLine()读出一行数据 ,不会读取换行符的。
3,缓冲区的关闭其实就是关闭它所提高效率的流对象,
十,readLine的原理:
无论是读一行,获取读取多个字符,其实最终都是在在硬盘上一个一个读取。所以最终使用的还是read方法
一次读一个的方法,只过就是先存放在一个容器里,当读到换行符时,才会返回。
十一,LineNumberReader(BuffferedReader的子类)
1,此类是获取或设置行号的一个包装类
2,特有方法:
int getLineNumber():获取行号
void setLineNumber(int) :设置行号
十二,字节流
InputStream:字节读取流
OutputStream:字节写入流
1.OutputStream中的方法(不需要刷新)
void close();关闭此流关联的资源
void flush();刷新此输出流并强制写出所有缓冲的输出字节
void write(byte[] byte);将byte数组定入此输出流。
void write(byte[]b,int off,int len);将指定byte数组中从偏移量off开始的len个字节写入此输出流
void write(int b)将指定的字节写入此输出流
2,InputStream中的方法:
int available(); 返回这个文件的大小。(\r\n占两个字节)可以根据返回值定义一个刚刚大小的数组(存放临时读取的字节)
int read();读取一个字节并返回
int read(byte[] byte):将字节读取到byte数组中返回读取的个数
3,字节流中的read方法返回值为什么不是byte类型?
因为字节流在读取数据时都是二进制的数据,有可能会读到连续8个1的情况,,这时程序会返回-1,也就是read方法结束的标志,如果返回是
int类型时,系统会自动进行类型提升但是,-1进行提升时还会是-1,所以这时为了保留原来的8位,,就要&255这样可以保留最低8位了,
而当写入一个字节时,,write方法会自动将int类型的数据强制转换成byte类型数据进行写入,所以复制后的文件大小不会改变。
4,BufferedInputStream中的read方法的原理?
BufferedInputStream中的read方法是利用传入的InputStream对象中的read方法将数据读到一个临时的数组中,然后,在从数组一个一个
的向外读取。也就是说调用传入对象 中的read方法将一个数据读取到指定的数组中的,然后在数组中一个一个的读取,当数组中的数据都
读完时,再去读取一批数据到数组中,如此循环。
十三,键盘录入
System.out:对应的是标准输出设备:控制台
System.in:对应的是标准输入设备:键盘
1,read方法是一种阻塞式方法。
2,转换流:
将字节流转换成字符流,在构造函数类型是字节流对象
InputStreamReader:
将字符流转换成字节流。
OutputStreamWriter:
3,代码:
package io;
import java.io.*;
public class KeyBoardInputDemo{
public static void main(String[] args){
inputDemo();
}
public static void inputDemo(){
BufferedReader bufr = null;
try{
bufr = new BufferedReader(new InputStreamReader(System.in))
;
String str = null;
while((str = bufr.readLine()) != null){
if("over".equals(str))
break;
System.out.println(str.toUpperCase());
}
}
catch(IOException e){
throw new RuntimeException("键盘录入出问题了,");
}
finally{
try{
if(bufr != null)
bufr.close();
}
catch(IOException i){
throw new RuntimeException("关闭流失败!")
;
}
}
}
}
十三。流操作的规律:
通过三个明确来完成
1,明确源和目的:
源: 输入流 InputStream Reader
目的:输出流 OutputStream Writer
2,操作的数据是否是纯文本:
是: 字符流
不是: 字节流
3,当体系明确后,在明确要使用哪 个具体的对象通过设备来进行区分。
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台
4,是否需要提高效率?
是:加入缓冲技术
5,转换流什么时候使用?
转换流 是字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流
6,改变标准的输入输出设备:
System.setIn(InputStream in);
System.setOut(PrintStream out)
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------