java从入门到精通第11章_《Java从入门到精通》第十二章学习笔记

第12章  输入和输出

一、流概述

流是指一组有序的数据序列,数据源和输出目标可以是文件,网络,压缩包或其他。

二、输入/输出流

所有输入流都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类;所有输出流都是抽象类OutputStream(字节输出流)和抽象类Writer(字符输出流)的子类。

1、输入流

InputStream是所有字节输入流的父类,该类主要方法如下,方法出现错误时候会引发IOException异常。

(1)read():从输入流中读取数据的下一个字节,返回0~255之间的int字节值,如果已到末尾,返回-1.

(2)read(byte[] b):从输入流中读入一定长度的字节,并以整数形式返回字节数。

(3)close():关闭此输入流并释放与该数据流关联的所有系统资源。

Java中的字符是Unicode编码,为双字节,而InputStream类处理的是字节流,一般在Java中用Reader类处理字符文本。

2、输出流

OutputStream是所有字节输出流的父类,主要方法如下:

(1)write(int b):将指定的字节写入此输出流。

(2)write(byte[] b):将b.length个字节从指定的byte数组写入流

(3)close():关闭输出流。

三、File类

1、文件的创建与删除

(1)File(String pathname):参数作为路径名创建一个新File实例。

(2)File(String parent,String child):参数分别作为父路径和子路径,创建一个新File实例。

(3)File(File f,String child):f作为父路径对象,child作为子路径字符串。

1 //项目中创建FileTest类,判断D盘的mywork文件夹是否存在work.txt2 //如果存在则删除,如果不存在则创建

3 importjava.io.File;4 public classFileTest {5

6 public static voidmain(String[] args) {7 File file=new File("D:/myword","test.txt");//创建文件对象

8 if(file.exists()){9 file.delete();10 System.out.println("文件已删除");11 }else{12 try{13 file.createNewFile();14 System.out.println("文件已创建");15 }catch(Exception e){16 e.printStackTrace();17 }18 }19 }20 }

2、获取文件信息

File类获取文件本身信息的方法主要包括:

(1)getName():获取文件的名称。

(2)canRead():判断文件是否可读

(3)canWrite():判断文件是否可写入

(4)exists():判断文件是否存在

(5)length():获取文件以字节为单位的长度

(6)getAbsolutePath():获取文件的绝对路径

(7)getParent():获取文件的父路径

(8)isFile():判断文件是否存在(判断对象是否是一个文件?)

(9)isDirectory():判断对象是否是一个目录

(10)isHidden():判断对象是否是隐藏文件

(11)lastMOdified():获取文件最后修改时间

importjava.io.File;public classFileTest {public static voidmain(String[] args) {

File file=new File("D:/myword","test.txt");//创建文件对象

if(file.exists()){

String name=file.getName(); //获取文件名称

long length=file.length(); //获取文件长度

boolean hidden=file.isHidden(); //判断文件是否隐藏

System.out.println("文件名称为:"+name);

System.out.println("文件长度为:"+length);

System.out.println("文件是隐藏文件吗?"+hidden);

}else{

System.out.println("文件不存在!");

}

}

}

//通过renameTo()重命名文件

importjava.io.File;public classFileTest {public static voidmain(String[] args) {

File file=new File("D:/myword","test.txt");//创建文件对象

if(file.exists()){

System.out.println("文件名称为:"+file.getName());//获取文件名称

System.out.println("文件长度为:"+file.length());//获取文件长度

System.out.println("文件是隐藏文件吗?"+file.isHidden());//判断文件是否隐藏

}else{

System.out.println("文件不存在!");

}

File file1=new File("D:/myword","testhaha.txt");if(file1.exists()){

System.out.println("已存在"+file1.getName()+"文件,无法重命名!!");

}else{

file.renameTo(file1);

System.out.println(file.getName()+"文件名称已修改为"+file1.getName());

}

}

}

四、文件输入、输出流

1、如果需要将数据永久保存,可使用FileInputStream和FileOutputStream类与文件建立连接,将需要的数据永久保存到文件里。

