- 字符流:
FileReader
FileWriter
BufferedReader
BufferedWriter- 字节流:
InputStream OutputStream
需求,想要操作图片数据,这时就要用到字节流。
- 1.写数据
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileStream {
public static void main(String[] args) throws IOException
{
writeFile();
}
public static void writeFile() throws IOException
{
FileOutputStream fos = new FileOutputStream("fos.txt");
fos.write("abcde".getBytes());
fos.close();
}
}
Snip20190917_21.png
- 2.读取数据
一、挨个读取
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileStream {
public static void main(String[] args) throws IOException
{
readFile_1();
}
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();
}
}
//输出
a
b
c
d
e
二、读取一行
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileStream {
public static void main(String[] args) throws IOException
{
readFile_2();
}
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();
}
}
//输出
abcde
三、使用available定义缓冲区。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public 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[fis.available()];//定义一个刚刚好的缓冲区,不用再循环了。
fis.read(buf);
System.out.println(new String(buf));
System.out.println("num="+num);
fis.close();
}
}
//输出
abcde
num=5
复制一个图片
思路:
1.用字节读取流对象和图片关联。
2.用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3.通过循环读写,完成数据的存储。
4.关闭资源。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyPic {
public static void main(String[] args)
{
FileOutputStream fos = null;
FileInputStream fis = null;
try
{
fos = new FileOutputStream("1.png");
fis = new FileInputStream("landscape.jpg");
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("写入关闭失败");
}
}
}
}
Snip20190918_23.png
演示mp3的复制,通过缓冲区。
BufferedOutputStream
BufferedInputStream
循环每次读取一个字节,有多少个字节读取多少次。再把每一个字节写入到1.mp3中。一共有8098212个字节。每次读取到的这个字节用by来接收,by为int型打印by的值为这个二进制的字节所表示的十进制数,循环里面会进行8098212次计算。
Snip20190918_26.png
import java.io.*;
public class CopyMp3 {
public static void main(String[] args) throws IOException
{
long start = System.currentTimeMillis();
copy_1();
long end = System.currentTimeMillis();
System.out.println((end-start) + "毫秒");
}
//通过字节流的缓冲区完成复制
public static void copy_1() throws IOException
{
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("0.mp3"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("1.mp3"));
int by = 0;
int count = 0;
while ((by=bufis.read())!=-1)
{
count++;
bufos.write(by);
}
System.out.println(count);
bufos.close();
bufis.close();
}
}
//输出
8098212
259毫秒
Snip20190918_25.png
自定义缓冲区复制Mp3
import java.io.*;
class MyBufferedInputStream
{
private InputStream in;
private byte[] buf = new byte[1024];
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);
System.out.println("输出的字节数组长度:"+count);
if (count < 0)
return -1;
pos = 0;
byte b = buf[pos];
count--;
pos++;
System.out.println("读到的字符数组中第"+pos+"个字节十进制表示为:"+b);
return b;
}
else if (count>0)
{
byte b = buf[pos];
count --;
pos++;
System.out.println("读到的字符数组中第"+pos+"个字节十进制表示为:"+b);
return b;
}
return -1;
}
public void myClose()throws IOException
{
in.close();
}
}
public class CopyMp3 {
public static void main(String[] args) throws IOException
{
long start = System.currentTimeMillis();
copy_2();
long end = System.currentTimeMillis();
System.out.println((end-start) + "毫秒");
}
public static void copy_2() throws IOException
{
MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("0.mp3"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("2.mp3"));
int by = 0;
int count = 0;
// System.out.println("第一个字节十进制表示为:"+bufis.myRead());
while ((by=bufis.myRead())!=-1)
{
// System.out.println("当前的字节"+by);
count++;
System.out.println("写入计数"+count);
bufos.write(by);
}
System.out.println("写入的字节数:"+count);
bufos.close();
bufis.myClose();
}
}
//输出
输出的字节数组长度:1024
读到的字符数组中第1个字节十进制表示为:73
写入计数1
读到的字符数组中第2个字节十进制表示为:68
写入计数2
读到的字符数组中第3个字节十进制表示为:51
写入计数3
读到的字符数组中第4个字节十进制表示为:4
写入计数4
读到的字符数组中第5个字节十进制表示为:0
写入计数5
读到的字符数组中第6个字节十进制表示为:0
写入计数6
读到的字符数组中第7个字节十进制表示为:0
写入计数7
读到的字符数组中第8个字节十进制表示为:0
写入计数8
读到的字符数组中第9个字节十进制表示为:0
写入计数9
读到的字符数组中第10个字节十进制表示为:35
写入计数10
读到的字符数组中第11个字节十进制表示为:84
写入计数11
读到的字符数组中第12个字节十进制表示为:83
写入计数12
读到的字符数组中第13个字节十进制表示为:83
写入计数13
读到的字符数组中第14个字节十进制表示为:69
写入计数14
读到的字符数组中第15个字节十进制表示为:0
写入计数15
读到的字符数组中第16个字节十进制表示为:0
写入计数16
读到的字符数组中第17个字节十进制表示为:0
写入计数17
读到的字符数组中第18个字节十进制表示为:15
写入计数18
读到的字符数组中第19个字节十进制表示为:0
写入计数19
读到的字符数组中第20个字节十进制表示为:0
写入计数20
读到的字符数组中第21个字节十进制表示为:3
写入计数21
读到的字符数组中第22个字节十进制表示为:76
写入计数22
读到的字符数组中第23个字节十进制表示为:97
写入计数23
读到的字符数组中第24个字节十进制表示为:118
写入计数24
读到的字符数组中第25个字节十进制表示为:102
写入计数25
读到的字符数组中第26个字节十进制表示为:53
写入计数26
读到的字符数组中第27个字节十进制表示为:53
写入计数27
读到的字符数组中第28个字节十进制表示为:46
写入计数28
读到的字符数组中第29个字节十进制表示为:49
写入计数29
读到的字符数组中第30个字节十进制表示为:57
写入计数30
读到的字符数组中第31个字节十进制表示为:46
写入计数31
读到的字符数组中第32个字节十进制表示为:49
写入计数32
读到的字符数组中第33个字节十进制表示为:48
写入计数33
读到的字符数组中第34个字节十进制表示为:52
写入计数34
读到的字符数组中第35个字节十进制表示为:0
写入计数35
读到的字符数组中第36个字节十进制表示为:0
写入计数36
读到的字符数组中第37个字节十进制表示为:0
写入计数37
读到的字符数组中第38个字节十进制表示为:0
写入计数38
读到的字符数组中第39个字节十进制表示为:0
写入计数39
读到的字符数组中第40个字节十进制表示为:0
写入计数40
读到的字符数组中第41个字节十进制表示为:0
写入计数41
读到的字符数组中第42个字节十进制表示为:0
写入计数42
读到的字符数组中第43个字节十进制表示为:0
写入计数43
读到的字符数组中第44个字节十进制表示为:0
写入计数44
读到的字符数组中第45个字节十进制表示为:0
写入计数45
读到的字符数组中第46个字节十进制表示为:-1
写入的字节数:45
3毫秒
发现的Mp3文件字节有缺省,循环只进行了45次,复制也只复制了45个字节。复制的mp3文件有缺省,打不开。通过打印发现循环只进行了45次就停止了,也就是只读到了45个字节,读到第46个字节的时候返回-1了,跳出循环。说明读到的第46个字节的十进制数为-1,二进制表示为11111111。详情请参考负数的二进制表示。
为什么读到的第46个字节的二进制为11111111?有什么办法可以避免终止循环?
读到的每一个字符是byte类型1个字节(8个二进制位),但是用int类型4个字节(32个二进制位)接收。类型提升了,但是十进制表示还是保持原值。
11111111 -->提升了一个int类型,那不还是-1吗?是-1的原因是因为在8个1前面补的是1导致的。那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现。
怎么补0呢?
11111111 11111111 11111111 11111111
& 00000000 00000000 00000000 11111111
00000000 00000000 00000000 11111111
所以需要对返回的字节和255(00000000 00000000 00000000 11111111)做与运算。
import java.io.*;
class MyBufferedInputStream
{
private InputStream in;
private byte[] buf = new byte[1024];
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);
// System.out.println("输出的字节数组长度:"+count);
if (count < 0)
return -1;
pos = 0;
byte b = buf[pos];
count--;
pos++;
// System.out.println("读到的字符数组中第"+pos+"个字节十进制表示为:"+b);
return b & 255;
}
else if (count>0)
{
byte b = buf[pos];
count --;
pos++;
// System.out.println("读到的字符数组中第"+pos+"个字节十进制表示为:"+b);
return b & 0xff;
}
return -1;
}
public void myClose()throws IOException
{
in.close();
}
}
public class CopyMp3 {
public static void main(String[] args) throws IOException
{
long start = System.currentTimeMillis();
copy_2();
long end = System.currentTimeMillis();
System.out.println((end-start) + "毫秒");
}
public static void copy_2() throws IOException
{
MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("0.mp3"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("2.mp3"));
int by = 0;
int count = 0;
// System.out.println("第一个字节十进制表示为:"+bufis.myRead());
while ((by=bufis.myRead())!=-1)
{
// System.out.println("当前的字节"+by);
count++;
// System.out.println("写入计数"+count);
bufos.write(by);
}
System.out.println("写入的字节数:"+count);
bufos.close();
bufis.myClose();
}
}
//输出
写入的字节数:8098212
196毫秒
Snip20190921_40.png
Snip20190921_41.png
网友评论