hhh
流
1.1 流的概念
流:在 Java中所有数据都是使用流读写的。流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
1.按照流向分:输入流;输出流
2.按照处理数据的单位分:字节流(8位的字节);字符流(16位的字节)
1.2 输入输出流
1.3字节流和字符流
字节流:数据流中最小的数据单元是字节 。InputStream、OutputStream
字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。Reader、Writer
1.4 字节流
FileInputStream和FileOutStream
1 public class FileInputStream extends InputStream{ }
- FileInputStream 从文件系统中的某个文件中获得输入字节。
- FileInputStream 用于读取诸如图像数据之类的原始字节流。
方法 | 解释 |
---|---|
FileInputStream(File file) | 通过打开与实际文件的连接创建一个FileInputStream,该文件由文件系统中的File对象file命名 |
FileInputStream(String name) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name 命名 |
2 public class FileOutputStream extends OutputStream{ }
- 文件输出流是用于将数据写入到输出流 File 或一个 FileDescriptor 。文件是否可用或可能被创建取决于底层平台。
- 特别是某些平台允许一次只能打开一个文件来写入一个 FileOutputStream (或其他文件写入对象)。 在这种情况下,如果所涉及的文件已经打开,则此类中的构造函数将失败。
方法 | 解释 |
---|---|
FileOutputStream(File file) | 创建文件输出流以写入由指定的 File 对象表示的文件 |
FileOutputStream(String name ) | 创建文件输出流以指定的名称写入文件 |
字节缓冲流BufferedInputStream和BufferedOutputStream
1public class BufferedInputStream extends FilterInputStream{ }
- ufferedInputStream 为另一个输入流添加了功能,即缓冲输入和支持 mark 和 reset 方法的功能。 当创建 BufferedInputStream 时,将创建一个内部缓冲区数组。
- 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次有多个字节。 mark 操作会记住输入流中的一点,并且 reset 操作会导致从最近的 mark 操作之后读取的所有字节在从包含的输入流中取出新的字节之前重新读取。
方法 | 解释 |
---|---|
BufferedInputStream(InputStream in) | 创建一个 BufferedInputStream 并保存其参数,输 |
入流 in ,供以后使用 | |
BufferedInputStream(InputStream in,int size) | 创建一个 BufferedInputStream 指定缓冲区大小,输入流 in ,供以后使用 |
1public class BufferedOutputStream extends FilterOutputStream{ }
- 该类实现缓冲输出流。 通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用。
方法 | 解释 |
---|---|
BufferedOutputStream(OutputStream out) | 创建一个新的缓冲输出流,以将数据写入指定 |
的底层输出流 | |
BufferedOutputStream(OutputStream out, int size ) | 创建一个新的缓冲输出流,以便以指定的缓冲 |
区大小将数据写入指定的底层输出流 |
为什么需要有缓冲流?
答:当我们用read()读取文件时,每读一个字节,访问一次硬盘,效率很低 。文件过大时,操作起来也不是很方便。因此我们需要用到buffer缓存流,当创建buffer对象时,会创建一个缓冲区数组。当我们读一个文件时,先从硬盘中读到缓冲区,然后直接从缓冲区输出即可,效率会更高。
1.5 字符流
FileReader 和 FileWriter
1 public class FileReader extends InputStreamReader{ }
- 如果要从文件中读取内容,可以直接使用 FileReader 子类。
- FileReader 是用于读取字符流。 要读取原始字节流,请考虑使用 FileInputStream.
方法 | 解释 |
---|---|
FileReader(File file) | 创建一个新的 FileReader ,给出 File 读取 |
FileReader(String fileName) | 创建一个新的 FileReader ,给定要读取的文件名称 |
2public class FileWriter extends OutputStreamWriter{ }
- 如果是向文件中写入内容,应该使用 FileWriter 子类
- FileWriter 是用于写入字符流。 要编写原始字节流,请考虑使用 FileOutputStrea
字符缓冲流 BufferedReader 和 BufferedWriter
1 public class BufferedReader extends Reader{ }
- 从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。
方法 | 解释 |
---|---|
BufferedReader(Reader in) | 创建使用默认大小的输入缓冲区的缓冲字符输入 |
流 | |
BufferedReader(Reader in, int size) | 创建使用指定大小的输入缓冲区的缓冲字符输入 |
流 |
2 public class BufferedWriter extends Writer{ }
- 将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。
为什么需要字符缓冲流
为了提高字符流读写的效率,引入了缓冲机制,进行字符批量的读写,提高了单个字符读写的效率。BufferedReader 用于加快读取字符的速度, BufferedWriter 用于加快写入的速度
1.6字节流VS字符流
- 字节流操作的基本单元是字节;字符流操作的基本单元为Unicode码元。
- 字节流在操作的时候本身不会用到缓冲区的,是与文件本身直接操作的;而字符流在操作的时候使
用到缓冲区的。 - 所有文件的存储都是字节(byte)的存储,在磁盘上保留的是字节。
- 在使用字节流操作中,即使没有关闭资源(close方法),也能输出;而字符流不使用close方法的话,不会输出任何内容。
1.7 字符字节转换流
1 InputStreamReader是Reader的子类,将输入的字节流转换成字符流
2 OutputStreamWriter是Writer的子类,将输出的字符流转换成字节流
程序
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("测试目录\\测试文件.txt");
//file.createNewFile();
OutputStream os = new FileOutputStream(file);//字节流
//源是文件内容
os.write("我是中国人".getBytes("UTF-8"));
InputStream is = new FileInputStream(file);
byte[] buf = new byte[1024];
int len = is.read(buf);
System.out.println(len);
String s = new String(buf, 0, len, "UTF-8");
System.out.println(s);
/*
System.out.println(is.available());// 估算值,平时不要用
int b;
// 正确的方式 r
while ((b = is.read()) != -1) {
System.out.println(b);
}
*/
//源是内存中的一段byte[]
/*
String ss = "我是中国人";
byte[] bytes = ss.getBytes();
InputStream in = new ByteArrayInputStream(bytes);
int b;
while((b =in.read())!=-1){
System.out.println(b);
}
*/
}
}
- FileInputStream 读文件
- FileOutputStream 写文件
- read()!=-1,就可以继续读
- 字符集String(buf,off,len,“UTF-8”);
- 不同的源
FileInputStream 源是文件的内容
ByteArrayInputStream 源是内存中的一段byte[]
读文件的两种的方式
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
//假设要读取的文件是GB18030的编码
public class TextDemo {
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\阮梦\\Desktop\\bite\\javaweb_多线程_IO\\2019-11-29-文件IO\\测试目录\\测试文件.txt");
//读文件方式一:
/*
InputStream is = new FileInputStream(file);
InputStreamReader isReader = new InputStreamReader(is, "GB18030");
char[] buf = new char[10];
int len = isReader.read(buf);
System.out.println(Arrays.toString(buf));
*/
/*
BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(file), "GB18030")
);
//InputStream-->Reader-->BufferedReader
//InputStreamReader 将输入的字节流转换成字符流
//BufferedReader字符缓冲流
reader.readLine();//一行一行去读
*/
//读文件方式二:
InputStream is = new FileInputStream(file);
Scanner scanner = new Scanner(is);
while(scanner.hasNext()){
System.out.println(scanner.next());
}
}
}
进程被启动时,默认三个流
1.标准输入
2.标准输出
3.标准错误
文件拷贝
import java.io.*;
public class Copy {
public static void main(String[] args) throws IOException {
String src = "C:\\Users\\阮梦\\Desktop\\bite\\javaweb_多线程_IO\\2019-11-29-文件IO\\测试目录\\测试文件.txt";
String dest = "C:\\Users\\阮梦\\Desktop\\bite\\javaweb_多线程_IO\\2019-11-29-文件IO\\测试目录\\目标文件.txt";
InputStream is = new FileInputStream(src);//读
OutputStream os = new FileOutputStream(dest);//写
int b;
while ((b = is.read()) != -1) {
os.write(b);
}
}
}
写入文件
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class FromTermailToFile {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
File file = new File("输出.txt");
FileWriter fileWriter = new FileWriter(file);//FileWriter字符流
while (scanner.hasNext()) {
String s = scanner.next();
for (int i = 0; i < s.length(); i++) {
fileWriter.append(s.charAt(i));
fileWriter.flush();//刷新
// 如果不刷新 必需等程序关闭后才会写入 输出.txt文件 中
}
}
fileWriter.close(); //Ctrl+d 关闭
}
}