1、流的概念和作用
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
注意:流只能顺序访问,不能像数组那样随机存取
2、流的分类
根据处理数据类型的不同分为:字符流和字节流
根据数据流向不同分为:输入流和输出流
3、字符流和字节流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。
字节流和字符流的区别:
读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。
4、输入流和输出流
输入流可以理解为向内存输入,输出流可以理解为从内存输出
InputStream或者Reader是从数据源读取数据(到内存中),OutputStream或者Writer是将数据(从内存中)写入到目标媒介典型的数据源或目标媒介有:文件、管道、网络连接、内存缓存、控制台…
注意:Java IO流通常是基于字节或者基于字符的。字节流通常以“stream”命名,比如InputStream和OutputStream。除了DataInputStream 和DataOutputStream 还能够读写int, long, float和double类型的值以外,其他流在一个操作时间内只能读取或者写入一个原始字节
5、组合流
一次读取一个字节是很慢的,借助缓冲可以从磁盘中一次读取一大块数据,然后从读到的数据块中获取字节。为了实现缓冲,可以把InputStream包装到BufferedInputStream中。例如
InputStream input = new BufferedInputStream(new FileInputStream(“xxx”));
6、字符流与字节流之间的转换
例如 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String strLine = bufferedReader.readLine();借助InputStreamReader可以将字节流转换为字符流
7、常用的几个类说明
// 区分是字符流还是字节流
// 以InputStream或OutputStream结尾是字节流,以Reader或Writer结尾是字符流
// 区分是输入还是输出
// 以Input或Read开头是输入,以Output或Writer结尾时输出
// byte stream
//input stream
String testStr = "heh";
StringBufferInputStream strBufferInputStream = new StringBufferInputStream(testStr); //从String中读取数据到Stream中
strBufferInputStream.read(b); // 从Stream中逐个字节读取
File testFile = new File("filePath");
FileInputStream fileInputStream = new FileInputStream(testFile); //从文件中读取数据到Stream中
byte[] storeByte = new byte[10];
fileInputStream.read(storeByte); // 从Stream中逐个字节读取 // 文件结尾返回 -1
byte[] testByte = new byte[10];
ByteArrayInputStream byteArrInputStream = new ByteArrayInputStream(testByte); // 从ByteArray中读取数据到Stream中
byteArrInputStream.read(testByte); // 从Stream中逐个字节读取
// output stream
File testFile2 = new File("filePath"); // 写入到哪个文件中去
FileOutputStream fileOutputStream = new FileOutputStream(testFile2);
byte[] srcByte = new byte[10];
fileOutputStream.write(srcByte); // 将byteArray写入到指定文件中
ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream();
byte[] srcByte2 = new byte[10];
byteArrOutputStream.write(srcByte2); // 将byteArray写入到Stream中
// character stream
String encoding = "utf-8";
File testFile3 = new File("filePath");
FileInputStream fileInputStream = new FileInputStream(testFile3);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,encoding);
char[] characters = new char[1024];
inputStreamReader.read(characters); // 逐个字符读取,从字节流中读取并根据编码转换成字符,存入字符数组中
BufferedReader bufferReader = new BufferedReader(inputStreamReader);
bufferReader.readLine(); // 按行读取字符 // 文件结尾返回null
5、读取实例
/**
* BIO模式
* 从输入流中读取指定长度的数据到字节数组中
* 如何确定字节数组长度:file.length()返回字节数组长度
* 如何保证文件内容全部读入:字节数组长度与文件内容长度相等
* @param fileName
* @return
* @throws IOException
*/
public static byte[] readByBytes(String fileName) throws IOException{
File file = new File(fileName);
InputStream fileInputStream = new FileInputStream(file);
long length = file.length(); // return length in bytes
System.out.println("file length:" + length);
byte[] fileBytes = new byte[(int)length];
int result = fileInputStream.read(fileBytes);
fileInputStream.close(); // must close
if(result != length){
throw new IOException("can't read all," + result + "!=" + length);
}
System.out.println("read length: " + result);
return fileBytes;
}
/**
* BIO模式
* 逐个字节读取
* 如何确定字节数组长度:file.length()返回字节数
* 如何保证文件内容全部被读取:比较文件长度与读取字节数组长度是否相等
* @param fileName
* @return
* @throws IOException
*/
public static byte[] readByOneByte(String fileName) throws IOException{
File file = new File(fileName);
FileInputStream fileInputStream = new FileInputStream(file);
long length = file.length(); // return length in bytes
System.out.println("file length:" + length);
byte[] fileBytes = new byte[(int)length];
int resultByte = fileInputStream.read();
int i = 0; // array index
while(resultByte != -1){
byte tempByte = (byte)resultByte;
fileBytes[i] = tempByte;
i++;
resultByte = fileInputStream.read();
}
fileInputStream.close(); // must close
if(fileBytes.length != length){
throw new IOException("can't read all," + fileBytes.length + "!=" + length);
}
System.out.println("read length: " + fileBytes.length);
return fileBytes;
}
/**
* BIO模式
* FileReader逐个字符读取文件,FileReader extends InputStreamReader
* 读取文件中内容到字符数组中
* 如何确定字符数组长度:
* FileReader不能自定义编码读取
* 此方法也可以用于读取二进制文件,只不过读取出来有很多乱码
* @param fileName
* @return
* @throws IOException
*/
public static char[] readByOneCharWithDefaultEncoding(String fileName) throws IOException{
File file = new File(fileName);
FileReader fileReader = new FileReader(file); // 不能自定义编码,内部默认采用系统的编码
System.out.println("当前采用编码: " + fileReader.getEncoding());
char[] charcters = new char[1024];
int result = fileReader.read(); // 逐个字符读取,不能按行读取
int i = 0;
while(result != -1 && i < 1024){
char temp = (char)result;
charcters[i] = temp;
i++;
result = fileReader.read();
}
fileReader.close();
return charcters;
}
/**
* BIO模式
* 逐个字符读取文件
* 读取文件中内容到字符数组中
* 如何确定字符数组长度:
* 此方法也可以用于读取二进制文件,只不过读取出来有很多乱码
* @param fileName
* @return
* @throws IOException
*/
public static char[] readByOneCharWithCustomEncoding(String fileName,String encoding) throws IOException{
File file = new File(fileName);
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file),encoding);
System.out.println("当前采用编码: " + inputStreamReader.getEncoding());
char[] charcters = new char[1024];
int result = inputStreamReader.read(); // 逐个字符读取,不能按行读取
int i = 0;
while(result != -1 && i < 1024){
char temp = (char)result;
charcters[i] = temp;
i++;
result = inputStreamReader.read();
}
inputStreamReader.close();
return charcters;
}
/**
* BIO模式
* 使用InputStreamReader作为字节流与字符流之间的桥梁
* 使用BufferedReader提升读取效率
* @param fileName
* @throws IOException
*/
public static void readByLine(String fileName) throws IOException{
String encoding = "utf-8"; // 既然是读取字符,肯定会涉及到编码问题
File file = new File(fileName);
if(file.isFile() && file.exists()){
InputStream inputStream = new FileInputStream(file);
// inputStreamReader是连接字节流和字符流的桥梁
// 读取指定数量的字节,并按照传入的编码转换成字符
InputStreamReader inputStreamReader = new InputStreamReader(inputStream,encoding);
// 使用BufferedReader的好处是可以一次读取多个字符(而不是一个字符)
BufferedReader bufferReader = new BufferedReader(inputStreamReader);
String readLine = bufferReader.readLine();
while( readLine != null) {
System.out.println(readLine);
readLine = bufferReader.readLine();
}
bufferReader.close();
}
}