FileInputStream是InputStream抽象类的实现类,FileOutputStream是OutputStream抽象类的实现类。

1 //使用FileOutputStream类向文件work写入信息2 //然后通过FileinputStream类将work文件中的数据读取到控制台中

3 import java.io.*;4 public classFileTest {5 public static voidmain(String[] args){6 File file=new File("F:\\...\\STUDY\\lab\\java","work.txt"); //创建文件对象

7 try{8 FileOutputStream out=new FileOutputStream(file); //创建FileOutputStream对象

9 byte bx[]=" tslvcj ".getBytes(); //创建字节型数组

10 out.write(bx); //将数组中信息写入文件

11 out.close(); //关闭输出流

12 }catch(Exception e){13 e.printStackTrace();14 }15 try{16 FileInputStream in=newFileInputStream(file);17 byte by[]=new byte[1024];18 int len=in.read(by); //将文件中字节流数据读取入数组

19 System.out.println("文件中信息是:"+new String(by,0,len));20 in.close();21 }catch(Exception e){22 e.printStackTrace();23 }24

25 }26

27 }

2、FileInputStream和FileOutputStream是针对字节流文件的类,如果对于非单字节编码的文件,可能会出现乱码,一般对字符流文件采用FileReader和FileWriter类。

1 import java.io.*;2 public classFileRwTest {3

4 public static voidmain(String[] args) {5 File file=new File("F:\\霜\\STUDY\\lab\\java","work.txt");6 try{7 FileWriter fwr=newFileWriter(file);8 fwr.write("ilc!");9 fwr.close();10 }catch(Exception e){11 e.printStackTrace();12 }13 try{14 FileReader fr=newFileReader(file);15 char mystr[]=new char[1024];16 int len=fr.read(mystr);17 System.out.println("文件中信息为:"+new String(mystr,0,len));18 fr.close();19 }catch(Exception e){20 e.printStackTrace();21 }22 System.out.println("文件名称为:"+file.getName());23 System.out.println("文件长度为:"+file.length()+"Bytes");24 System.out.println("文件是否隐藏:"+file.isHidden());25 }26 }

1 import java.io.*;2 public classFileTest {3 //显示某一文件类下所有文件的名称

4 public voidshowFileName(File file){5 if(!file.exists()){6 System.out.println("文件不存在!");7 }else{8 if(file.isFile()){9 System.out.println(file.getName());10 }else{11 File[] fd=file.listFiles();12 for(File fx:fd){13 showFileName(fx);14 }15 }16 }17 }18 public static voidmain(String[] args){19 FileTest ft=newFileTest();20 File file=new File("E:\\lab");21 ft.showFileName(file);22 }23 }

1 //删除指定文件或文件夹

2 import java.io.*;3 public classDelFile {4 public voiddelF(File file){5 if(!file.exists()){6 System.out.println("文件不存在!");7 }else{8 if(file.isFile()){9 System.out.println("文件"+file.getName()+"已删除!");10 file.delete();11 }else{12 File[] fa=file.listFiles();13 for(File fx:fa){14 delF(fx);15 }16

17 }18 }19 }20 public static voidmain(String[] args){21 DelFile delTest=newDelFile();22 File file=new File("E:\\lab");23 delTest.delF(file);24 }25 }

五、带缓存的输入、输出流

1、BufferedInputStream类可以对任意InputStream类进行带缓存区的包装以达到性能优化,有两种构造函数:

(1)BufferedInputStream(InputStream in):创建了32个字节的缓存流;

(2)BufferedInputStream(InputStream in,int size):按指定大小创建缓存流。

2、BufferedOutputStream类输出信息和向OutputStream类输入信息完全一样,只不过BufferedOutputStream通过flush()方法强制将缓存区的数据输出结束。其有两种构造方法:

(1)BufferedOutputStream(OutputStream in):创建一个32个字节的缓存区;

(2)BufferedOutputStream(OutputStream in,int size):按指定大小创建缓存流。

