/**
*@author StormMaybin
*Date 2016-07-29
*/
总有人要赢的,那个人为什么不能是我?
继续昨天的IO流总结,今天是第二篇,在上一篇说会分为两篇来总结IO,可是今天看了看,貌似还有一些知识点没复习到,所以会增加一篇,另外以后还会不定时的分享一些其他知识点总结,温故而知新嘛,哈哈,废话不多说了,开始吧!
上一篇是从字符流开始的,这一篇我们来看看字节流,转换流和一些小的知识点,以及字节流的运用(复制MP3文件或者图片)!
和字符流一样,字节流也有两个抽象类作为其他类的父类,一个是输出字节流InputStream,另外一个就是OutputStream。其他类都是这两个类的拓展!
字节流的概念就先看到这,下面我们先用一个小案例来引出今天的知识点(复制图片文件)
package com.stormma.FileStream;
import java.io.*;
/***
* 复制 一个图片
* 思路:
* 1、字节读取流对象和图片文件进行关联
* 2、用字节写入流创建一个图片文件,用于存储获取到的图片数据
* 3、通过循环读写,完成数据的存储
* 4、关闭资源
* @author StormMaybin
*
*/
public class CopyPic
{
/**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
FileInputStream fis = null;
FileOutputStream fos = null;
try
{
fos = new FileOutputStream ("F:\\2.jpg");
fis = new FileInputStream ("F:\\1.jpg");
byte [] buf = new byte [1024];
int len = 0;
while ((len = fis.read(buf)) != -1)
{
fos.write(buf,0,len);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (fis != null)
{
try
{
fis.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
if (fos != null)
{
try
{
fis.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
复制结果:
可以看到我们成功的复制了1.png这个图片资源!
package com.stormma.FileStream;
import java.io.*;
/***
* 需求:
* 自定义字节流的缓冲
* @author StormMaybin
*
*/
public class MyBufferedInputStream
{
private InputStream in;
private byte [] buf = new byte [1024];
private int pos = 0;
private int count = 0;
public MyBufferedInputStream (InputStream in)
{
this.in = in;
}
public int myRead()
{
//通过in对象读取硬盘中的数据,存储到buf中去
//如果是count=0,那么说明byte数组是空的,所以开始读取数据
if (count == 0)
{
try
{
count = in.read(buf);
//标记位
pos = 0;
}
catch (Exception e)
{
e.printStackTrace();
}
//通过下标找到数据
byte b = buf [pos];
//byte数组的个数递减
count --;
//移动标记位
pos ++;
/***
* 至于这个为什么是返回b&255,原因很简单就是
* 一个字节是8位,比如00000000 00000000 00000000 11111111
* 这个转换成int类型是-1 ,这样会导致复制意外结束
*/
return b&255;
}
//如果byte数组中还有数据继续往出取!
else if (count > 0)
{
byte b = buf [pos];
count --;
pos ++;
return b&255;
}
return -1;
}
//关闭流方法
public void myClose()
{
try
{
in.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
这样,就完成了输入字节流的自定义!
何时使用转换流?
具体的对象体现:
我们来看看java API是怎么解释的
这样说起来很苍白,我们还是来用代码演示一下!
演示代码之前,先看一个小技巧
/**
* 流操作的基本规律:
* 1、明确源和目的
* --源:输入流:InputStream,Reader
* --目的:输出流:OutputStream,Writer
* 2、操作的数据是否是纯文本
* --是纯文本:字符流
* --不是纯文本:字节流
* 3、当体系明确之后,然后明确用哪个具体的对象
* 通过设备来区分
* 源设备:内存,磁盘,键盘
* 目的设备:内存,硬盘,控制台
*/
现在我们来实现一个功能,把一个文件的内容输出到控制台上!
package com.stormma.FileStream;
import java.io.*;
/***
1. 源:文件
2. 目的:控制台
3. 需求:把文件内容输出到控制台上
4. @author StormMaybin
5. 分析:
6. 因为源是文本文件,那么选择使用Reader
7. 目的是控制台,对应的对象是System.in,System.in操作字节流
8. 但是为了操作更见方便,这样用转换流把字节流转换成字符流
9. InputStreamReader isr = new InputStreamReader(System.in);
10. 然后看看是否要提高效率,如皋需要的话,那么就选择使用缓冲区
11. BufferedReader bufr = new BufferedReader(isr);
12. 合并为一句就是BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
13. ***********
14. 这里如果需要编码转换的话
15. 可以用转换流进行编码格式转化
16. 参数(String encoding)
*/
public class FileStreamDemo2
{
/**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
//创建读取和写入对象
BufferedReader bufr = null;
BufferedWriter bufw = null;
try
{
/***
* FileInputStream fis = new FileInputStream ("copy_bufwriter.txt");
* InputStreamReader isr = new InputStreamReader(fis);
* BufferdeReader bufr = new BufferedReader(isr);
*
*/
bufr = new BufferedReader(new InputStreamReader(new FileInputStream("copy_bufwriter.txt")));
bufw = new BufferedWriter(new OutputStreamWriter(System.out));
}
catch (FileNotFoundException e)
{
System.out.println("找不到文件了");
}
String lines = null;
try
{
while ((lines = bufr.readLine()) != null)
{
bufw.write(lines);
bufw.newLine();
bufw.flush();
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if (bufr != null)
{
try
{
bufr.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
if (bufw != null)
{
try
{
bufw.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
现在问题又出来了,这怎么回事,打印结果里面怎么有乱码!其实很简单,源文件copy_bufwriter.txt这个的编码格式是utf-8,而在上面的代码中默认是gbk解码和编码的!编码:字符–>字节,解码:字节–>字符,既然源文件的编码格式是utf-8,那我们应该也用utf-8来编码和解码,不然肯定会产生乱码的!所以我们来修改一下源文件来解决这个问题!
package com.stormma.FileStream;
import java.io.*;
public class FileStreamDemo2
{
/**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
BufferedReader bufr = null;
BufferedWriter bufw = null;
try
{
/***
* FileInputStream fis = new FileInputStream ("copy_bufwriter.txt");
* InputStreamReader isr = new InputStreamReader(fis);
* BufferdeReader bufr = new BufferedReader(isr);
*
*/
bufr = new BufferedReader(new InputStreamReader(new FileInputStream("copy_bufwriter.txt"),"utf-8"));
bufw = new BufferedWriter(new OutputStreamWriter(System.out,"utf-8"));
}
catch (FileNotFoundException e)
{
System.out.println("找不到文件了");
}
catch (UnsupportedEncodingException e)
{
System.out.println("不支持这种编码格式");
}
String lines = null;
try
{
while ((lines = bufr.readLine()) != null)
{
bufw.write(lines);
bufw.newLine();
bufw.flush();
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if (bufr != null)
{
try
{
bufr.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
if (bufw != null)
{
try
{
bufw.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
现在上面那一行乱码中文注释解决了!
现在我们看一下LineNumberReader这个类!本来这个类应该是上一篇文章中的,但是由于疏忽,哈哈哈,我们先来看一下java API对LineNumbetReader的介绍吧
大致了解一下,下面我们自己来定义一个MyLineNumberReader类来实现LineNumberReader类的功能。
package com.stormma.FileReaderWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class MyLineNumberReader
{
private Reader r;
private int lineNumber = 0;
/***
* @author StormMaybin
* @param r
*/
public MyLineNumberReader(Reader r)
{
this.r = r;
}
public String myReadLine()throws IOException
{
//标记行号
lineNumber++;
StringBuilder sb = new StringBuilder();
int ch = 0;
//因为这里的read方法有可能会抛出异常
//所以这个函数申明可抛出异常
while ((ch = r.read()) != -1)
{
if (ch == '\r')
{
continue;
}
else if (ch == '\n')
{
return sb.toString();
}
else
{
sb.append((char)ch );
}
}
//避免丢失最后一行
if (sb.length() != 0)
{
return sb.toString();
}
return null;
}
/***
* myClose方法
* 实现关闭流功能
* @throws IOException
*/
public void myClose()throws IOException
{
r.close();
}
public int getLineNumber()
{
return lineNumber;
}
public void setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
}
}
/***
* 演示类
* @author StormMaybin
*
*/
class MyLineNumberReaderDemo
{
public static void main (String [] args)throws IOException
{
FileReader fr = new FileReader("copy_bufwriter.txt");
MyLineNumberReader mbufr = new MyLineNumberReader(fr);
mbufr.setLineNumber(100);
String lines = null;
while ((lines = mbufr.myReadLine()) != null)
{
System.out.println(mbufr.getLineNumber()+lines);
}
mbufr.myClose();
}
}
好了,java IO总结篇(二)到这就结束了,期待第三篇,哈哈哈!