IO流的细谈
在Android请求网络数据的时候,如果使用HttpURLConnection来访问网络请求,其中的一步就是打开输入流,关于IO流我也看过不少的博客,但是看几遍很容易理解,并使用,时间一长我就会忘记,所以下面我就总结了几篇我常看的博客上的IO流知识
https://blog.csdn.net/m366917/article/details/52433489
https://blog.csdn.net/m366917/article/details/52435993
这两篇博客讲的很详细,我自己看完后总结了一篇,帮助自己记忆。
首先IO流在Android中可以获取服务器中的网络数据,然后写入本地,之前对于InputStream和OutputSream老是混淆,接下来就说说我的理解:
InputSream:
字节输入流,注意,这个输入相当于将文件(服务器或者本地文件)的数据,写到你要编代码的程序中,就是如果你想获得文件中的数据,就使用输入流。
OutputStream
字节输出流,这个输出相当于将你在程序代码写的信息,输出到服务器或者本地文件。
================================================================================================
注意,这两个类都是抽象基类,平常使用最多的还是其子类
最简单的使用如下
创建输出流,
输出流——-将程序里写的helloword输出到fos.txt文件中
FileOutputStream out = new FileOutputStream("fos.txt");
out.write("helloworld".getBytes());
out.close();
输入流(读取流)———将fos.txt文件中的内容读取出来
FileInputStream in = new FileInputStream("fos.txt");
int length = 0;
while((length = in.read())!=-1){
System.out.print((char)length); //一次写一个字节
}
in.close();
这里就要说代码中使用的方法了
FileInputStream的构造方法
- FileInputStream(File file)
- FileInputStream(String name)
FileOutputStream的构造方法
- FileOutputStream(File file)
- FileOutputStream(String name)
FileInputStream的成员方法
- public int read():一次读取一个字节
- public int read(byte[] b):一次读取一个字节数组
FileOutputStream的成员方法
- public void write(int b) :写一个字节
- public void write(byte[] b):写一个字节数组
- public void write(byte[] b,int off,int len):写一个字节数组的一部分
================================================================================================
复制文件的思路
- 读取要复制的文件内容,使用到了输入流InputStream
- 打开一个输出流,并指定要输出的文件名(或者具体的文件路径)
- 复制数据,将数据复制到一个字节数组并用输出流写到文件中
看下代码就清晰了:
FileInputStream in = new FileInputStream("fos.txt");
FileOutputStream out = new FileOutputStream("copyfos.txt");
byte[] bys = new byte[1024];
int length = 0;
while((length = in.read(bys))!=-1){
out.write(bys, 0, length);//写入字节 b[0],然后写入字节 b[0+1],
//依此类推;最后一个写入字节是 b[0+len-1]
}
in.close();
out.close();
字节缓冲流
一次写一个数组相比一次写一个字节快了很多,下面说一下缓冲区,这个更高效。
BufferOutputStream 字节缓冲输出流
BufferInputStream 字节缓冲输入流
下面将一个字符串到test文件中,看代码
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("test.txt"));
bos.write("hello".getBytes()); //这里写入的就是一个字符串,但是相当于转换成字节数组
bos.close();
然后读数据,看代码
BufferedInputStream in = new BufferedInputStream(new FileInputStream("test.txt"));
in.mark(in.available()+1); //这里注意,主要是读字节数据中还用到了这个输入流,所以要标记这个流,下面会解释。
//读取数据(一次读取一个字节)
int length = 0;
while((length = in.read())!=-1){
System.out.print((char)length); //不强转成char的话输出的是ASCII码
}
in.reset();
//一次读取一个字节数组,并输出到test2文件中
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("test2.txt"));
int len = 0;
byte[] bys = new byte[1024];
while((len = in.read(bys))!=-1){
out.write(bys, 0, len);
}
in.close();
out.close();
关于in.mark()和in.reset(),这两个方法我从网上摘了一段
在文件流读取完之后会定位到末端,则无法再用该输入流读取数据。若用read()方法则返回-1,若你调用available()方法返回0,若要重新读取,则要用到mark和reset方法。若要重新从0开头开始读取,则要在读取输入流之前用mark方法,参数readlimit由自己定义。若在读取了第n个字节后调用mark方法,在输入流读取完之后,调用reset则从新重第n个字节开始读取
mark就像书签一样,用于标记,以后再调用reset时就可以再回到这个mark过的地方。mark方法有个参数,通过这个整型参数,你告诉系统,希望在读出这么多个字符之前,这个mark保持有效。比如说mark(10),那么在read()10个以内的字符时,reset()操作后可以重新读取已经读出的数据,如果已经读取的数据超过10个,那reset()操作后,就不能正确读取以前的数据了,因为此时mark标记已经失效。
接下来就说说字符输入输出流
Reader
- InputStreamReader字符输入流
- public InputStreamReader(InputStream in):用默认的编码读取数据
- public InputStreamReader(InputStream in,String charsetName):用指定的编码读取数据
Writer
- OutputStreamWriter字符输出流
- public OutputStreamWriter(OutputStream out):根据默认编码把字节流的数据转换为字符流
- public OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流
下面就看代码怎么使用
将字符串写入文件中
OutputStreamWriter ows = new OutputStreamWriter(new FileOutputStream("osw.txt"),"GBK");
ows.write("胖儿");
ows.close();
读文件数据
InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"),"GBK");
int ch = 0;
while((ch = isr.read())!=-1){
System.out.print((char)ch);
}
接下来写出这几个read和writer方法
OutputStreamWriter的方法:
- public void write(int c):写一个字符
- public void write(char[] cbuf):写一个字符数组
- public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
- public void write(String str):写一个字符串
- public void write(String str,int off,int len):写一个字符串的一部分
下面挨个使用一遍
OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream("osw.txt"));
//1、public void write(int c):写一个字符
os.write('a');
os.write(99);
os.write("\r\n");
// public void write(char[] cbuf):写一个字符数组
char[] ch = {'o','n','e','f','a','t'};
os.write(ch);
os.write("\r\n");
//public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
os.write(ch, 1, 3);
os.write("\r\n");
//public void write(String str):写一个字符串
os.write("一个胖儿");
os.write("\r\n");
//public void write(String str,int off,int len):写一个字符串的一部分
os.write("一个胖儿",0,2);
os.write("\r\n");
os.close();
结果:
ac
onefat
nef
一个胖儿
一个
InputStreamReader的方法
- public int read():一次读取一个字符
- public int read(char[] cbuf):一次读取一个字符数组
字符流读数据和字节流的数据一样,看下代码
InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"));
//一次读取一个字节数组
int len = 0;
char[] ch = new char[1024];
while(((len = isr.read(ch))!=-1)){
System.out.println(new String(ch,0,len));
}
字符转换流的简化写法
FileReader
FileWriter
这里就练习一下复制文件的操作
//数据源
FileReader fr = new FileReader("test.txt");
//目的地
FileWriter fw = new FileWriter("osw.txt");
//这里写到osw文件里的数据会覆盖掉原先osw里的数据
int len = 0;
char[] chars = new char[1024];
while((len = fr.read(chars))!=-1){
fw.write(chars, 0, len);
}
fr.close();
fw.close();
字符缓冲流
BufferedWriter字符缓冲输出流
BufferedReader字符缓冲输入流
字符缓冲流的用法和字节的一样,这里说一下它的特殊用法
BufferedWriter:
- public void newLine():根据系统来决定换行符
BufferedReader:
- public String readLine():一次读取一行数据
BufferedReader br = new BufferedReader(new FileReader("osw.txt"));
//一次读取一行
String line = null;
while((line = br.readLine())!=null){
System.out.println(line);
}
br.close();
好了,以上就是我看博客的加上自己的练习,总结的一套。