------- android培训、java培训、期待与您交流! ----------
Io流
字符流:
InputStream OutputStream
字节流:
Reader Writer
操作数据的最常见体现形式是:文件
实例:操作系统上的文件。
OutputStreamWriter下的FileWriter就是用来对文件进行写入的。
所有的前缀名都是该流的功能。也就是操作什么类型的文件。
publicFileWriter(String fileName)
throws IOException根据给定的文件名构造一个 FileWriter 对象。
FileWriter fw =new FileWriter("1.txt");
创建一个FileWriter对象,该对象一被初始化就必须要声明被操作的文件。
而且该文件会被创建到指定的目录下。产生一个新的文件,也就是在创建文件。
如果该文件已经存在同名文件,则该同名文件会被新创建的所覆盖。(不管有没有就是要创建并覆盖)。
fw.write("123123");
写入数据到底层缓冲区中。而不是真正写到文件中。
fw.flush();
刷新该流的缓冲,并将流中的数据写入到目标中。
fw.close();//和flush()的区别在于,flush刷新后,流可以继续使用,close刷新后,关闭流。也就是关闭了资源。在关闭的同时也要刷新此流。
当java在用流写入数据的时候,要调用底层的操作系统资源。用这些资源去写数据。
由于每次创建FileWriter的时候,都会创建一个新的文件去覆盖旧的文件,
当我们在写数据的时候,想要对文件进行续写应该怎么处理。
publicFileWriter(File file, boolean append) throws IOException
根据给定的 File 对象构造一个 FileWriter 对象。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。
FileWriter fw =new FileWriter("1.txt",true);
当我们去这样创建的时候,如果这个文件不存在,则创建一个新文件,如果这个文件已经存在了,就不去创建这个文件了。并在文件的末尾处进续写。
文件的读取。
Reader
FileReader
publicFileReader(String fileName)
throws FileNotFoundException在给定从中读取数据的文件名的情况下创建一个新 FileReader。
FileReader fr =new FileReader("1.txt");
int ch = fr.read();
System.out.println((char)ch);
fr.close();
对于read方法来说,一次读一个字符,而且会自动往下读。而不是每次从头读。
public intread()
throws IOException读取单个字符。在字符可用、发生 I/O 错误或者已到达流的末尾前,此方法一直阻塞。
用于支持高效的单字符输入的子类应重写此方法。
返回:
作为整数读取的字符,范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1
在使用下边的方法的时候,
public int read(char[] cbuf)
在文件中读的数据,都放到了char数组中,每次读的个数就是数组的长度,直到读取完,当读取完时候,读的个数就是所读取完的个数。并返回这个每次读取的个数。读取完成后,再去读取,就返回一个-1。
字符流的缓冲区:
缓冲区的出现是为了提高对数据的读写效率。所以在创建
缓冲区之前,必须要先有流对象。
BufferedWriter与 BufferedReader
FileWriter fw = new FileWriter("buf.txt");
//为了提高字符写入流的效率,加入了缓冲技术。
BufferedWriter bw = new BufferedWriter(fw);
bw.write("abcde");
bw.flush();
bw.close();
当我们在关闭一个流对象的时候,其实关闭它的装饰流对象,其实就是在关闭当前这个流对象。
在使用换行的时候,使用BufferedWriter中的newLine()比用‘\r\n’更加的准确。
它根据操作系统的类型去写对应的换行符。
BufferedReader:
BufferedReader(Readerin)
创建一个使用默认大小输入缓冲区的缓冲字符输入流。
实例:
//创建一个读取流对象和文件相关联。
//创建一个读取流对象和文件相关联。
FileReader fr = new FileReader("buf.txt");
//为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的
//的构造函数。
BufferedReader bufr = new BufferedReader(fr);
bufr.readLine();
bufr.close();
在这个流中提供了一个能一行一行读取数据的方式。当读取完毕的时候,readLine返回 null;
使用这样的方式:
String string = null;
while((string = bufr.readLine())!=null)
{
System.out.println(string);
}
bufr.close();
对文本数据的获取。
在readLine中中读取的时候,并不包含任何的终止符。
当我们再输出的时候,一定要切记在字符串后边打印换行符。
ReadLine的方法的原理。十分重要。
其实它最终还是用read()方法去读取。
字节流:
InputStream OutputStream
在字节流的基本操作中,写入的是一个字节或者一个字节数组。
在字符输出流中,可以直接写入,不必调用flush就可以写到文件中,不经过缓冲区
当我们在使用InputStream中利用数组进行读取的时候,使用 available()方法,可以得到这个文件中没有读取的字节总数。从而定义一个大小刚刚好数组,避免了重复循环读取。但是利用这个方法,可能导致数组空间太大,导致内存溢出,不建议使用。
字节流的缓冲区:BufferedInputStream BufferedOutputStream
基本原理:
先将字节写入到缓冲区中,当调用read()的时候,从这个缓冲区中读取。
自定义的一个缓冲字节流。
public class MyBufferedInputStream extends FilterInputStream
{
private InputStream is;
private byte[] bytes;
private int total,pos;
public MyBufferedInputStream(InputStream is)
{
super(is);
bytes = new byte[1024];
}
@Override
public int read() throws IOException
{
if(total==0)
{
total = is.read(bytes);
if(total<0)
return -1;
pos = 0;
}
byte b = bytes[pos];
total--;
pos++;
return b;
}
}
对于缓冲区的原理,就是在调用read等读数据时候,先看缓冲区是否有数据,如果没有,则调用父类的read(byte[] bytes)方法。装满缓冲区,然后从这个缓冲区中读取数据,如果缓冲区中有数据,则将缓冲区的数据拿出来即可。
当我们通过流去读取键盘数据的时候,只能一个字节一个字节的读取,我们想用形如字符流中readLine方法去一次读写一行数据,应该怎么做?
解决方式,将字节流转成字符流,再去使用字符流缓冲区的readLine方法。InputStreamReader转换流其实是先将传入的字节流转换成一个sd = StreamDecoder.forInputStreamReader(in, this, dec);每次在读取一个字符的时候,将字节流对应的文件中的二进制根据转换流特定的编码表转成一个字符,然后返回。
也就是InputStreamReader是字节流通向字符流的桥梁,它使用指定的charset读取字节并将其解码为字符。
|
需求:现在想把键盘录入的数据存储在一个文件中。
源:键盘。
目的:文件
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new FileWriter("3.txt"));
想一个文件的数据打印在控制台上
源:文件
目的:控制台。
BufferedReader br = new BufferedReader(new FileReader("3.txt"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
流操作的基本规律:
通过三个明确来完成:
1. 明确源和目的。
源:输入流。InpustreamReader
目的:输入流。OutputStream Writer
2. 操作的数据是否是纯文本。
是:字符流。不是,字节流。
3. 当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分。
源设备:内存,硬盘,键盘。
目的设备:内存,硬盘,控制台
特别的分析一个,将键盘录入的数据保存到一个文件中
1, 源:InputStream Reader
2, 是不是纯文本?是!Reader
3, 设备:键盘,对应的对象是system.in
不是选择Reader,而是一个字节流。为了操作键盘的文本数据方便,要使用转换流。按照字符串操作最方便。看是否想提高效率?BufferedReader
4, 目的:OutputStream Writer
5, 是不是纯文本?是!Writer
6, 设备:硬盘。一个文件,使用FileWriter
7, 是否想提高效率,使用BufferedWriter
扩展一下,想要把录入的数据按照指定的编码表,将数据存到文件中。
要使用转换流才能完成这种功能,故使用OutputStreamWriter
通常,在涉及到字符编码转换的时候需要用到转换流。
Properties是一个集合类。是hashtable的子类。
也就是说它具备map集合的特点,而且它里边存储的键值对都是字符串。
是集合中和IO技术相集合的集合容器,可以用于键值对形式的配置文件。
应用:
//设置和获取元素
Properties properties = new Properties();
properties.setProperty("zhangsan","30");
properties.setProperty("lisi","22");
Set<String> set = properties.stringPropertyNames();
for(String s:set)
{
System.out.println(s+"..."+properties.getProperty(s));
}
与IO相结合的方式。
需求:如何将流中的数据存储到集合中,也就是将info.txt键值数据存到集合中进行操作。
Propertiesproperties = new Properties();
FileInputStream fis = newFileInputStream("1.txt");
//1,用流和一个文件相关联。
properties.load(fis);
//从输入流中读取属性列表(键和元素对)。
properties.list(System.out);
//也就是将这个属性以列表的形式输入到设备上。
要求:使用properties进行数据加载的时候,需要对文件数据有固定的格式:键=值。
打印流:PrintWriter与PrintStream
最强大提供了打印方法,可以将各种数据类型的数据都原样打印。
字节打印流:
PrintStream
构造函数可以接收的参数类型。File对象,String,字节输出流。
字符打印流:
PrintWriter(非常的常用,用于web开发中的网络传输)
使用这个对象一条条的打印到客户端去。
构造函数可以接收的参数类型:File对象,String,OutputStream ,Writer