inputStream和InputstreamReader和writer分别怎么用?有什么联系?
InputStream 是接口
File(path);
FileInputStream(file); ---- read write对应于byte[],所以字节流
InputStreamReader(fileInputStream); ----read write对应于char[],所以字符流
BufferedReader(inputStreamReader); ---- read write对应于char[],增加了readLine方法
字节流:InputStream 和OutputStream,两个是为字节流设计的,主要用来处理字节或二进制对象,
字符流:Reader和 Writer.两个是为字符流(一个字符占两个字节)设计的,主要用来处理字符或字符串.
文字文件的时候使用字符流;视频音乐等使用字节流
InputStream,FileInputStream,InputStreamReader,FileReadr,BufferedReader之间的区别
1字节=8bit(位)
Java中
但是utf-8下:
1字符 = 1字节
1字符 = 3字节(中文)
Unicode下:
1字符 = 2字节
InputStream和FileInputStream区分:
InputStream是接口,不能实例化,FileInputStream是InputStream的实现类,用以读取字节流
FileReader和InputStreamReader
都是字符流,但是两者构造器不同:
new InputStreamReader(InputStream in)//将流作为参数
new FileReader(File或fileName)//将文件或文件路径及名称作为路径
//字节流
fis = new FileInputStream(new File(“d://aa.txt”));
n = fis.read(byte[])//fis还有内容返回读取的字节数,否则返回-1
//字符流
fileReader=new FileReader("d:\\aa.txt");
inputStreamReader = new InputStreamReader(System.in);
(n=fileReader.read(char[]))!=-1//fileReader还有内容返回读取的字符数,否则返回-1
//字符串流
BufferedReader br=new BufferedReader(fileReader);或
new BufferedReader(inputStreamReader)
(s=br.readLine())!=null//直接返回读取的字符串
从字节-->字符-->字符串流,本质就是读取的单位越来越大.其实本质上计算机能识别的只有0和1(位bit),但是bit根本不能存储小的信息单位,所以数据是以字节为单位存储的。
问题1:有了字节流为什么还需要字符流?
本质问题就是有了字节为什么还需要字符,参照上面 Ascii,Unicode和utf-8之间的区分与联系.
问题2:什么时候使用字节流、什么时候使用字符流?
字节流与字符流区别:
1)字节流在操作时不会用到缓冲区(内存),直接对文本本身进行操作;但字符在操作时使用了缓冲区,通过缓冲区在操作文件
2)在硬盘上所有文件都是以字节形式存在(图片,音频,视频),字符在内存中才会形成
针对第一点:如果一个程序频繁对资源做IO操作,使用字节流,效率会很低;如果使用字符流,把需要操作的数据暂时放到内存中,以后直接从内存读取,避免多次IO操作,提高效率;
针对第二点:真正存储和传输数据都是以字节为单位的,字符仅存在于内存,所以字节使用范围更广.
结论:
字节用来读取英文,图片,歌曲,视频还能内容比较适合
但是中文之类的应该使用字符流,可以提高效率
问题3流中经常用到的设计模式有几个?是什么?怎么用的?
两种 适配器和装饰器
适配器:如 new InputStreamReader(new FileInputStream(“Data。txt”));
io有什么作用
1 文件操作,如问文件写入、上传等
2 网络编程中的应用。其实接口请求、内容返回,这些数据的传输都是通过流来实现
bio和nio操作文件实例
public class StreamTest {
public static void main(String[] args) {
try {
long l1 = System.currentTimeMillis();
File source = new File("/Users/mazhen/desktop/软件/归档.zip");
File dest = new File("/Users/mazhen/desktop/软件/归档.zip1");
FileInputStream fileInputStream = new FileInputStream(source);
FileOutputStream fileOutputStream = new FileOutputStream(dest);
// StreamTest.inDirectCopyFile(fileInputStream,fileOutputStream);
StreamTest.directCopyFile(fileInputStream,fileOutputStream);
// StreamTest.nioTransferTo();
// StreamTest.bioCopyFile(fileInputStream,fileOutputStream);
fileInputStream.close();
fileOutputStream.close();
long l2 = System.currentTimeMillis();
System.out.println(l1-l2);
// new StreamTest().nioTransferTo();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void bioCopyFile(FileInputStream fis, FileOutputStream fos) throws IOException {
byte[] bytes = new byte[1024];
int n = 0;
while ((n = fis.read(bytes)) != -1) {
fos.write(bytes,0,n);
}
}
// nio 间接拷贝 内核空间->用户空间->内核空间
public static boolean inDirectCopyFile(FileInputStream fis, FileOutputStream fos) throws IOException {
FileChannel srcFileChannel = fis.getChannel();
FileChannel targetFileChannel = fos.getChannel();
//间接获取ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while(true) {
byteBuffer.clear();
int readByte = srcFileChannel.read(byteBuffer);
if(readByte == -1) {
break;
}
byteBuffer.flip();
targetFileChannel.write(byteBuffer);
}
return true;
}
// nio 直接拷贝 内核空间->内核空间
public static boolean directCopyFile(FileInputStream fis, FileOutputStream fos) throws IOException {
FileChannel srcFileChannel = fis.getChannel();
FileChannel targetFileChannel = fos.getChannel();
//间接获取ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
while(true) {
byteBuffer.clear();
int readByte = srcFileChannel.read(byteBuffer);
if(readByte == -1) {
break;
}
byteBuffer.flip();
targetFileChannel.write(byteBuffer);
}
return true;
}
// nio零拷贝方法
public static void nioTransferTo() throws IOException {
File source = new File("/Users/mazhen/desktop/软件/kesmac.zip");
File dest = new File("/Users/mazhen/desktop/软件/kesmac.zip1");
FileChannel sourceChannel = new FileInputStream(source).getChannel();
FileChannel destChannel = new FileOutputStream(dest).getChannel();
sourceChannel.transferTo(0, sourceChannel.size(), destChannel);
}
}
上面代码测试结果如下
mac测试 --时间都是ms
1.1G 350M
传统bio方式 20238 6065
indirectBuffer 15556 4673
directBuffer 13268 4600
transferTo 1214 350 ---强大的零拷贝
需要拷贝的方式:直接拷贝(使用indirectBuffer)和间接拷贝(使用directBuffer),差别30%性能,差别并不大;
非directBuffer时,内核空间-->用户空间数据-->内核空间。
directBUffer时,内核空间1-->内核空间2。
使用directBuffer少了一次内存拷贝,但是性能提升真的有限
零拷贝和需要拷贝的方式相比,效率差别很大,10-20倍左右性能差距!!!!
所以建议使用transferTo的零拷贝方式
上面使用directBuffer好像没啥卵用,或者是因为我的文件不够大。。。
说明:虽然现在单独出了nio包,但是其实io包中的FileInputStream其实效果也不会很差,因为已经用nio对io中的类进行了改写,下面代码可以证明: