------------android培训、java培训、期待与您交流!--------------
大纲:
一、字节流概述
二、FileInputStream
三、复制图片(字节输入输出流)
四、复制mp3(通过字节流的缓冲区完成复制)
五、模拟BufferedInputStream
六、键盘录入
七、转换流(属字符流)
八、打印系统参数
一、字节流概述
字节流的抽象基类:
|---->InputStream:字节输入流
|---->OutputStream:字节输出流
它的操作与字符流类似,可以参与字符流的定义、读取、写入、处理异常的格式,只不过
它可以对非字符的数据,比如图片、视频、音频文件(例如mp3)等进行操作,而字符流不能。
常用字节流:
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
二、FileInputStream
FileInputStream是InputStream的一个子类,用于读取诸如图像数据之类的原始字节流。
import java.io.*;
class FileStream {
public static void main(String[] args) throws IOException {
readFile_3();
}
// 第三种方式:定义一个刚刚好的字节数组,进行读取,文件太大不适合用
public static void readFile_3() throws IOException {
FileInputStream fis = new FileInputStream("fos.txt");
// 定义一个刚刚好的缓冲区。不用在循环了。
int num = fis.available();//返回文件的字节数
byte[] buf = new byte[num];
fis.read(buf);
System.out.println(new String(buf));
fis.close();
}
// 第二种方式:定义字节数组,循环读取
public static void readFile_2() throws IOException {
FileInputStream fis = new FileInputStream("fos.txt");
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
System.out.println(new String(buf, 0, len));
}
fis.close();
}
// 第一种方式:一个一个字节读取
public static void readFile_1() throws IOException {
FileInputStream fis = new FileInputStream("fos.txt");
int ch = 0;
while ((ch = fis.read()) != -1) {
System.out.println((char) ch);
}
fis.close();
}
// 往文件里写数据
public static void writeFile() throws IOException {
FileOutputStream fos = new FileOutputStream("fos.txt");
fos.write("abcde".getBytes());
fos.close();
}
}
但不适合大文件(如视频),这样内存会崩溃。
三、复制图片(字节输入输出流)
用FileInputStream和FileOutputStream流对象
思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。
import java.io.*;
class CopyPic
{
public static void main(String[] args)
{
FileOutputStream fos = null;
FileInputStream fis = null;
try
{
fos = new FileOutputStream("c:\\2.bmp");
fis = new FileInputStream("c:\\1.bmp");
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("写入关闭失败");
}
}
}
}
四、复制mp3(通过字节流的缓冲区完成复制)
用BufferedOutputStream和BufferedInputStream流对象,对象里面都有内置的数组做缓冲
import java.io.*;
class CopyMp3
{
public static void main(String[] args) throws IOException
{
long start = System.currentTimeMillis();
copy();
long end = System.currentTimeMillis();
System.out.println((end-start)+"毫秒");
}
//通过字节流的缓冲区完成复制。
public static void copy()throws IOException
{
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));
int by = 0;
while((by=bufis.read())!=-1)
{
bufos.write(by);
}
bufos.close();
bufis.close();
}
}
以上read方法虽然也是一个一个字节读取的,但是效率依然很高,因为read方法不从硬盘直接读取,
而是从缓冲流内部的字节数组中读取的。write方法也不是收到一个字节就输出到硬盘,而是先把它
存到内部数组中,等数组存满之后再输出到硬盘中。说到底read和write方法之间是通过数组交换
数据的,也就是数据在内存中进行交换。
五、模拟BufferedInputStream
import java.io.*;
class MyBufferedInputStream {
private InputStream in;
private byte[] buf = new byte[1024 * 4];
private int pos = 0, count = 0;
MyBufferedInputStream(InputStream in) {
this.in = in;
}
// 一次读一个字节,从缓冲区(字节数组)获取。
public int myRead() throws IOException {
// 通过in对象读取硬盘上数据,并存储buf中。
if (count == 0) {
count = in.read(buf);
if (count < 0)
return -1;
pos = 0;
byte b = buf[pos];
count--;
pos++;
return b & 255;
} else if (count > 0) {
byte b = buf[pos];
count--;
pos++;
return b & 0xff;
}
return -1;
}
public void myClose() throws IOException {
in.close();
}
}
1、myread返回值类型为什么是int而不是byte?
下面是一段字节码文件的二进制数据:
11111111-111111110000000000101001001010100101010010101001010
第一个字节就是11111111,十进制就是-1,所以如果不做任何转换的话myread
方法读到-1程序就会停止读取数据,数据还没有读完,程序就已经结束,读到的
数据就不再完整,所以需要转化。
2、为什么return b时要&255(0xff)?
因为针对字节是11111111,需要转化,先将byte提升为int,
即由11111111变为 11111111 11111111 11111111 11111111
但int类型的还是-1,是-1的原因是因为在8个1前面补的是1导致的。
那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现。
这就需要&255(0xff),操作如下:
11111111 11111111 11111111 11111111
&00000000 00000000 00000000 11111111
------------------------------------------------------------
00000000 00000000 00000000 11111111
得到的数据是255不再是-1
扩展一下:
一个数的负数,是取反之后再加1。
比如1的二进制是00000001
-1的二进制是:
0000-0001 --------〉 1
1111-1110 --------〉 取反
0000-0001 --------〉 加1
1111-1111 --------〉 -1二进制
六、键盘录入
System.out:对应的是标准输出设备,控制台。
System.in:对应的标准输入设备:键盘。
需求:
通过键盘录入数据。
当录入一行数据后,就将该行数据进行打印。
如果录入的数据是over,那么停止录入。
import java.io.*;
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("over".equals(s))
break;
System.out.println(s.toUpperCase());
sb.delete(0,sb.length());//清空数组
}
else
sb.append((char)ch);
}
}
}
七、转换流(属字符流)
用InputStreamReader和OutputStreamReader
是字符和字节之间的桥梁,通常涉及到字符编码转换时,需要用到转换流。
键盘录入(缓冲方式)
import java.io.*;
class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
//获取键盘录入对象。
//InputStream in = System.in;
//将字节流对象转成字符流对象,使用转换流。InputStreamReader
//InputStreamReader isr = new InputStreamReader(in);
//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
//BufferedReader bufr = new BufferedReader(isr);
//键盘的最常见写法。
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
// OutputStream out = System.out;
// OutputStreamWriter osw = new OutputStreamWriter(out);
// BufferedWriter bufw = new BufferedWriter(osw);
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
bufr.close();
}
}
通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。
也就是readLine方法。
readLine方法是字符流BufferedReader类中的方法。因此需要对InputStream类
进行装饰,但一个是字符流,一个是字节流,中间就需要一个转换流。
编码表
FileWriter是使用的默认编码表GBK.
但是存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。
所以要使用的对象是OutputStreamWriter。而该转换流对象要接收一个字节输出流。
而且还可以操作的文件的字节输出流FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");
还需要高效处理的话就要用缓冲流,BufferedWriter bufw = new BufferedWriter(osw);
八、打印系统参数
import java.util.*;
import java.io.*;
class SystemInfo
{
public static void main(String[] args) throws IOException
{
Properties prop = System.getProperties();
//System.out.println(prop);
prop.list(new PrintStream("sysinfo.txt"));
}
}
------------android培训、java培训、期待与您交流!--------------