1、字节流——File
字节流的介绍
字符流:(一个字符2个字节16位)
FileReader FileWriter。
BufferedReader BufferedWriter
字节流:(一个字节8位)
InputStream(输入的都是读) OutputStream(输出的都是写)(这里以流为对象,流向内存输出数据,就是写内存;内存数据输入流,对于流,就是将内存的数据读出)
字节流操作的是字节数据,字符流操作的也是字节数据,不过它会查询编码表。
对于Writer()方法,字节流写入字节,字符流写入字符!
字节流读取示例
package pack;
import java.io.*;
public class FileStreamDemo
{
public static void main(String[] args) throws IOException
{
writeFile();
readFile_1();
System.out.println();
readFile_2();
System.out.println();
readFile_3();
}
//写字节流
public static void writeFile() throws IOException
{
//使用抽象类OutpurStream的子类FileOutpurStream创建字节流写入对象,同时创建一个txt文件
FileOutputStream fos = new FileOutputStream("fos.txt");//这里可能没有写入文件或者写入文件错误,注意抛出异常
/*写数据
write(byte[] b):将 b.length 个字节从指定 byte 数组写入此文件输出流中。
write(int b):将指定字节写入此文件输出流(只操作8位数据)。
*/
//这里使用 String类的byte[] getBytes()将字符串转变为字节数组再写入
fos.write("abcdef".getBytes());
//这里我们发现不刷新不关闭文件“fos.txt”中也有数据(19-11,7.40解析)
//对于没有指定缓冲区的字节流,数据会直接写入内存,不需要刷新(与字符流的区别)
fos.close();
}
//读字节流——一个字节一个字节读取
public static void readFile_1()throws IOException
{
FileInputStream fis = new FileInputStream("fos.txt");
//int read():从此输入流中读取一个数据字节。 与字符流相同,读到结尾返回-1
int ch = 0;
while((ch = fis.read()) != -1)
{
System.out.println((char)ch);//将读到的字节的int数据转换为char字符
}
fis.close();//注意关闭流
}
//读字节流——按数组读取
public static void readFile_2()throws IOException
{
FileInputStream fis = new FileInputStream("fos.txt");
//int read(byte[] b) 从此输入流中将最多 b.length个字节的数据读入一个 byte数组中。当数组长度为-1读取完毕。
int len= 0;
byte[] buf = new byte[1024];//注意这里改为byte数组
while((len = fis.read(buf)) != -1)//对比readFile_3,这里我们不知道要存入的字节长度,因此需要判断
{
System.out.println(new String(buf,0,len));//同样使用String的构造方法将byte数组转换为字符串
}
fis.close();//注意关闭流
}
//读字节流——使用字节流的特殊方法available——慎重使用,读取的数据太大的时候内存会溢出
public static void readFile_3()throws IOException
{
FileInputStream fis = new FileInputStream("fos.txt");
//使用available方法获取我们要读取的文件中字节的个数(包括回车“\r\n”)
int num = fis.available();
//这里我们已经知道要存储的字节个数,因此我们直接用数组将其存储起来即可,不需要循环判断结尾(只有到了结尾read()才会返回1)
byte[] buf = new byte[num];//将数组长度定义为要存储的字节个数
fis.read(buf);//直接将直接存储到buf,由于buf长度与要存储的字节个数刚刚好相等,所以不需要判断结尾
System.out.println(new String(buf));//buf与字节个数刚刚好,就不需要再指定数组长度
fis.close();
}
}
/*
* 结果:第一种一次打印一个字节,第二种则是将字节全部存储到数组中再打印。
a
b
c
d
e
f
abcdef
abcdef
*/
字节流练习:需求:想要操作图片数据,这时就要用到字节流。复制一个图片。
/*(不要用字符流处理,容易出错!)
复制一个图片,思路:
1,用字节读取流对象和图片关联;
2,用字节写入流对象创建一个图片文件,用于存储获取到的图片数据;
3,通过循环读写,完成数据的存储;
4,关闭资源。
*/
package pack;
import java.io.*;
public class CopyPic
{
public static void main(String[] args) throws IOException
{
FileInputStream fis = null;
FileOutputStream fos = null;
try
{
fis = new FileInputStream("G:\\readLine原理图.bmp");//先读取一张图片数据
fos = new FileOutputStream("G:\\copy.bmp");//创建一张图片用于存储
byte[] buf = new byte[1024];
int len = 0;
while((len = fis.read(buf)) != -1)
{
fos.write(buf,0,len);
}
}
catch(IOException e)
{
System.out.println("图片复制失败");
}
finally
{
try
{
if(fis != null)
fis.close();
}
catch(IOException e)
{
System.out.println("读取关闭失败");
}
try
{
if(fos != null)
fos.close();
}
catch(IOException e)
{
System.out.println("写入关闭失败");
}
}
}
}
2、字节流缓冲区
字节流缓冲区与字符流的缓冲区使用方法类似,不过字符流缓冲区的写入BufferedWrite有换行方法newLine(),而字节流写入BufferedOutputStream则没有;字节流缓冲区读取BufferedReader可以读行readLine(),而字节流读取缓冲区BufferedInputStream只能读取单个字节或者字节数组。(因为字节流缓冲区在读取的时候会将换行符也一起读取进来,所以在写出的时候也不需要手动换行)
如下示例
/*(不要用字符流处理,容易出错!)
复制一个图片,思路:
1,用字节读取流对象和图片关联;
2,用字节写入流对象创建一个图片文件,用于存储获取到的图片数据;
3,通过循环读写,完成数据的存储;
4,关闭资源。
*/
package pack;
import java.io.*;
public class ByteBuffered
{
public static void main(String[] args) throws IOException
{
//用currentTimeMillis()方法来测量拷贝的时间
long start = System.currentTimeMillis();
copy_1();
long end = System.currentTimeMillis();
System.out.println("拷贝的时间为:"+(end - start));
}
//通过字节流的缓冲区完成复制。
public static void copy_1()throws IOException
{
BufferedOutputStream bufos = new BufferedOutputStream(new