概述:Java 流图的结构
java 基本IO 流知识:
按照类型分为:字节型和字符型
按照数据的流向分:输入流和输出流
字节流和字符流的区别
1.处理的对象不同:字节流可以处理任何类型的数据(如图片,影频,音频文件),字符流就只能处理字符型的数据。
2.读写的单位不同:字节流 (字节)为单位,字符流(字符)为单位
字符流在读取时查了指定的编码表,提高了字符高效操作的对象。处理常见的文本数据。
二.从图中结构上主要有:
字节流:
以InputStream,OutputStream 基类
其子类也都是InputStream,OutputStream为后缀名。
字符流:
以Reader,Writer 基类
其他子类都是以Reader,Writer为后缀名。
三.下面先讨论字符流,因为我们常用的都是简单的字符数据操作。
- 字符输入输出流
Reader 输入字符流的父类,它是一个抽象类。
常见方法有:
int read():读取一个字符。返回的是读到的那个字符。如果读到流的末尾,返回-1.
int read(char[]):将读到的字符存入指定的数组中,返回的是读到的字符个数,也就是往数组里装的元素的个 数。如果读到流的末尾,返回-1.
close(): 关闭该源,进行资源的释放
|-- FileReader 专门用来处理文件的字符读取流对象
常用构造方法:
|-- FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader。
|-- FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新FileReader。
|--BufferReader 字符输入流缓冲区,从中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取,要结合流才可以使用。
BufferReader bufr = new BufferReader(new FileReader(String fileName));
|--readLine():一次读一行,到行标记时,将行标记之前的字符数据作为字符串返回。当读到末尾时,返回null。
|--CharArrayReader,StringReader 两种基本的介质流,它们 把字符数组,字符串作为源的输入流的实现,分别从Char数组、String中读取数据。
|-- FilterReader 有自定义具体作为装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。
|-- InputSteamReader 作为连接字节流和字符流的桥梁,将字节流转变为字符流。
Writer 输出字符流的父类,它是一个抽象类。
常用方法:
write(ch): 将一个字符写入到流中。
write(char[]): 将一个字符数组写入到流中。
write(String): 将一个字符串写入到流中。
flush():刷新流,将流中的数据刷新到目的地中,流还存在。
close():关闭资源:在关闭前会先调用flush(),刷新流中的数据去目的地。然后关闭流。
|-- FileWriter 专门用来处理文件的字符写入流对象
常用构造方法:
|-- FileWriter (File file) 在给出 File 对象的情况下构造一个 FileWriter 对象。
|-- FileWriter (String fileName) 在给出文件名的情况下构造一个 FileWriter 对象。
注意:以上步骤会创建一个新的文件到指定目录下,如果有同名的文件存在,则会覆盖。
|-- FileWriter (String fileName,boolean append) 在给出文件名的情况下构造 FileWriter 对象,不覆盖原有文件,在其后添加数据
|-- BufferWriter 字符输出流缓冲区,从中写入文本,缓冲各个字符,从而提供字符、数组和行的高效写入。要结合流才可以使用。
BufferWriter bufw = new BufferWriter(new FileWriter(String fileName));
|--newLine():跨平台的换行符。
|-- CharArrayWriter ,StringWriter 两种基本的介质流,它们 把字符数组,字符串作为源的输出流的实现,分别从Char数组、String中写入数据。
|-- PrintWriter 传送的字符输出流。
|-- OutputSteamWriter 作为连接字节流和字符流的桥梁,将字节流转变为字符流。直接子类是FileWriter。
其他知识:1.操作流就是在调用Windows底层的输入输出流,因此流都要刷新才能实现其功能,用完以后要关闭资源。
2.Windows 换行符是由两个字符'\r\n'表示。
3.缓冲区其实就像杯子装水,而不是一滴一滴的喝。实际上就是将数组进行封装。
4.readLine()方法原理:
其实内部还是用的是read()方法,每一次读一个字符,临时存储起来,当读到'\r\n'即换行符时,再将临时容器中存储的数据一次性返回。
自定义一个类中功能与readLine()一致的方法
import java.io.*;
class MyBufferedReader extends Reader
{
private Reader r;
MyBufferedReader(Reader r)
{
this.r = r;
}
//可以一次读一行数据的方法。
public String myReadLine()throws IOException
{
//定义一个临时容器。原BufferReader封装的是字符数组。
//为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch=r.read())!=-1)
{
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
/*
覆盖Reader类中的抽象方法。
*/
public int read(char[] cbuf, int off, int len) throws IOException
{
return r.read(cbuf,off,len) ;
}
public void close()throws IOException
{
r.close();
}
public void myClose()throws IOException
{
r.close();
}
}
class MyBufferedReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("buf.txt");
MyBufferedReader myBuf = new MyBufferedReader(fr);
String line = null;
while((line=myBuf.myReadLine())!=null)
{
System.out.println(line);
}
myBuf.myClose();
}
}
5.对于读取或者写入流对象的构造函数,以及读写方法,还有刷新关闭功能都会抛出IOException或其子类。所以都要进行处理。或者throws抛出,或者try catch处理.
- 字节输入输出流
FileInputStream fis = new FileInputStream("a.txt");
fis.available();//获取关联的文件的字节数,在文件体积不是很大的情况下使用。
byte[] buf = new byte[fis.available()];//创建一个刚刚好的缓冲区。
//文件过大,大小超出jvm的内容空间时,会内存溢出。
fis.read(buf);
类FileInputStream 和类FileterInputStream 共同继承抽象类InputStream
将有字母的大写转化成小写:
public class ReadFileInputStream extends FilterInputStream {
protected ReadFileInputStream(InputStream arg0) {
super(arg0);
}
@Override
public int read() throws IOException {
return super.read();
}
@Override
public int read(byte[] arg0, int arg1, int arg2) throws IOException {
return super.read(arg0, arg1, arg2);
}
@Override
public int read(byte[] arg0) throws IOException {
return super.read(arg0);
}
}
FileOutputStream fos = new FileOutputStream("fos.txt");
fos.write("abcde".getBytes());//getBytes()转换成为字节数组
fos.close();
InputStreamReader(InputStream,String charSet):通过该构造函数初始化,可以指定编码表。
OutputStreamWriter(OutputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK。
OutputStreamWriter(OutputStream,String charSet):通过该构造函数初始化,可以指定编码表。
//获取键盘录入对象。
//InputStream in = System.in;
//将字节流对象转成字符流对象,使用转换流。InputStreamReader
//InputStreamReader isr = new InputStreamReader(in);
//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
//BufferedReader bufr = new BufferedReader(isr);
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
IO 总结规律
void setLineNumber(int)
和int getLineNumber()
,它们可分别用于设置和获取当前行号。
Properties
可保存在流中或从流中加载。 Properties是hashtable的子类。也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。是集合中和IO技术相结合的集合容器。
void list(PrintStream out) 将属性列表输出到指定的输出流
Properties prop=System.getProperties();
prop.list(System.out); 将java信息有序地打印在控制台上
常用方法:
1,存入键值对:setProperty(key,value);
2,获取指定键对应的值:value getProperty(key);
3,获取集合中所有键元素:
4,列出该集合中的所有键值对,可以通过参数打印流指定列出到的目的地。
list(PrintStream);
list(PrintWriter);
例:list(System.out):将集合中的键值对打印到控制台。
list(new PrintStream("prop.txt")):将集合中的键值对存储到prop.txt文件中。
5,可以将流中的规则数据加载进行集合,并称为键值对。
load(InputStream):
jdk1.6版本。提供了新的方法。
load(Reader):
注意:流中的数据要是"键=值" 的规则数据。
6,可以将集合中的数据进行指定目的的存储。
store(OutputStram,String comment)方法。
jdk1.6版本。提供了新的方法。
store(Writer ,String comment):
使用该方法存储时,会带着当时存储的时间。
3.PrintStream
为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。它还提供其他两项功能。与其他输出流不同,PrintStream
不会抛出IOException
;而是,异常情况仅设置可通过checkError
方法测试的内部标志。另外,为了自动刷新,可以创建一个PrintStream
;这意味着可在写入字节数组之后自动调用flush
方法,可调用其中一个 println
方法,或写入一个新行字符或字节 ('\n'
)。
4.DataInputStream(InputStream) 和DataOutputStream(OutputStream)
操作基本数据类型的方法:
int readInt():一次读取四个字节,并将其转成int值。
boolean readBoolean():一次读取一个字节。
short readShort();
long readLong();
DataOutputStream:
writeInt(int):一次写入四个字节。
注意和write(int)不同。write(int)只将该整数的最低一个8位写入。剩余三个8位丢弃。
writeBoolean(boolean);
writeShort(short);
writeLong(long);
File类概述:用来将文件或文件夹封装对象,方便对文件与文件夹的属性信息操作,而这是流对象不能做的。
File类常见方法:
1.构造函数:
File(String filename):将一个字符串路径(相对或者绝对)封装成File对象,该路径是可存在的,也可以是不存在。
File(String parent,String child);根据 parent 路径名字符串和 child 路径名字符串创建一个新 File
实例。
File(File parent,String child); 根据 parent 抽象路径名和 child 路径名字符串创建一个新 File
实例。
2,特别的字段:separator:跨平台的目录分隔符。
如:File file = new File("c:"+File.separator+"abc"+File.separator+"a.txt");
1,创建。
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。
2,删除。
boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();在程序退出时删除指定文件。
3,判断。
boolean exists() :文件是否存在.
isFile(): 判断File对象中封装的是否是文件。
isDirectory(); 判断File对象中封装的是否是文件夹。
isHidden(); 判断文件或者文件夹是否隐藏。在获取硬盘文件或者文件夹时,
对于系统目录中的文件,java是无法访问的,所以在遍历,可以避免遍历隐藏文件。
isAbsolute(); 判断文件是否绝对路径
4,获取信息。
getName(): 获取文件或者文件夹的名称。
getPath(): File对象中封装的路径是什么,获取的就是什么
getParent(): 获取File对象封装文件或者文件夹的父目录。如果封装的是相对路径,那么返回的是null.
getAbsolutePath() 获取File对象的绝对路径
long lastModified() 获取文件或者文件最后一次修改的时间。
long length() 获取文件大小。
String[] list():获取指定目录下当前的文件以及文件夹名称。
String[] list(Filenamefilter): 可以根据指定的过滤器,过滤后的文件及文件夹名称。
File[] listFiles():获取指定目录下的文件以及文件夹对象。