您的位置:首页 > 职场人生

黑马程序员-----Java基础(IO(一))

2015-09-13 15:45 489 查看
——- android培训java培训、期待与您交流! ———-

IO流

1)流按操作数据分为两种:字节流和字符流。

2)流按流向分为:输入流和输出流。

3)字节流的抽象基流:InputStream和OutputStream

4)字符流的抽象基流:Reader和Writer

tip:此四个类派生出来的子类名称都是以父类名作为子类名的后缀,以前缀为其功能;如Reader子类FileReader

字符流

读写

1,创建一个FileWriter对象,该对象一被初始化,就必须要明确被操作的文件。(文件的数据的续写是通过构造函数 FileWriter(Strings,boolean append),在创建对象时,传递一个true参数,代表不覆盖已有的文件。)

2,调用write(String s)方法,将字符串写入到流中。

3,调用flush()方法,刷新该流的缓冲,将数据刷新到目的地中。

4,调用close()方法,关闭流资源。但是关闭前会刷新一次内部的缓冲数据,并将数据刷新到目的地中。(java自身不能写入数据,而是调用系统内部方式完成数据的书写,使用系统资源后,一定要关闭资源。)

读写步骤相似。

缓冲区

1,提高了流的读写效率,所以在缓冲区创建前,要先创建流对象。即先将流对象初始化到构造函数中。

2,缓冲技术原理:此对象中封装了数组,将数据存入,再一次性取出。

3,缓冲区步骤:

1)创建一个字符写入流对象。

FileWriter fw=newFileWriter(“buf.txt”);

2)只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。

BufferedWriter bufw =new BufferedWriter(fw);

3)调用write方法写入数据到指定文件

bufw.write(“adfg”);

4)BufferedWriter缓冲区中提供了一个跨平台的换行符:

bifw.ewLine();

为了排除意外事故,保证数据存在,建议写入一次就刷新一次)

bufw.flush();

5其实关闭缓冲区,就是在关闭缓冲区中的流对象。

bufw.close();

4、读取流缓冲区BufferedReader

该缓冲区提供了一个一次读一行的方法readLine,方便于堆文本数据的获取,当返回null时表示读到文件末尾。readLine方法返回的时候,只返回回车符之前的数据内容。并不返回回车符。

readLine方法原理:

无论是读一行。或者读取多个字符。其实最终都是在在硬盘上一个一个读取。所以最终使用的还是read方法一次读一个的方法。

代码记录:

/**
* 通过缓冲区复制一个.java文件
*/
BufferedWriter bw = null;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("D:\\Java. Workplaces"
+ "\\exam\\src\\com\\itheima\\BufferedWriterDemo.java"));
bw = new BufferedWriter(new FileWriter("Hello World副本2.txt"));
bw.write("//Copy_BufferedWriterDemo.java");
bw.newLine();
bw.flush();
String value = null;
while ( (value = br.readLine()) != null) {
bw.write(value);
bw.newLine();
bw.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null ) {
br.close();
}
if (bw !=null ) {
bw.close();
}
System.out.println("bingo!");
} catch (IOException e) {
e.printStackTrace();
}
}


自定义BufferedReader:根据BufferedReader类中特有一行一行读取方法readLine()的原理,自定义一个类中包含相同功能的方法

步骤:

a、初始化自定义的类,加入流对象。

b、定义一个临时容器,原BufferedReader封装的是字符数组,此类中可定义一个StringBuilder的容器,最终可实现字符串的提取。

代码实现:

/**
* 装饰设计模式:
* 当想要对已有的对象进行功能增强时,
* 可以定义类,将已有对象传入,基于已有的功能,并提供增强功能
* 那么自定义的类称谓装饰类
* 装饰类通常会通过构造方法接收被装饰对象
* 并基于被装饰对象的功能,提供更强的功能
*/
class MyBufferedRader{
private FileReader fr;
public MyBufferedRader(FileReader fr){
this.fr = fr;
}
//可以一次读一行的方法
public String myreadline() throws IOException {
//定义一个临时容器,原BufferedReader封装的字符数组
StringBuilder sb = new StringBuilder();
int len = 0;
while (( len = fr.read()) != -1) {
if ( len == '\r')
continue;
if ( len == '\n')
return sb.toString();
else
sb.append((char)len);
}
if ( sb.length() != 0)
return sb.toString();
return null;
}

public void mycloese() throws IOException {
fr.close();
}
}


6、LineNumberReader

在BufferedReader中有个直接的子类LineNumberReader:

setLineNumber();//设置初始行号

getLineNumber();//获取行号

代码记录:

