一、流的概述
流是用来读写数据的,java有一个类叫File,它封装的是文件的文件名,只是内存里面的一个对象,真正的文件是在硬盘上的一块空间,在这个文件里面存放着各种各样的数据,我们想读文件里面的数据怎么办呢?
你可以把文件想象成一个小桶,文件就是一个桶,文件里面的数据就相当于是这个桶里面的水,那么我们怎么从这个桶里面取水呢,也就是怎么从这个文件读取数据呢。
常见的取水的办法是我们用一根管道插到桶上面,然后在管道的另一边打开水龙头,桶里面的水就开始哗啦哗啦地从水龙头里流出来了,桶里面的水是通过这根管道流出来的,因此这根管道就叫流,JAVA里面的流式输入/输出跟水流的原理一模一样,当你要从文件读取数据的时候,一根管道插到文件里面去,然后文件里面的数据就顺着管道流出来,这时你在管道的另一头就可以读取到从文件流出来的各种各样的数据了。当你要往文件写入数据时,也是通过一根管道,让要写入的数据通过这根管道哗啦哗啦地流进文件里面去。除了从文件去取数据以外,还可以通过网络,比如用一根管道把我和你的机子连接起来,我说一句话,通过这个管道流进你的机子里面,你马上就可以看得到,而你说一句话,通过这根管道流到我的机子里面,我也马上就可以看到。
从程序的角度来讲,从计算机读取到的原始数据肯定都是010101这种形式的,一个字节一个字节地往外读,当你这样读的时候你觉得这样的方法不合适,没关系,你再在这根管道的外面再包一层比较强大的管道,这个管道可以把010101帮你转换成字符串。这样你使用程序读取数据时读到的就不再是010101这种形式的数据了,而是一些可以看得懂的字符串了。
二、流的分类
2.1、读取方式:
字节流:一个字节(8位)一个字节读取(InputStream和OutputStream);
字符流:按字符读取(Reader和Writer)
2.2、输入输出:
什么叫输入流?什么叫输出流?用一根管道一端插进文件里程序里面,然后开始
读数据,那么这是输入还是输出呢?如果站在文件的角度上,这叫输出,如果站在
程序的角度上,这叫输入。我们所说的输入输出都是站在程序的角度上
2.3、节点流和处理流:
节点流:单独具备流输入输出功能的流,比如FileInputStream,BtyeArrayInputStream,FileWriter等。
处理流:自身不具备流输入输出功能的流,必须包裹一个节点流才具备流输入输
出功能,比如BufferedReader,BufferedOutputStream,DataInputStream,InputStreamReader等。
三、流的基本方法
3.1、字节节点流
InputSteam
read()——读取一个字节并以整数的形式返回。若已到文件末尾返回-1。
read(btye[] b)——读取一系列字节并存储到缓存字节数组b,返回实际读取的字节数。若已到文件末尾返回-1。这样可以避免频繁从磁盘读取造成磁盘IO阻塞。
read(byte[] b,int offset,int length)——读取length个字节,并从offset位置开始缓存到字节数组b,返回实际读取的字节数。若已到文件末尾返回-1。
skip(long n)——跳过n个字节不读,返回实际跳过的字节数。
OutputStream
void write(int b)——向输出流中写一个字节数据,该字节数据为参数b的低8位。
void write(byte[] b)——将字节数组b写入输出流。
void write(byte[] b,int off,int len)——将字节数组从off开始的len个字节写入输出流。
void flush()——将输出流中缓冲的数据全部写出到目的地。
3.2、字符节点流
reader和writer的方法和上面的差不多,只不过其是按字符读取的,一个字符(char)等于两个字节。
3.3
- OutputStreamWriter-字符处理流
/**
如果用一个FileOutputStream流往文件里面写东西,
得要一个字节一个字节地写进去,但是如果我们在
FileOutputStream流上面套上一个字符转换流,将字
节流转换为字符流,那我们就可以一个字符一个字符
地写进去。
*/
Writer outputStreamWriter=new OutputStreamWriter(new FileOutputStream(new File("D:\\download\\test.txt")), "utf8");
outputStreamWriter.write("你好,java");
outputStreamWriter.close();
- DataOutputStream-数据流处理流
/**
数据流的作用使可以读写java原始数据
*/
public static void main(String[] args) throws IOException {
ByteArrayOutputStream baos=new ByteArrayOutputStream();
DataOutputStream dos=new DataOutputStream(baos);
ByteArrayInputStream bais=null;
DataInputStream dis=null;
try {
dos.writeDouble(8);
dos.writeBoolean(false);
bais=new ByteArrayInputStream(baos.toByteArray());
dis=new DataInputStream(bais);
System.out.println(bais.available());
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
} catch (Exception e) {
e.printStackTrace();
} finally {
bais.close();
dos.close();
bais.close();
dis.close();
}
}
3.4、缓冲流
BufferedInputStream/BufferedReader
3.5、打印流
打印流没有对应的输入流。对应的输出字节流与字符流是PrintStream和PrintWriter。
public static void main(String[] args) throws IOException {
PrintStream ps=null;
FileOutputStream fos=null;
try {
fos=new FileOutputStream("E:\\test.txt",true);
ps=new PrintStream(fos);
/** 设置系统输出位置,默认为控制台,这里改变system.out输出流位置为文件 */
System.setOut(ps);
/** print函数以系统默认编码(GBK)编码,打开的时候必须设置解码格式为GBK才不会出现乱码 */
System.out.print("defaultEncoding:"+Charset.defaultCharset()+"||");//GBK
String srcStr="content:测试编码转换";
/** utf8编码,gbk解码,出现乱码 */
String toGbk=new String(srcStr.getBytes("utf8"),"GBK");
System.out.print(toGbk);
/** gbk编码,以utf8解码,正常 */
System.out.print(new String(toGbk.getBytes("GBK"),"utf8")+"||");
/**gbk编码,utf8解码,出现乱码 */
String toUtf=new String(srcStr.getBytes(),"utf8");
System.out.print(toUtf);
/** utf8编码,gbk解码,无法还原 */
/**
* 原因:gbk属于定长编码,utf8属于变长编码(最高有效位数31位,用6个字节),而且通常其每个
* 字节的高位用来判断组成这个字符的utf8编码有无下一个字节,所以通常某些以gbk编码的字节在utf8
* 解码时发现根本无法解析为一个正确的字符,这时utf8将其偷偷替换为某种不可言喻的?字符,而?再用
* utf8编码时,已经无法到原本的编码了,因为那是utf8中不可能出现的编码序列,这时候utf8用一个
* 乱入编码代替。再用gbk解码就会出现乱码,通常是"锟斤拷"。
* 所以:以非UTF-8编码编码出的字节数组,一旦以UTF-8进行解码,通常这是一条不归路。相反地,
* 其他的固定长度编码几乎都可以顺利还原。
*/
System.out.print(new String(toUtf.getBytes("utf8"), "GBK"));
System.out.print("\r\n");
} catch (Exception e) {
e.printStackTrace();
}
}
3.6、序列化的流
ObjectOutputStream和ObjectInputStream。可读写序列化的对象。
3.7、字节数组流
ByteArrayOutputStream,ByteArrayOutputStream
这两个流的主要功能在于使用ByteArrayOutputStream的toByteArray方法,可以将文件内容转化为字节数组,从而便于文件编码等。主要实现如下:
private String getImgStr(String path) throws IOException {
InputStream is=new FileInputStream(path);
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
int size=1024;
byte[] temp=new byte[size];
int readLen=0;
while ((readLen=is.read(temp, 0, size))!=-1) {
byteArrayOutputStream.write(temp, 0, readLen);
}
byte[] byteStr=byteArrayOutputStream.toByteArray();
Base64Encoder base64Encoder=new Base64Encoder();
//base64编码
StringBuffer sb=new StringBuffer();
base64Encoder.encodeWordData(byteStr, sb);
return "data:image/png;base64,"+sb.toString();
}
网友评论