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

黑马程序员——java学习日记六

2015-10-22 18:25 513 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一、IO流简介

 1 IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式,把用于操纵流的对象都放在IO包中。

流按操作数据分为两种:字节流和字符流。流按流向分为:输入流和输出流。

 2 IO流常用基类:字节流的抽象基类InputStream,OutputStream。字符流的抽象基类:Reader,Writer。由这四个类派生出来的子类名称都是以其父类名作为子类目的后缀。如:InputStream的子类FileInputStream,Reader的子类FileReader

二、字符流

1 用字符流操作文本文件:

需求:在硬盘上,创建一个文件并写入一些文字数据。
查阅文档找到一个专门用于操作文件的Writer子类对象------FileWriter。

//创建一个FileWriter对象。构造函数中需要传入写入文件名。
//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
//其实该步就是在明确数据要存放的目的地。
FileWriter fw = new FileWriter("demo.txt");

//调用write方法,将字符串写入到流中。(将内容写入到了缓冲区里面)
fw.write("hello world");

//刷新流对象中的缓冲中的数据。
//将数据刷到目的地中。
fw.flush();

//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
//将数据刷到目的地中。
//和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
fw.close();
2 IO异常的处理方式
class Demo{
public static void main(String[] args)
{
FileWriter fw = null;
try
{
fw = new FileWriter("demo.txt");//构造函数抛出异常
fw.write("abcdefg");
}
catch(IOException randname)//存储路径不合法
{
System.out.println("catch:"+randname.toString());
}
finally
{
try
{
if(fw!=null)//判断写入流对象是否为空
fw.colse();
}
catch(IOException e)
{
System.out.println(e.toString());
}
}
}
3 文件的续写

在FileWriter(String fileName,boolean append)构造函数中传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写:
FileWriter fw = new FileWriter("demo.txt",true);

4 文件读取

FileReader用来读取字符文件,此类的构造函数假定采用默认字符编码和默认字节缓冲区大小。
//创建一个文件读取流对象,打开指定文件。
//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
FileReader fr = new FileReader("FileReaderDemo.java");

//调用读取流对象的read方法。
//read():一次读取一个字符。而且会自动往下读。----才发现这和C语言好像 是getchar()的翻版
int ch = 0;
while((ch=fr.read())!=-1)//作为整数读取的字符,范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1
{
System.out.println("ch="+(char)ch);
}

fr.close();

//----------------------------------*************************-----------------------------------------

//定义一个字符数组。用于存储读到字符。
//该read(char[])返回的是读到字符个数,若读到文件末尾则返回-1
char[] buf = new char[1024];

int num = 0;
while((num=fr.read(buf))!=-1)
{
System.out.println(new String(buf,0,num));
}

//----------------------------------*************************-----------------------------------------
/*
需求:复制文本文件
复制的原理:
其实就是将C盘下的文件数据存储到f盘的一个文件中。

步骤:
1,在D盘创建一个文件。用于存储C盘文件中的数据。
2,定义读取流和C盘文件关联。
3,通过不断的读写完成数据存储。
4,关闭资源。
*/

//创建目的地。
FileWriter fw = new FileWriter("RuntimeDemo_copy.txt");

//与已有文件关联。
FileReader fr = new FileReader("RuntimeDemo.java");

int ch = 0;
while((ch=fr.read())!=-1)
{
fw.write(ch);
}

/*
方式二
char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1)
{
fw.write(buf,0,len);
}
*/

fw.close();
fr.close();


5 字符流的缓冲技术

缓冲区的出现提高了对数据的读写效率。对应类:BufferedWriter  BufferedReader

缓冲区要结合流才可以使用,在流的基础上对流的功能进行了增强。
//创建一个写入流对象
FileWriter fw = new FileWriter("buf.txt");

//将写入流对象传递给增强对象
BufferedWriter bufw = new BufferedWriter(fw);

for(int x=1; x<5; x++)
{
bufw.write("helloworld"+x);
//增添换行
bufw.newLine();
bufw.flush();
}

//**只要用到缓冲区,就要记得刷新
//bufw.flush();

//其实关闭缓冲区,就是在关闭缓冲区中的流对象。
bufw.close();

----------------------------------*************************-----------------------------------------
/*
字符读取流缓冲区:
该缓冲类提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。
当返回null时,表示读到文件末尾。

readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。
*/
//创建一个读取流对象和文件相关联。
FileReader fr = new FileReader("buf.txt");

//为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。
BufferedReader bufr = new BufferedReader(fr);

String line = null;

while((line=bufr.readLine())!=null)
{
System.out.print(line);
}

bufr.close();
6 装饰设计模式

当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的类成为装饰类。

装饰与继承的区别:

通过继承将每一个子类都具备某些功能那么继承体系会变得复杂和臃肿,不利于扩展于是进行优化,单独描述一下某些功能的内容,将需要被缓冲的对象,传递进来,也就是,谁需要被缓冲,谁就作为参数传递给缓冲区,这样继承体系就变得很简单,优化了体系结构。
//自定义一个类来模拟BufferedReader

import java.io.*;

class MyBufferedReader extends Reader
{
private Reader r;//封装一个字符读取流

MyBufferedReader(Reader r)
{
this.r = r;
}

public String myReadLine()throws IOException
{
//定义一个临时容器 原BufferReader封装的是字符数组。
//我们自定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
StringBuilder sb = new StringBuilder();

int ch =0;
while((ch=r.read())!=-1) //读取一个字符
{
if(ch=='\r')         //判断是否为回车符
continue;
if(ch=='\n')         //判断是否为换行符
return sb.toString();返回结果
else
sb.append((char)ch);//将字符添加进缓冲区中
}

//如果文件中没有换行
if(sb.length()!=0)
return sb.toString();
return null;
}

/*
覆盖Reader类中的抽象方法。
*/
public int read(char[] cbuf, int off, int len) throws IOException
{
return r.read(cbuf,off,len) ;//调用被修饰对象
}

public void myClose()throws IOException
{
r.close();
}
}

----------------------------------*************************-----------------------------------------
//一个带行号
4000
的缓冲区对象。
class LineNumberReaderDemo
{
public static void main(String[] args)throws IOException
{
FileReader fr = new FileReader("CopyMp3.java");//创建一个文件字符读取流对象

LineNumberReader lnr = new LineNumberReader(fr);//创建一个装饰对象

String line = null;
lnr.setLineNumber(100);                        //将行号起点设置为100
while((line=lnr.readLine())!=null)             //读取一行判读是否为空
{
System.out.println(lnr.getLineNumber()+":"+line);//输出行号和内容
}

lnr.close();
}
}


三、字节流

字节流用于操作二进制文件,比如图片文件,音乐文件,等等。
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[fis.available()];//定义一个刚刚好的缓冲区。

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();

}
}