LineNumberReader lnr = null;
try {
lnr = new LineNumberReader(new FileReader("Hello World副本2.txt"));
String line = null;
lnr.setLineNumber(40);//设置行号,从41开始
while ((line = lnr.readLine()) != null) {
//              System.out.println(line);//不带行号
System.out.println(lnr.getLineNumber()+":"+line);//getLineNumber() 获得行号<
4000
/span>
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if ( lnr != null)
lnr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


字节流

字节流与字符流大体相同,但是字节流还可以操作其他媒体文件,如图片等。

代码记录:

/**
* 字节流
* 复制一张图片
* 思路:
* 输入流与图片关联,输出流指定目的地
* 通过读写循环,完成复制
* 关闭流
*/
public class CopyPic {

public static void main(String[] args) {

FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("1.bmp");
fos = new FileOutputStream("1副本.bmp");
byte[] cbuf = new byte[1024];
int len = 0;
while ( (len = fis.read(cbuf)) != -1){
fos.write(cbuf, 0, len);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
if (fos != null)
fos.close();
System.out.println("bingo!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}


二、字节流缓冲区

1、读写特点:

read():会将字节byte型值提升为int型值

write():会将int型强转为byte型,即保留二进制数的最后八位。 2、原理:将数据拷贝一部分,读取一部分,循环,直到数据全部读取完毕。

1)先从数据中抓取固定数组长度的字节,存入定义的数组中,再通过然后再通过read()方法读取数组中的元素,存入缓冲区。

2)循环这个动作,直到最后取出一组数据存入数组,可能数组并未填满,同样也取出包含的元素。

3)每次取出的时候,都有一个指针在移动,取到数组结尾就自动回到数组头部,这样指针在自增。

4)取出的时候,数组中的元素在减少,取出一个,就减少一个,直到减到0即元素取完。

5)当文件中的全部数据都被读取出时,read()方法就返回-1。 3、自定义读取字节流缓冲区

需求:根据字节流缓冲区的原理,自定义一个字节流缓冲区。 注意:

1、字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。

因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。

所以,为了避免这种情况将读到的字节进行int类型的提升。并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。而在写入数据时,只写该int类型数据的最低8位。

2、byte类型的-1提升为int类型时还是-1。原因:因为在bit8个1前面补的全是1导致的。如果在bit8个1前面补0,即可以保留原字节数据不变,又可以避免-1的出现。这时将byte型数据&0xff即255即可。

代码记录:

/**
* 1个字节=8个二进制位
* 1个int类型是32个二进制位
*/
class MyBufferedInputStream {

private InputStream in;
private byte[] buf = new byte[1024];//定义数组
private int pos = 0, count = 0; //定义指针和计数器
public MyBufferedInputStream(InputStream in) {
this.in = in;
}
//自定义个读方法,一次读取一个字节
public int myread() throws IOException {
//通过in读取硬盘中的数据,存放在buf当中
if (count == 0){
//count == 0时,往buf中装数据
count = in.read(buf);
if (count < 0){
return -1;
}
pos = 0;//格式化pos指针
//从buf中取数据
byte b = buf[pos];
count--;
pos++;
return b&255;
/**
* b为byte类型,被int类型接收,提升了
* byte  -1 ----->   int  -1
* byte:     11111111
* int:      11111111 11111111 11111111 11111111
* 补0后的int:00000000 00000000 00000000 11111111   255
* byte提升为int时,在前面补0而不是补1,这样来保留原数据不变,也可避免-1的出现,补0的方法
* byte  11111111
* int   11111111 11111111 11111111 11111111
* &     00000000 00000000 00000000 11111111
* -------------------------------------
* int   00000000 00000000 00000000 11111111
*/

} else if (count > 0){
//count不为0,说明buf中存在数据,只进行取数据操作
byte b = buf[pos];
count--;
pos++;
return b&255;
}
return -1;
}
//关闭流方法
public void myclos() throws IOException {
in.close();
}
}


流操作规律

一)流对象操作规律

明确:

1. 明确源和目的地

输入流 InputStream,reader

目的:输出流 OutputStream,writer

2. 操作的数据是不是纯文本

是:字符流

否:字节流

3. 明确体系后,再明确要使用那个具体的对象

通过设备来进行区分

源设备:内存,键盘,硬盘

目的设备:内存,硬盘(文件),控制台

二)转换流的由来:

a、字符流与字节流之间的桥梁

b、方便了字符流与字节流之间的操作

代码记录:

/**
* 通过键盘录入
* 当录入一行后,打印该行数据
* 输入over,停止录入
* @author 弥尔
*
*/
public class ReadIn {

public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//      myread1();
//      turnstream();
lianxi();
}
/**
* 练习:将一个文本文件打印在控制台
* 写出3个明确
*  1. 明确源和目的地
*      源:输入流       reader
*      目的:输出流  writer
* 2. 操作的数据是不是纯文本
*      是:字符流
* 3. 明确体系后,再明确要使用那个具体的对象
*      通过设备来进行区分
*      源设备:硬盘
*      目的设备:控制台
* @throws IOException
*/
public static void lianxi() throws IOException {
//高效缓冲区,输入流,源文件来自硬盘
BufferedReader br = new BufferedReader(new FileReader("Hello World副本2.txt"));
//高效缓冲区,输出流,目的地为控制台,system.out是字节流输出,需要用转换流,将字符转为字节输出
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while ( (line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
/**
* 转换流
* @throws IOException
*/
public static void turnstream() throws IOException {
System.out.println("123");
//字节流转换为字符流输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//字节流转换为字符流输出
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while ( (line = br.readLine()) != null) {
if ( "over".equalsIgnoreCase(line)) {
break;
}else {
bw.write(line);
bw.newLine();
bw.flush();
}
}
br.close();
bw.close();
}

/**
* 读一行的原理
*/
public static void myread1() {
System.out.println("123");
InputStream in = System.in;
StringBuilder sb = new StringBuilder();
int ch = 0;
while (true) {
try {
ch = in.read();
if (ch=='\r'){
continue;
}else if (ch=='\n'){
String s = sb.toString();
if ("over".equalsIgnoreCase(s)){
break;
}else {
System.out.println(s.toUpperCase());
sb.delete(0, sb.length());
}
}else {
sb.append((char)ch);
}

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}


打印流

代码记录:

package com.itheima;

import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;

public class PrintStreamDemo {

public static void main(String[] args) {

try
9b51
{
int[] arr = new int[2];
System.out.println(arr[4]);
} catch (Exception e) {
PrintStream ps = null;
try {
ps = new PrintStream("exception.log");
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");
String s = sdf.format(d);
ps.println(s);
System.setOut(ps);

} catch (FileNotFoundException e1) {
e1.printStackTrace(ps);
}
e.printStackTrace(ps);
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: