IO:
字节流:
针对的字节数据,包括文本也包括媒体数据,如果是纯文本用字符流处理较为便捷。
字节流所使用的缓冲区是一个byte[]。
常用的对象:
FileInputStream,FileOutputStream,BufferedInputStream,BufferedOutputStream。
需求:
copyMp3
public void copyMp3()
{
FileInputStream fis = new FileInputStream("1.mp3");
BufferedInputStream bufis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("2.mp3");
BufferedOutputStream bufos = new BufferedOutputStream(fos);
int by = 0;
while((by=bufis.read())!=-1)
{
bufos.write(by);
bufos.flush();
}
bufos.close();
bufis.close();
}
模拟BufferedInputStream。原理:其实将一个字节数组进行封装,通过方法将一批数据存入数组中,在通过数组的指针每一次返回数组中一个字节。当数组元素全部取出后,在存入一批新的数据,重复此过程。
class MyBufferedInputStream
{
private InputStream in;
private byte[] arr = new byte[1024*4];
private int pos = 0,count = 0;
MyBufferedInputStream(InputStream in)
{
this.in = in ;
}
public int myRead()throws IOException
{
if(count==0)
{
count = in.read(arr);
if(count<0)
return -1;
pos = 0;
byte b = arr[pos];
pos++;
count--;
return b;//return b&255;
}
else if(count>0)
{
byte b = arr[pos];
pos++;
count--;
return b;//return b&0xff;
}
return -1;
}
public void myClose()throws IOException
{
in.close();
}
}
当使用自定义的缓冲区时,居然出现的秒杀的情况,为什么会如此呢?
因为mp3数据最终的二进制表现形式中,很容易出现连续N多1的情况,
只要出现了连续的8个1,对于一个字节而言十进制体现形式就是-1。
那么就满足while循环结束条件。程序终止。
为了避免这种情况,在读到一个字节时,将该字节进行了提升变成int型。
但是byte-1,变成int 还是-1。为了避免,在进行提升的过程中,保留的源字节的8为数据,并在前以补零方式进行提升。
这样一个byte -1 变成了int 的255。这就避免了-1的情况。
如何补的零呢?只要将读到的字节&255或者&0xFF.都可以。这也是read方法不是返回byte而返回int类型的原因。
通过该过程就可以明确,read方法在对字节或者字符进行提升,而write方法在对提升后的int数据进行强转,
只写出了最低的8位,或者最低的16位。
---------------------------------
字符流:
四个:
字节流:
四个。
为了实现字符和字节流之间的转换,出现了转换流。
转换流的由来,
当读到的字节数据都是纯文本的时候,而且文本中出现中文字符,那么在解析该字节数据时就需要指定编码表。
因为可以识别中的编码表不唯一。在使用转换流时,如果未指定编码表,那么默认使用本地码表。
InputStramReader:字节通向字符的桥梁
OutputStreamWriter:字符通向字节的桥梁
--------------------------------
流操作的基本规律:
1,明确数据源和数据目的。
明确到底是使用输入流还是输出流。
2,明确要处理的数据是否是纯文本。
明确到底是使用字符流还是字节流。
当明确体系后,到底该用该体系的哪个对象呢?
根据数据存在的设备而定,
数据源所在设备可以是,硬盘,键盘,内存。
数据目的所在设备可以是,硬盘,控制台,内存。
需求:
获取键盘录入,将录入信息存储到本地文件中。
源:键盘录入,输入流。
处理的数据:纯文本,字符输入流。Reader
该用哪个对象呢?
键盘录入System.in完成的。那么它是一个标准的字节输入流。InputStream。
为了操作文本数据方便,将字节流转换成字符流。使用InputStreamReader。
但是为了提高对字符操作的效率,BufferedReader.
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
目的:本地文件(硬盘)输出流。
处理的数据:纯文本,字符输出流。Writer。
该用该体系的哪个对象呢?
可以操作的文件FileWriter对象。
为了提高写入流的效率。BufferedWriter.
public void show()
{
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw =
new BufferedWriter(new FileWriter("a.txt"));
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
bufw.write(line);
bufw.newLine();
bufw.flush();
}
bufw.close();
bufr.close();
}
/*
如果基本上面的分析,但不使用缓冲区,代码是一个什么样子呢?
*/
public static void show()throws IOException
{
InputStreamReader isr = new InputStreamReader(System.in);
FileWriter fw = new FileWriter("a.txt");
char[] arr = new char[1024];
int len = 0;
while((len=isr.read(arr))!=-1)
{
System.out.println(len);
String s = new String(arr,0,len-2);
if("over".equals(s))
break;
fw.write(arr,0,len);
fw.flush();
}
fw.close();
isr.close();
}
获取本地文本数据,将数据息存储到本地另一个文件中,按照UTF-8的编码形式。
源:硬盘,输入流。
数据:纯文本,字符输入流,Read。
该用哪个对象呢?
因为是文件FileReader为了提高效率BufferedReader.
目的:本地文件(硬盘)输出流。
处理的数据:纯文本,字符输出流。Writer。
该用该体系的哪个对象呢?
可以操作的文件的对象,但是因为要将字符数据进行编码在进行存储,就需要使用字符向字节过滤的桥梁。OutputStreamWriter.
就要使用转换流。而转换流要接收的对象都是字节流对象。所以要使用的可以操作的File的FileOutputStream。
为了提高写入流的效率。BufferedWriter.
public void show()
{
BufferedReader bufr = new BufferedReader(new FileReader("a.txt));
BufferedWriter bufw =
new BufferedWriter(new OutputStreamWriter(new FileOutputStream("b.txt"),"UTF-8"));
}
-----------------------------
异常日志。
printStackTrace(PrintStream );
try
{
int[] arr = new int[2];
System.out.println(arr[3]);
}
catch(Exception e)
{
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(d);
try
{
PrintStream out = new PrintStream("exception.log");
e.printStackTrace(out);
out.close();
}
catch(IOException e)
{
throw new RuntimeException("日志建立失败");
}
}