----------------------------------*************************-----------------------------------------
/*
复制一个图片
思路:
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("F:\\a\\2.txt");//目的
fis = new FileInputStream("F:\\1.txt");//源

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
*/
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("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();

}
}


四、读取键盘录入

System.out:对应的是标准输出设备,控制台。

System.in:对应的标准输入设备:键盘。

需求:

通过键盘录入数据。

当录入一行数据后,就将该行数据进行打印。

如果录入的数据是over,那么停止录入。

思路:

1 创建一个输入流与标准输入流关联

2 创建一个字符缓冲区

循环:

3 读取一个字符

  如果该字符是普通字符

  则将该字符加到字符缓冲区中

  如果该字符是'/r'

  继续循环读取下一个字符

  如果该字符是'/n'

  取出字符缓冲区中的字符串

  判断该字符串是否是"over"

  如果是终止循环

  如果不是 打印该字符串 将字符缓冲区清空delete(0,s.length())
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();//read()方法是阻塞式方法
if(ch == '\r')
continue;
if(ch == '\n')
{
String s = sb.toString();
if(s.equals("over"))
break;
System.out.println(s);
sb.delete(0,sb.length());
}
else
sb.append((char)ch);
}
}
}


五、转换流

InputStreamReader 是字节流通向字符流的桥梁,它使用指定的字符集读取字节并将其解码为字符。为了提高读取效率,可以考虑在 BufferedReader 内包InputStreamReader。BufferedReader in = new BufferedReader(newInputStreamReader(System.in)); 

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符集 将要写入流中的字符编码成字节。提高写入效率可采取将 OutputStreamWriter 包装到 BufferedWriter 中以避免频繁调用转换器 Writer out = new BufferedWriter(new OutputStreamWriter(System.out));

class  TransStreamDemo
{
public static void main(String[] args) throws IOException
{

//键盘录入的最常见写法
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

//标准输出
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

String line = null;

while((line=bufr.readLine())!=null)//读取键盘的一行输入
{
if("over".equals(line))//如果输入等于over则终止输出
break;
bufw.write(line);//用父类的方法read()
bufw.newLine();//增加换行符
bufw.flush();//刷新缓冲区
}

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