Java基础——IO(1)
来源:互联网 发布:淘宝里的极有家是什么 编辑:程序博客网 时间:2024/06/10 15:31
IO流
概述
Java中采用IO流的方式来进行数据传输,IO流分为两种:
1)字节流的抽象基流:InputStream和OutputStream 2)字符流的抽象基流:Reader和Writer
P.S.
此四个类派生出来的子类名称都是以父类名作为子类名的后缀,以前缀为其功能;如InputStream子类FileInputStream;Reader子类FileReader 记住:如果要操作文字数据,建议优先考虑字符流。 而且要将数据从内存写到硬盘上,要使用字符流中的输出流:Writer。 硬盘的数据基本体现是文件,希望找到一个可以操作文件的Writer:FileWriter
字符流
字符流输入:
用例:
public class Test1 { public static void main(String[] args) throws IOException { File file = new File("d://IO"); if(!file.exists()){ //不存在则创建路径 file.mkdirs(); } FileWriter fw = new FileWriter(file+"/123.txt"); fw.write("你好,字符流输入!"); //刷新缓存到指定文件 fw.flush(); fw.close(); }}
若更改为:FileWriter fw = new FileWriter(file+”/123.txt”,true);
表示: 如果为 true,则将字节写入文件末尾处,而不是写入文件开始处 。
加ture常用来进行文件续写。
字符流输出
1.单个字符读取
public class Test2 { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("d://IO/123.txt"); int c = 0; while((c= fr.read())!=-1){ //这里read的返回值是char值的int型,可以转型为char类型 System.out.print((char)c); } }}
2.字符数组读取
public class Test3 { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("d://IO/123.txt"); char []c = new char[1024]; //返回值是读取的长度 int len = fr.read(c); System.out.println(new String(c, 0, len)); }}
练习:
需求: 将d盘一个文本文件复制到f盘、 复制的原理: 其实就是将c盘下的文件数据存储到e盘的一个文件中。 步骤: 1、在e盘创建一个文件。用于存储c盘文件中的数据。 2、定义读取流和c盘文件关联。 3、通过不断的读写完成数据存储。 4、关闭资源。
/**单字符传输*/public class Test4 { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("D:\\IO\\123.txt"); FileWriter fw = new FileWriter("f:\\copy123.txt"); //单个字符传送 int c ; while((c=fr.read())!=-1){ /**public void write(int c) * c - 指定要写入字符的 int。 */ fw.write(c); } fr.close(); fw.close(); }}
public class Test5 { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("D:\\IO\\123.txt"); FileWriter fw = new FileWriter("f:\\copy123.txt"); // 字符数组传送 char[] c = new char[1024]; String buf = null; int len = 0; while ((len = fr.read(c)) != -1) { buf = new String(c, 0, len); fw.write(buf); } fw.close(); fr.close(); }}
字符流的缓冲区——BufferedReader和BufferedWriter
使用注意:
1.使用缓冲区技术是为了解决性能问题,提高效率2.需要先建立流对象,再将流对象交给缓冲区构造函数去处理3. 记住,只要用到缓冲区,就要记得刷新。(关闭流同样会刷新,但为了排除意外事故,保证数据存在,建议写入一次就刷新一次) 如:bufw.flush();4.小知识:BufferedWriter缓冲区中提供了一个跨平台的换行符:newLine();可以在不同操作系统上调用,用作数据换行。 如:bufw.newLine();5.读取流缓冲区BufferedReader BufferedReader.readLine():另外开辟了一个缓冲区,存储的是原缓冲区一行的数据,不包含换行符。所以实际使用中常使用BufferedReader.newLine();方法换行
练习:使用字符缓冲区复制文本
public class Test6 { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("D:\\IO\\Hello.java")); BufferedWriter bw = new BufferedWriter(new FileWriter("f:\\CopyHello.java")); String buf = null; while((buf = br.readLine())!=null){ bw.write(buf); //添加换行,否则输出文本没有格式 bw.newLine(); // //使用缓冲区的刷新方法将数据刷目的地中 } bw.close(); br.close(); }}
练习:模仿一个BufferedReader的readLine方法
/*需求:根据readLine方法原理,模拟BufferedReader写一个自己的MyBufferedReader*/import java.io.*;//自定义缓冲类class MyBufferedReader extends Reader{ private Reader r;//定义接收的流对象 MyBufferedReader(Reader r) { this.r=r; } //自定义整行读取 public String myReadLine()throws IOException { //创建一个容器,用来存储一行的字符 StringBuilder sb =new StringBuilder(); //一个字符一个字符读取 for (int ch=0;(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; } //复写父类中的抽象方法 public int read(char[] cbuf, int off, int len) throws IOException { return r.read(cbuf,off,len); } //复写父类的close方法 public void close()throws IOException { r.close(); }}//测试MyBufferedReaderpublic class Test7{ public static void main(String[] args) { MyBufferedReader mbr=null; try { mbr=new MyBufferedReader(new FileReader("D:\\IO\\Hello.java")); for (String line=null;(line=mbr.myReadLine())!=null ; ) { System.out.println(line);//显示效果 } } catch (IOException e) { throw new RuntimeException("读取数据失败"); } finally { try { if(mbr!=null) mbr.close(); } catch (IOException e) { throw new RuntimeException("读取流关闭失败"); } } }}
LineNumberReader
此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。 换行符('\n')、回车符('\r')
/*需求:利用LineNumberReader的特有方法去设置和获取文件中数据的行号*/public class Test8 { public static void main(String[] args) { LineNumberReader lnr = null; try { // 将读取流对象传入 lnr = new LineNumberReader(new FileReader("D:\\IO\\Hello.java")); lnr.setLineNumber(10);// 设置开始行号 for (String line = null; (line = lnr.readLine()) != null;) { System.out.println(lnr.getLineNumber() + ":" + line);// 打印每行行号和字符 } } catch (IOException e) { throw new RuntimeException("读取数据失败"); } finally { try { if (lnr != null) lnr.close(); } catch (IOException e) { throw new RuntimeException("读取流关闭失败"); } } }}
装饰设计模式
通过多态进行一个功能的增强,不要仅仅使用继承,而应多使用多态。
字节流
1.基本操作与字符流类相同。但它不仅可以操作字符,还可以操作其他媒体文件。2.由于媒体文件数据中都是以字节存储的,所以,字节流对象可直接对媒体文件的数据写入到文件中,而可以不用再进行刷流动作。3.读写字节流:InputStream 输入流(读) OutputStream 输出流(写)
练习:复制图片等媒体资源
public class Test1 { public static void main(String[] args) throws IOException { InputStream in = new FileInputStream("d:\\IO\\ME.JPG"); OutputStream out = new FileOutputStream("f:\\CopyME.JPG"); /** * 另种写法:不推荐 * byte []b= new byte[in.available()]; * 若in.available()值过大,会导致内存溢出 * p.s. * in.available():返回文件中的字节个数 */ // 推荐写法,自定义字符缓冲区 byte[] b = new byte[1024]; int len = 0; while ((len = in.read(b)) != -1) { out.write(b, 0, len); } out.close(); in.close(); }}
字节流缓冲区
练习:自定义字节流读取缓冲区
/* 自定义字节流读取缓冲区 思路: 1、定义一个固定长度的数组 2、定义一个指针和计数器用于读取数组长度,和计数数组元素是否取完为0 3、每次将字节数据存入元素要先将数组中的元素取完 */ /*自定义字节流读取缓冲区思路:1、定义一个固定长度的数组2、定义一个指针和计数器用于读取数组长度,和计数数组元素是否取完为03、每次将字节数据存入元素要先将数组中的元素取完*/import java.io.*;class MyBufferedInputStream{ private InputStream in; private byte[] by=new byte[1024]; private int count=0,pos=0; MyBufferedInputStream(InputStream in) { this.in=in; } //自定义读方法,一次读一个字节 public int myRead()throws IOException { //通过in对象读取硬盘上数据,并存储by中。 //存储在数组中的数据被读取完,再通过in对象从硬盘上读取数据 if(count==0) { count=in.read(by); if(count<0)//文件数据全部被读取出来了 return -1; pos=0;//初始化指针 byte b=by[pos]; count--;//每被读一个字节,表示数组中的字节数少一个 pos++;//指针加1 return b&255;//返回的byte类型提升为int类型,字节数增加,且高24位被补1,原字节数据改变。 //通过与上255,主动将byte类型提升为int类型,将高24位补0,原字节数据不变。 //而在输出字节流写入数据时,只写该int类型数据的最低8位。 } else if(count>0)//如果数组中的数据没被读取完,则继续读取 { byte b=by[pos]; count--; pos++; return b&0xff; } return -1; } //自定义关闭资源方法 public void close()throws IOException { in.close(); }}//测试自定义输入字节流缓冲区public class Test2{ public static void main(String[] args) { long start=System.currentTimeMillis(); //利用字节流的缓冲区进行复制 copy_2(); long end=System.currentTimeMillis(); System.out.println("复制共用时:"+(end-start)+"毫秒"); } //使用字节流的缓冲区进行复制 public static void copy_2() { BufferedOutputStream bout=null; MyBufferedInputStream bin=null; try { //关联复制文件输入流对象到缓冲区 bin=new MyBufferedInputStream(new FileInputStream("d:\\IO\\ME.JPG")); //指定文件粘贴位置的输出流对象到缓冲区 bout=new BufferedOutputStream(new FileOutputStream("f:\\CopyME.JPG")); int by=0; while((by=bin.myRead())!=-1) { bout.write(by);//将缓冲区中的数据写入指定文件中 } } catch(IOException e) { throw new RuntimeException("MP3复制失败"); } finally { try { if(bin!=null) bin.close();//关闭输入字节流 } catch(IOException e) { throw new RuntimeException("读取字节流关闭失败"); } try { if(bout!=null) bout.close();//关闭输出字节流 } catch(IOException e) { throw new RuntimeException("写入字节流关闭失败"); } } }}
流操作
键盘录入
一、键盘录入
1.标准输入输出流
System.in:对应的标准输入设备,键盘。 Ssytem.out:对应的是标准的输出设备,控制台。 System.in的类型是InputStream. System.out的类型是PrintStream是OutputStream的子类FilterOutputStream的子类。
2.改进
由于键盘录入是字节流,效率较低。可不可以使用整行读取,那么需要借助readLine方法,但是这个是字符流的方法。所以,需要将字节流转换成字符流。 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
练习:
/** * 需求:将键盘录入的数据转换成大写输出,显示在控制台,当输入over时,表示结束 源:键盘录入。 目的:控制台。 */public class Test1 { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); String s = null; while((s = br.readLine())!=null){ if(s.equals("over")) break; bw.write(s.toUpperCase()); bw.flush(); } }}
练习:
/** * 需求:想把键盘录入的数据存储到一个文件中。 * 源:键盘 * 目的:文件 * 把录入的数据按照指定的编码表(UTF-8),将数据存到文件中。 * 需求:想要将一个文件的数据打印在控制台上。 * 源:文件 * 目的:控制台 */public class Test2 { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new FileWriter("f:\\MyTest.txt")); String s = null; while((s = br.readLine())!=null){ if(s.equals("over")) break; bw.write(s); bw.flush(); bw.newLine(); } bw.close(); br.close(); }}
流的操作规律
1、
源:键盘录入。 目的:控制台。
2、需求:想把键盘录入的数据存储到一个文件中。
源:键盘 目的:文件。 使用字节流通向字符流的转换流(桥梁):InputStreamReader
3、需求:想要将一个文件的数据打印在控制台上。
源:文件 目的:控制台 使用字符流通向字节流的转换流(桥梁):OutputStreamWriter
4、流操作的基本规律:
最痛苦的就是流对象有很多,不知道该用哪一个。
通过三个明确来完成:
4.1 明确源和目的。
源:输入流。InputStream Reader 目的:输出流。OutputStream Writer
4.2 操作的数据是否是纯文本。
是:字符流 否:字节流
4.3 当体系明确后,再明确要使用哪个具体的对象。通过设备来进行区分:
源设备:内存,硬盘,键盘 目的设备:内存,硬盘,控制台
5、规律体现
5.1 将一个文本文件中数据存储到另一个文件中。复制文件。
1)源:因为是源,所以使用读取流:InputStream和Reader 明确体系:是否操作文本:是,Reader 明确设备:明确要使用该体系中的哪个对象:硬盘上的一个文件。Reader体系中可以操作文件的对象是FileReader 是否需要提高效率:是,加入Reader体系中缓冲区 BufferedReader. FileReader fr = new FileReader("a.txt"); BufferedReader bufr = new BufferedReader(fr); 2)目的:输出流:OutputStream和Writer 明确体系:是否操作文本:是,Writer 明确设备:明确要使用该体系中的哪个对象:硬盘上的一个文件。Writer体系中可以操作文件的对象FileWriter。 是否需要提高效率:是,加入Writer体系中缓冲区 BufferedWriter FileWriter fw = new FileWriter("b.txt"); BufferedWriter bufw = new BufferedWriter(fw);
练习:将一个图片文件中数据存储到另一个文件中。复制文件。要按照以上格式自己完成三个明确。
1)源:输入流,InputStream和Reader 是否是文本?否,InputStream 源设备:硬盘上的一个文件。InputSteam体系中可以操作文件的对象是FileInputSteam 是否需要提供效率:是,BufferedInputStream BufferedInputSteambis=newBufferedInputStream(newFileInputStream("c:/users/asus/desktop/1.jpg")); 2)目的:输出流,OutputStream和Writer 是否是文本?否,OutputStream 源设备:硬盘上的文件,FileOutputStream 是否需要提高效率:是,加入BufferedOutputStream BufferedOutputStreambos=newBufferedOutputStream(newFileOutputStream("c:/users/asus/desktop/2.jpg"));
5.2 需求:将键盘录入的数据保存到一个文件中。
1)源:InputStream和Reader 是不是纯文本?是,Reader 设备:键盘。对应的对象是System.in。——为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。所以既然明确了Reader,那么就将System.in转换成Reader。用Reader体系中转换流,InputStreamReader InputStreamReaderisr = new InputStreamReader(System.in); 需要提高效率吗?需要,BufferedReader BufferedReaderbufr = new BufferedReader(isr); 2)目的:OutputStream Writer 是否是存文本?是!Writer。 设备:硬盘。一个文件。使用 FileWriter。 FileWriter fw = newFileWriter("c.txt"); 需要提高效率吗?需要。 BufferedWriter bufw = new BufferedWriter(fw);
5.3 扩展:想要把录入的数据按照指定的编码表(UTF-8)(默认编码表是GBK),将数据存到文件中。
目的:OutputStream Writer 是否是存文本?是!Writer。 设备:硬盘上的一个文件。使用 FileWriter。——但是FileWriter是使用的默认编码表:GBK。而存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。所以要使用的对象是OutputStreamWriter。 该转换流对象要接收一个字节输出流,而且还可以操作的文件的字节输出流:FileOutputStream OutputStreamWriter osw =new OutputStreamWriter(newFileOutputStream("d.txt"),"UTF-8"); 需要高效吗?需要,BufferedWriter BufferedWriter bufw = new BufferedWriter(osw);
记住:
转换流什么使用? 字符和字节之间的桥梁。通常,涉及到字符编码转换时,需要用到转换流。
练习:将一个文本数据打印在控制台上。要按照以上格式自己完成三个明确。
1)源:InputStreamReader 是文本?是:Reader 设备:硬盘。上的文件:FileReader 是否需要提高效率?是:BufferedReader BufferedReader br=new BufferedReader(newFileReader("1.txt")); 2)目的:OutputStream Writer 是文本?是:Writer 设备:控制台。对应对象System.out。由于System.out对应的是字节流,所以利用OutputSteamWriter转换流 是否提高效率?是:BufferedWriter BufferedWriter bw =new BufferedWriter(newOutputStreamWriter(system.out));
练习:带编码的流操作
/** * 带编码集的操作 * @author LQX * */public class Test3 { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in, "UTF-8")); //指定UTF-8编码 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("f://MyTest.java"), "UTF-8"); String s = null; while((s = br.readLine())!=null){ if(s.equals("over")) break; osw.write(s+"\r\n"); osw.flush(); } }}
public class Test4 { public static void main(String[] args) throws IOException { /*BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("f:\\MyTest.java"))); String s = null; while((s = br.readLine())!=null){ System.out.println(s); }*/ //该文件在创建时我指定了编码为UTF-8,所以多出来是乱码 FileReader fr = new FileReader("f:\\MyTest.java"); char []c = new char[1024];/* int len = 0; while((len = fr.read(c))!=-1){ System.out.println(new String(c, 0, len)); }*/ //修改后,设定了编码为UTF-8,能正确读出来 InputStreamReader isr = new InputStreamReader(new FileInputStream("f:\\MyTest.java"), "UTF-8"); int len = 0; while((len = isr.read(c))!=-1){ System.out.println(new String(c, 0, len)); } }}
什么时候使用流转换?
1.目标设备是字节流,但操作是字符流,使用转换流作为桥梁,提高效率。2.涉及文本字符编码表时,必须使用转换流,因为只有它才提供自定义编码。
0 0
- Java基础——IO(1)
- java基础—IO
- java基础—java的Io操作学习(1)
- Java基础——IO(流)
- Java基础——IO(2)
- Java基础—IO流(一)
- Java基础—IO流(二)
- Java基础—IO流(三)
- 黑马程序员——Java基础--IO流(1)
- Java基础——IO
- java基础学习—IO
- Java基础—IO流
- java基础—-IO流
- java基础—IO流
- java基础—IO流
- java学习——java基础(七)之 IO
- Java基础——Java IO详解
- java基础—java的Io操作学习(2)
- Hadoop系列三:运行job过程日志
- URAL 1723 Sandro's Book
- Android中对话框的用法(单选,多选,确定,取消)
- Java中?:这个是什么意思
- 设计模式:Android AlertDialog的builder(建造者模式)
- Java基础——IO(1)
- 信息学奥林匹克竞赛-小玉学游泳
- Ajax简述
- 解决用easygui是出现Attribute: 'module' object has no attribute 'msgbox'
- cJSON库如何在KIEL4上使用?
- Linux命令缩写来由
- easyUI对列表的增、删、改、查例子。
- REPEATABLE-READ 预读
- confluence安装破解