3、BufferedReader类与BufferedWriter类分别继承Reader类和Writer类

*BufferedReader类常用方法如下:

(1)read():读取单个字符;

(2)readLine():读取一个文本行,并将其返回为字符串;若无数据,返回null;

(3)writ(String s,int off,int len):写入字符串的某一部分;

(4)flush():刷新该流的缓存。

补充:

一、RandomAccessFile

是java提供的对内容的访问类,可读写操作,顾名思义也可以随机访问文件(即访问文件的任意位置)。

1、Java文件模型:对于Java而言,在硬盘上的文件是byte-byte-byte存储的,是字节数据的集合

2、访问有两种模式:"rw"(读写)、"r"(只读)

RandomAccessFile raf=new RandomAccessFile(file,"rw");

因为随机访问,所以RandomAccessFile类内部含有一个文件指针,第一次打开文件时候指针指向文件开头即pointer=0;随着操作指针会后移。

3、写方法

raf.write(int):只写一个字节(int的后8位),同时指针指向下一个字节位置

4、读取文件

int b=raf.read():读取指针所指的一个字节

5、文件操作完成后一定要关闭

raf.close();

1 importjava.io.File;2 importjava.io.RandomAccessFile;3 importjava.util.Arrays;4

5

6 public classRafDemo {7 public static void main(String[] args) throwsException{8 //创建文件所在目录对应的文件对象

9 File demo=new File("demo");10 if(!demo.exists()){11 demo.mkdir();12 }13 //创建文件对象

14 File file=new File(demo,"raf.dat");15 if(!file.exists()){16 file.createNewFile();17 }18 //创建针对上面文件的文件访问类

19 RandomAccessFile raf=new RandomAccessFile(file,"rw");20 //看一下指针的位置

21 System.out.println(raf.getFilePointer());22

23 raf.write('A');//只写一个字节,A的后8位(低8位)

24 System.out.println(raf.getFilePointer());25 raf.write('B');26

27 //定义一个整数,写入文件28 //但每次只能写一个字节29 //只能通过移位,分别写4词

30 int i=0x7fffffff;31 raf.write(i>>>24);//先写高8位,因为write写的是低8位,所以先右移24位,

32 raf.write(i>>>16);33 raf.write(i>>>8);34 raf.write(i);35 //前面写了6个字节,此时指针指向6

36 System.out.println(raf.getFilePointer());37

38 //可以直接写int型数据

39 raf.writeInt(i);40

41 System.out.println(raf.getFilePointer());42

43 String s="中";44 byte[] gbk=s.getBytes("gbk");45 raf.write(gbk);46 System.out.println(raf.length());47

48 //读文件必须先把指针移动到头部

49 raf.seek(0);50 //一次性读取到字符数组

51 byte[] buf=new byte[(int)raf.length()];52 raf.read(buf);53

54 System.out.println(Arrays.toString(buf));55 for (byteb : buf) {56 System.out.print(Integer.toHexString(b&0xff)+" ");57 }58 //字符数组构造成字符串

59 String s1=newString(buf);60 System.out.println(s1);61 raf.close();62 }63

64 }

二、IO流

分为字节流和字符流

1、字节流

(1)InputStream\OutputStream

InputStream抽象了应用程序读取数据的方式;OutputStream抽象了应用程序写出数据的方式;

(2)达到文件结尾,即EOF=End  读到-1就是读到结尾

(3)输入流基本方法(一般即读出的操作)

int b=in.read();读取一个字节无符号填充到整型b的低8位.读到-1即结尾

in.read(byte[] buf):读取数据填充到字节数组buf中

in.read(byte[] buf,int start,int size):从buf的start位置开始读取size长度的数据到字节数组buf中

(4)输出流基本方法(一般即写入的操作)

out.write(int b):只写一个byte(b的低八位)到out流

out.write(byte[] buf):将buf字节数组写入流

out.write(byte[] buf,int start,int size)

(5)InputStream\OutputStream的子类:FileInputStream和FileOutputStream

FileInputStream具体实现了在文件上读取数据

