流
什么是流?
在Java中,所有数据都是使用流写的.流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象. 数据在两设备之间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作.
输入输出流
输入就是将数据从各种设备中读取到内存
输出则是相反,是将数据写入到各种输出设备
字节流:数据流中最小的数据单元是字节 。InputStream、OutputStream
字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节
。Reader、Writer
从字节流中读取字符
public class InputDemo {
public static void main(String[] args) throws IOException {
InputStream is = 获取一个输入字节流();
String message = 从一个输入字节流中得到最终的字符(is);
System.out.println(message);
}
private static String 从一个输入字节流中得到最终的字符(InputStream is)
throws IOException {
//手动从字节流中读,假设流的长度小于8192
byte[] buffer = new byte[8192];
int len = 8192;
for (int i = 0; i < buffer.length; i++) {
int b = is.read();
if (b == -1){
//b = -1 说明读完了
len = i;
break;
}
buffer[i] = (byte) b;
}
String s = new String(buffer,0,len,"UTF-8");
return s;
}
private static InputStream 获取一个输入字节流() throws IOException {
InputStream is;
is = new FileInputStream("本地文件.txt");
return is;
}
}
我是一个本地文件内容
我是UTF-8编码
用一个reader 读一个字符流/reader读到缓冲区返回长度!
//用一个字节流得到字符流(字节流是该字符流的源码)
private static String 从一个输入字节流中得到最终的字符(InputStream is)
throws IOException{
Reader reader = new InputStreamReader(is,"UTF-8");
char[] buffer = new char[1024];
int len = reader.read(buffer);//读到缓冲区!!!!!!!
return new String(buffer,0,len);
}
我是一个本地文件内容
我是UTF-8编码
带缓冲区的BufferedReader可以有效提升效率
private static String 从一个输入字节流中得到最终的字符(InputStream is) throws IOException{
Reader reader = new InputStreamReader(is,"UTF-8");
BufferedReader bufferedReader = new BufferedReader(reader);
return bufferedReader.readLine();//读一行数据
}
从字符流读,和从字符流读
private static String 从一个输入字节流中得到最终的字符(InputStream is) throws IOException{
Reader reader = new InputStreamReader(is,"UTF-8");
StringBuilder sb1 = new StringBuilder();
char[] buffer = new char[1024];
int len;
while ((len = reader.read(buffer))!= -1){
//调试后发现,只进入了一次循环,reader.read(buffer)直接返回了21,然后sb1就append了
//然后发现到结尾了(即流结尾返回-1)不进入循环;
sb1.append(buffer,0,len);
}
System.out.println(sb1.toString());
StringBuilder sb2 = new StringBuilder();
int c;
while ((c = reader.read())!= -1){
char cb = (char) c;
sb2.append(cb);
}
System.out.println(sb2.toString());
return "";
}
这里需要注意,new一个String里面的buffer可用是char[]也可以是byte[],但是StringBuilder append只能append char[] 类型的数组
通过Scanner去读
private static String 从一个输入字节流中得到最终的字符(InputStream is) throws IOException{
Scanner scanner = new Scanner(is,"UTF-8");
return scanner.nextLine();
}
InputStream(abs class) 一次一个字节/一次一组字节
Reader(abs class) 一次一个字符/一次一组字符
BufferReader(继承自Reader) 一次一个字符/一次一组字符/一次一行
Reader和Writer是字符流
InputString和OutputString是字节流
内存中的源ByteArrayInputStream:这也是个字符流
class 内存中的源{
public static void main(String[] args) throws IOException{
byte[] source = "中国 人民 站起来 了".getBytes("UTF-8");//转成了字节
InputStream is = new ByteArrayInputStream(source);
Scanner s = new Scanner(is,"UTF-8");
while (s.hasNext()){
System.out.println(s.next());
}
s.close();
}
}
中国
人民
站起来
了
输出
输出表现在字节流上:OutputStream
表现在字符流上:Writer
public class OutPut {
public static void main(String[] args) throws IOException {
OutputStream os = new FileOutputStream("本地输出文件.txt");
os.write(0x41);// A
os.write(0x0d);// \r
os.write(0x0a);// \n
os.flush();
os.close();
}
}
这个文件夹里就有一个A了
转成字符流去写
public class OutPut {
public static void main(String[] args) throws IOException {
OutputStream os = new FileOutputStream("本地输出文件.txt");
Writer writer = new OutputStreamWriter(os,"UTF-8");
//转成字符流
writer.write('c');
writer.write("你好");
char[] buffer = {'我' ,'在','这'};
writer.write(buffer,0,buffer.length);
writer.flush();
writer.close();
}
}
public class OutPut {
public static void main(String[] args) throws IOException {
OutputStream os = new FileOutputStream("本地输出文件.txt");
Writer writer = new OutputStreamWriter(os,"UTF-8");
writer.write('c');
writer.write("你好");
char[] buffer = {'我' ,'在','这'};
writer.write(buffer,0,buffer.length);
writer.append("\r\n我爱 sing dance rap basketball");
writer.flush();
writer.close();
}
}
在这个文件中
c你好我在这
我爱 sing dance rap basketball
PrintWriter(只能处理字符) vs PrintStream(可以处理字节和字符)
PrintStream
class PrintStream1{
public static void main(String[] args) throws IOException {
//OutputStream os = new FileOutputStream("本地文件.txt");
//PrintStream out = new PrintStream(os,false,"UTF-8"); 不同的构建方式
PrintStream out = new PrintStream("本地输出文件.txt","UTF-8");
out.println("我是中国人");
out.println("我是第二行");
out.println("我爱 sing dance rap basketball");
out.flush();
out.close();
}
}
PrintWriter
class PrintWriter2{
public static void main(String[] args) throws IOException {
PrintWriter out = new PrintWriter("本地输出文件.txt","UTF-8");
out.printf("你好%n");
out.println("我是谁");
out.flush();
out.close();
}
}
关于Buffer和Flush
缓冲区(buffer):解决输入输出速度不匹配问题(为什么需要缓冲区):
用read()读取文件时,每读一个字节,访问一次硬盘,效率很低.文件过大时候,操作起来也不是很方便.因此需要用到buffer缓存流,当创建buffer对象,会先创建一个缓冲区数组.先从评判者读到缓冲区,然后直接从缓冲区输出即可.
刷新(flush):全部泄出来
字节流对比字符流
- 字节流操作的基本单元是字节;字符流操作的基本单元为Unicode码元
- 字节流在操作的时候本身不会用到缓冲区,是与文件本身直接操作的;而字符流在操作的时候使用到缓冲区
- 所有文件的存储都是字节(byte)的存储,在磁盘上保留的是字节.
- 在使用字节流操作符时候,即使没有关闭资源(close方法)也能输出,但是字符流不使用close方法的话,不会输出任何内容.
- 有时候我们需要进行字节流与字符流二者之间的转换,因为这是两种不同的流,所以,在进行转换的时候我们需要用到 OutputStreamWriter 和 InputStreamReader.
- InputStreamReader 是从字节流到字符流的桥:它读取字节,并使用指定的 charset 将其解码为字符 。
- OutputStreamWriter 是字符的桥梁流以字节流:向其写入的字符编码成使用指定的字节
charset 。
小结
I/O流的操作
- 按照流向分:输入流;输出流
- 按照处理数据的单位分:字节流(8位的字节)字符流(16位的字节)
- 按照流动的功能分:节点流(低级流)和处理流(高级流)
1846

被折叠的 条评论
为什么被折叠?



