FileInputStream
用字节流复制一张图片
public class CopyPicture {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("D:\\1.png");
fos = new FileOutputStream("D:\\2.png");
byte[] buf = new byte[1024];
int len = 0;
while((len = fis.read(buf)) != -1){
fos.write(buf,0,len);
}
} catch (IOException e) {
throw new RuntimeException("复制文件失败");
} finally {
try {
if(fis != null)
fis.close();
} catch (IOException e) {
throw new RuntimeException("读取文件关闭失败");
}
try {
if(fos != null)
fos.close();
} catch (IOException e) {
throw new RuntimeException("写入文件关闭失败");
}
}
}
}
BufferedInputStream
原理:
缓冲区里面有一个数组,每次抓取一批数据存入数组中,并返回数据长度。定义一个指针,从数组中一个一个读出数据,当数据读完时,再抓取一批数据。自定义缓冲区代码如下:
public class MyBufferedInputStream {
InputStream is;
byte[] buf = new byte[1024];
int count;//抓取的数据长度
int pos;//指针
MyBufferedInputStream(InputStream is){
this.is = is;
}
public int myRead() throws IOException {
if(count == 0) {
count = is.read(buf);
if(count == -1)
return -1;
pos = 0;
}
byte b = buf[pos];
count--;
pos++;
return b&255;//注释如下
}
}
注意 read读一个字节可能读到-1,导致不再继续往下读,所以read把byte类型提升为一个int类型,但还是-1,是-1的原因是因为在8个1前面补的都是1导致的。那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现
read方法在提升,write方法在强转
测试如下
public class CopyMp3 {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
copy();
long end = System.currentTimeMillis();
System.out.println((end - start) + "毫秒");
}
private static void copy() throws IOException {
FileInputStream fis = new FileInputStream("D:\\1.png");
FileOutputStream fos = new FileOutputStream("D:\\2.png");
MyBufferedInputStream mbis = new MyBufferedInputStream(fis);
int lin = 0;
while((lin = mbis.myRead()) != -1) {
fos.write(lin);
}
fis.close();
fos.close();
}
}
读取键盘录入
- System.out:对应的是标准的输出设备,控制台
- System.in:对应的是标准输出设备:键盘
- 当录入一行数据后,就将该行数据打印
- 如果录入的数据是over,那么停止录入
public class ReadIn {
public static void main(String[] args) throws IOException {
InputStream in = System.in;
StringBuilder sb = new StringBuilder();
while(true) {
int ch = in.read();
if(ch == '\r')
continue;
if(ch == '\n') {
String s= sb.toString();
if(s.equals("over"))
break;
System.out.println(s);
sb.delete(0, sb.length());
}else {
sb.append((char)ch);
}
}
}
}
既然是录入一行一行打印,可以想到字符流缓冲区的readLine()方法,所以需转换流,代码如下
public class 转换流 {
public static void main(String[] args) throws IOException {
//字节流转字符流
InputStream in = System.in;
InputStreamReader isr = new InputStreamReader(in);
BufferedReader bufr = new BufferedReader(isr);
//字符流转字节流
PrintStream out = System.out;
OutputStreamWriter osr = new OutputStreamWriter(out);
BufferedWriter bufw = new BufferedWriter(osr);
String line = null;
while((line = bufr.readLine()) != null) {
if(line.equals("over"))
break;
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}
}
流的操作规律:
想要知道
-
明确源和目的(汇)
源:inputStream Reader
目的:OutputStream Writer -
明确数据是否是纯文本数据
源:是纯文本:Reader 否则:InputStream
目的:是纯文本:Writer 否则:OutputStream -
明确具体的设备
源设备:- 硬盘:File
- 键盘:System.in
- 内存:数组
- 网络:Socket流
目的设备:
- 硬盘:File
- 控制台:System.out
- 内存:数组
- 网络:Socket流
-
是否需要其他额外功能
- 是否需要高效(缓冲区)
是,就加上buffer - 流转换
- 是否需要高效(缓冲区)
什么时候使用流转换呢?
- 源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁。提供对文本操作的便捷
- 一但文本设计到具体的指定编码表时,就必须使用转换流