FileOutputStream具体实现了在文件上写数据

1 importjava.io.File;2 importjava.io.IOException;3 import java.io.*;4

5

6 public classIOUtil {7 /*

8 * 读取指定文件内容,按照16进制输出到控制台9 * 并且每输出10个byte换行10 */

11

12 public static void printHex(String fileName) throwsException{13 //把文件作为字节流进行读操作

14 FileInputStream in=newFileInputStream(fileName);15 intb;16 int i=1;17 while((b=in.read())!=-1){18 if(b<=0xf){19 System.out.print("0");20 }21 System.out.print(Integer.toHexString(b)+" ");22 if(i++%10==0){23 System.out.println();24 }25 }26 System.out.println();27 System.out.println("文件一共有"+i+"个字节!");28 in.close();29 }30

31 }32

33 public classIOUtilTest1 {34

35 public static voidmain(String[] args) {36 try{37 IOUtil.printHex("F:\\IOUtil.java");38 } catch(Exception e) {39 e.printStackTrace();40 }41 }42

43 }

上面程序中用in.read()通过单字节读取文件,对于较大的文件,一般用in.read(byte[] buf,int start,int size)进行批量读取以节约时间。

针对上面的程序,优化如下:

1 public static void printHexByByteArray(String fileName)throwsException{2 FileInputStream in=newFileInputStream(fileName);3 byte[] buf=new byte[20*1024];4 //从in中批量读取字节,放入到buf字节数组中,从第0个位置开始放置,最多放buf.length个字节;返回为读取的个数

5 int bytes=in.read(buf,0,buf.length);6 int j=1;7 for (int i=0;i

18 }

利用FileOutputStream写文件,并完成文件的复制功能。

1 importjava.io.FileInputStream;2 importjava.io.FileOutputStream;3 importjava.io.IOException;4 importjava.io.File;5 public classFileOutDemo1 {6 public static void copyFile(File srcFile,File destFile)throwsIOException{7 if(!srcFile.exists()){8 throw new IllegalArgumentException("文件不存在!");9 }10 if(!srcFile.isFile()){11 throw new IllegalAccessError(srcFile+"不是文件");12 }13 FileInputStream in=newFileInputStream(srcFile);14 FileOutputStream out=newFileOutputStream(destFile);15 byte[] buf=new byte[8*1024];16 intb;17 while((b=in.read(buf,0,buf.length))!=-1){18 out.write(buf,0,b);19 out.flush();//刷新缓冲区

20 }21 in.close();22 out.close();23

24 }25 public static void main(String[] args)throwsIOException{26 File demo=new File("demo");27 if(!demo.exists()){28 demo.mkdir();29 }30 //如果该文件不存在,则直接创建,如果存在删除后创建

31 FileOutputStream out=new FileOutputStream("demo/out.txt");32 out.write('a');33 out.write('b');34 byte[] buf="中国".getBytes("gbk");35 out.write(buf);36 File srcFile=new File("demo/out.txt");37 File outCopy=new File("demo/outCopy.txt");38 copyFile(srcFile,outCopy);39

40

41 }42

43 }

三、DataOutputStream/DataInputStream是对“流”功能的扩展,可以更方便的读取int,long,字符等类型数据

1 import java.io.*;2 public classDosDemo {3 public static void main(String[] args)throwsException{4 String file="demo/dos.txt";5 File demo=new File("demo");6 if(!demo.exists()){7 demo.mkdir();8 }9 //DataOutputStream类的构造函数的参数是FileOutputStream类对象

10 DataOutputStream dos=newDataOutputStream(11 newFileOutputStream(file));12 dos.writeInt(10);13 dos.writeInt(-10);14 dos.writeLong(10);15 dos.writeDouble(10.5);16 dos.writeUTF("中国");17 dos.writeChars("中国");18 dos.close();19 DataInputStream dis=newDataInputStream(20 newFileInputStream(file));21 int i=dis.readInt();22 System.out.println(i);23 i=dis.readInt();24 System.out.println(i);25 long l=dis.readLong();26 System.out.println(l);27 double d=dis.readDouble();28 System.out.println(d);29 String s=dis.readUTF();30 System.out.println(s);31 dis.close();32 }33 }

4、BufferedInputStream/BufferedOutputStream:为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能。

比喻:从应用程序中把数据输出到文件,相当于把一缸水倒入外面的一个水箱

那么:

FileOutputStream类的write()方法相当于一滴一滴倒入;

DataOutputStream类的writeXxx()方法(包括writeInt,writeLong,writeUTF等)相当于一瓢一瓢地倒入;

而BufferOutputStream类的write()方法相当于先一瓢一瓢倒入桶中,再从桶中倒入水箱。

下面是通过不同IO流类的复制文件方法所耗时的对比:

/*利用带缓冲的字节流类

* 进行文件的复制*/

import java.io.*;public classCopyFile {//Buffered流操作

public static void copyFileByBuffer(File srcFile,File destFile)throwsException{if(!srcFile.exists()){throw new IllegalArgumentException("文件不存在!");

}if(!srcFile.isFile()){throw new IllegalAccessError(srcFile+"不是文件");

}

BufferedInputStream bis=newBufferedInputStream(newFileInputStream(srcFile));

BufferedOutputStream bos=newBufferedOutputStream(newFileOutputStream(destFile));intc;while((c=bis.read())!=-1){

bos.write(c);

bos.flush();

}

bis.close();

bos.close();

}//单字节流操作

public static void copyFileByByte(File srcFile,File destFile)throwsException{if(!srcFile.exists()){throw new IllegalArgumentException("文件不存在!");

}if(!srcFile.isFile()){throw new IllegalAccessError(srcFile+"不是文件");

}

FileInputStream bis=newFileInputStream(srcFile);

FileOutputStream bos=newFileOutputStream(destFile);intc;while((c=bis.read())!=-1){

bos.write(c);

}

bis.close();

bos.close();

}//字节批量操作

public static void copyFileByArray(File srcFile,File destFile)throwsException{if(!srcFile.exists()){throw new IllegalArgumentException("文件不存在!");

}if(!srcFile.isFile()){throw new IllegalAccessError(srcFile+"不是文件");

}

FileInputStream bis=newFileInputStream(srcFile);

FileOutputStream bos=newFileOutputStream(destFile);intc;byte[] ba=new byte[2024*1024];while((c=bis.read(ba,0,ba.length))!=-1){

bos.write(ba,0,ba.length);

}

bis.close();

bos.close();

}//字节流操作

public static void copyFileByData(File srcFile,File destFile)throwsException{if(!srcFile.exists()){throw new IllegalArgumentException("文件不存在!");

}if(!srcFile.isFile()){throw new IllegalAccessError(srcFile+"不是文件");

}

DataInputStream bis=newDataInputStream(newFileInputStream(srcFile));

DataOutputStream bos=newDataOutputStream(newFileOutputStream(destFile));intc;while(bis.available()>0&&(c=bis.read())!=-1){

bos.write(c);

}

bis.close();

bos.close();

}

}importjava.io.File;public classcopyTest {public static void main(String[] args)throwsException {

File demo=new File("demo");if(!demo.exists()){

demo.mkdir();

}

File srcFile=new File("demo/but.wma");

File destFile=new File("demo/c1.wma");

File destFile1=new File("demo/c2.wma");

File destFile2=new File("demo/c3.wma");

File destFile3=new File("demo/c4.wma");long start=System.currentTimeMillis();

CopyFile.copyFileByBuffer(srcFile, destFile);long end=System.currentTimeMillis();

System.out.println("BufferedCopy用了"+(double)(end-start)/1000+"秒!");

start=System.currentTimeMillis();

CopyFile.copyFileByData(srcFile, destFile1);

end=System.currentTimeMillis();

System.out.println("DataCopy用了"+(double)(end-start)/1000+"秒!");

start=System.currentTimeMillis();

CopyFile.copyFileByByte(srcFile, destFile2);

end=System.currentTimeMillis();

System.out.println("ByteCopy用了"+(double)(end-start)/1000+"秒!");

start=System.currentTimeMillis();

CopyFile.copyFileByArray(srcFile, destFile3);

end=System.currentTimeMillis();

System.out.println("ArrayCopy用了"+(double)(end-start)/1000+"秒!");

}

}/*可以看出批量操作的复制时间最短

* 其次是带缓冲流

* Data流包装类和单字节读取时间最慢

* 但也可以看出批量操作的时间比带缓冲流节约时间效果非常明显*/

5、字符流:一次处理一个字符,字符的底层仍然是基本的字节序列。一般操作的都是文本和文本文件。

1、InputStreamRead:完成byte流解析为char流,按照编码解析。

OutputStreamWriter:提供char流到byte流,按照编码解析。

1 import java.io.*;2

3

4 public classIsrAndOswDemo {5 public static void main(String[] args)throwsIOException {6 //先创建FileInputStream对象in,用做创建InputStreamReader类对象的构造函数的参数

7 FileInputStream in=new FileInputStream("H:\\javalab\\1.txt");8 InputStreamReader isr=new InputStreamReader(in);//参数不加编码类型则采用项目默认的编码

9

10 FileOutputStream out=new FileOutputStream("H:\\javalab\\2.txt");11 OutputStreamWriter osw=newOutputStreamWriter(out);12 //单字符读取写入

13 intc;14 while((c=isr.read())!=-1){15 System.out.print((char)c);16 osw.write((char)c);17 osw.flush();18 }19 //批量读取,放入buff字符数组,从0开始放,最多放buff.length个字符,返回的是读到的字符个数

20 /*char[] buff=new char[8*1024];21 int c;22 while((c=isr.read(buff,0,buff.length))!=-1){23 String s=new String(buff,0,c);24 System.out.println(s);25 osw.write(buff,0,c);26 osw.flush();27 }*/

28 in.close();29 isr.close();30 }31 }

2、FileReader/FileWriter:比InputStreamReader/OutputStreamWriter操作要方便;

可以直接对文件进行字符流构造

1 import java.io.*;2 public classFrAndFwDemo {3

4 public static void main(String[] args)throwsIOException {5 FileReader fr=new FileReader("H:\\javalab\\3.txt");6 FileWriter fw=new FileWriter("H:\\javalab\\4.txt",true);7 char[] buff=new char[2*1024];8 intc;9 while((c=fr.read(buff,0,buff.length))!=-1){10 String s=new String(buff,0,c);11 System.out.println(s);12 fw.write(buff,0,c);13 fw.flush();14 }15 fr.close();16 fw.close();17 }18 }

3、字符流的过滤器:BufferedReader最强大的功能是readLine方法,一次读一行;

BufferedWriter/PrintWriter:写操作。

1 import java.io.*;2 public classBrAndBwAndPwDemo {3 public static void main(String[] args)throwsIOException{4 //对文件进行读写操作5 //Buffered过滤文件流构造比较方法

6 BufferedReader br=newBufferedReader(7 newInputStreamReader(8 new FileInputStream("H:\\javalab\\4.txt")));9 /*BufferedWriter bw=new BufferedWriter(10 new OutputStreamWriter(11 new FileOutputStream("H:\\javalab\\5.txt")));12 String line;13 while((line=br.readLine())!=null){14 System.out.println(line);//一次读一行并不能识别换行15 bw.write(line);//没法单独写一行16 bw.newLine();//单独写换行操作17 bw.flush();18 }19 */

20 //PrintWriter的构造比较简单

21 PrintWriter pw=new PrintWriter("H:\\javalab\\5.txt");22 //PrintWriter pw1=new PrintWriter("H:\\javalab\\5.txt",true);//自动带清空缓冲区功能

23 String line;24 while((line=br.readLine())!=null){25 //pw.print(line);

26 pw.println(line);//换行用println()

27 pw.flush();28 }29 br.close();30 pw.close();31

32

33

34 }35

36 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值