java IO流 详解

xiaoxiao2021-02-28  121

“` 流的概念和作用:流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质就是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。 IO流的分类: 根据处理数据类型的不同:字符流和字节流。 根据数据流向不同分为:输入流和输出流。 字符流和字节流 字符流的由来:因为数据编码的不同,而有了对字符进行高效操作的流对象。本质就是基于字节流的读取时,去查了码表。字节流与字符流的区别: 1.读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。 2.处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。 3.字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作;而字符流在操作的时候是会用到缓冲区的,是通过缓冲区来操作文件的。 结论:优先选用字节流,首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。字符只是在内存中才会形成,所以在开发时,字节流使用广泛。 输入流和输出流 输入流只能进行读操作,输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。 java IO流对象 1.输入字节流: 定义和结构说明:InputStream是所有输入字节流的父类,它是一个抽象类。 ByteArrayInputStream、StringBufferInputStream、FileInputStream是三种基本的介质流,他们分别从byte数组、StringBuffer和本地文件中读取数据。 ObjectInputStream和所有FilterInputStream的子类都是装饰流。意思是FileInputStream类可以通过一个String路径名创建一个对象,FileInputStream(String name),而DataInputStream必须装饰一个类才能返回一个对象,DataInputStream(InputStream in)。

实例: /** * 字节流 * 读文件内容 * */ import java.io.*; class hello{ public static void main(String[] args) throws IOException { String fileName=”D:”+File.separator+”hello.txt”; File f=new File(fileName); InputStream in=new FileInputStream(f); byte[] b=new byte[1024]; int count =0; int temp=0; while((temp=in.read())!=(-1)){ b[count++]=(byte)temp; } in.close(); System.out.println(new String(b)); } } 注意:当读到文件末尾的时候会返回-1,正常情况是不会返回-1的。 2.输出字节流OutputStream OutputStream是所有输出字节流的父类,它是一个抽象类。 ByteOutputStream和FileOutputStream是两种基本的介质流,它们分别向byte数组和本地文件中写入数据。 实例: /** * 字节流 * 向文件中写入字符串 * */ import java.io.*; class hello{ public static void main(String[] args) throws IOException { String fileName=”D:”+File.separator+”hello.txt”; File f=new File(fileName); OutputStream out =new FileOutputStream(f); String str=”Hello World”; byte[] b=str.getBytes(); out.write(b); out.close(); } } 注:这样会覆盖原来文件中的内容。 /** * 字节流 * 向文件中追加新内容: * */ import java.io.*; class hello{ public static void main(String[] args) throws IOException { String fileName=”D:”+File.separator+”hello.txt”; File f=new File(fileName); OutputStream out =new FileOutputStream(f,true);//true表示追加模式,否则为覆盖 String str=”Rollen”; //String str=”\r\nRollen”; 可以换行 byte[] b=str.getBytes(); for (int i = 0; i < b.length; i++) { out.write(b[i]); } out.close(); } } 注:这样只是在原文件的后面加上,并不会覆盖。 /** * 文件的复制 * */ import java.io.*; class hello{ public static void main(String[] args) throws IOException { if(args.length!=2){ System.out.println(“命令行参数输入有误,请检查”); System.exit(1); } File file1=new File(args[0]); File file2=new File(args[1]);

if(!file1.exists()){ System.out.println("被复制的文件不存在"); System.exit(1); } InputStream input=new FileInputStream(file1); OutputStream output=new FileOutputStream(file2); if((input!=null)&&(output!=null)){ int temp=0; while((temp=input.read())!=(-1)){ output.write(temp); } } input.close(); output.close(); }

}

/** * 使用内存操作流将一个大写字母转化为小写字母 * */ import java.io.*; class hello{ public static void main(String[] args) throws IOException { String str=”ROLLENHOLT”; ByteArrayInputStream input=new ByteArrayInputStream(str.getBytes()); ByteArrayOutputStream output=new ByteArrayOutputStream(); int temp=0; while((temp=input.read())!=-1){ char ch=(char)temp; output.write(Character.toLowerCase(ch)); } String outStr=output.toString(); input.close(); output.close(); System.out.println(outStr); } }

3.字符输入流Reader 定义和说明:Reader是所有的输入字符流的父类,它是一个抽象类。 CharReader、StringReader是两种基本的介质流,它们分别在char数组、String中读取数据。 BufferReader很明显是一个装饰类,它和其子类负责装饰其他Reader对象。 FilterReader是所有自定义具体装饰流的父类,其子类PushbackReader对Reader对象进行了装饰,会增加一个行号。 InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。后面会有Reader 与InputStream 的对应关系。

实例: /** * 字符流 * 从文件中读出内容 * */ import java.io.*; class hello{ public static void main(String[] args) throws IOException { String fileName=”D:”+File.separator+”hello.txt”; File f=new File(fileName); char[] ch=new char[100]; Reader read=new FileReader(f); int count=read.read(ch); read.close(); System.out.println(“读入的长度为:”+count); System.out.println(“内容为”+new String(ch,0,count)); } }

注:最好采用循环读取的方式,因为我们有时候不知道文件到底有多大。 以循环方式从文件中读取内容 /** * 字符流 * 从文件中读出内容 * */ import java.io.*; class hello{ public static void main(String[] args) throws IOException { String fileName=”D:”+File.separator+”hello.txt”; File f=new File(fileName); char[] ch=new char[100]; Reader read=new FileReader(f); int temp=0; int count=0; while((temp=read.read())!=(-1)){ ch[count++]=(char)temp; } read.close(); System.out.println(“内容为”+new String(ch,0,count)); } }

注:BufferedReader只能接受字符流的缓冲区,因为每一个中文需要占据两个字节,所以需要将System.in这个字节输入流变为字符输入流,采用:

BufferedReader buf = new BufferedReader(newInputStreamReader(System.in));

下面是一个实例: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;

/** * 使用缓冲区从键盘上读入内容 * */ public class BufferedReaderDemo{ public static void main(String[] args){ BufferedReader buf = new BufferedReader( newInputStreamReader(System.in)); String str = null; System.out.println(“请输入内容”); try{ str = buf.readLine(); }catch(IOException e){ e.printStackTrace(); } System.out.println(“你输入的内容是:” + str); } }

4.字符输出流Writer Writer 是所有的输出字符流的父类,它是一个抽象类。 CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。 BufferedWriter 是一个装饰器为Writer 提供缓冲功能。 PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。 OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。 实例: /** * 字符流 * 写入数据 * */ import java.io.*; class hello{ public static void main(String[] args) throws IOException { String fileName=”D:”+File.separator+”hello.txt”; File f=new File(fileName); Writer out =new FileWriter(f); String str=”hello”; out.write(str); out.close(); } }

注:只是你可以直接输入字符串,而不需要你将字符串转化为字节数组。当你如果想问文件中追加内容的时候,可以使用将上面的声明out的哪一行换为: Writer out =new FileWriter(f,true); 这样,当你运行程序的时候,会发现文件内容变为:hellohello如果想在文件中换行的话,需要使用“\r\n”比如将str变为String str=”\r\nhello”;这样文件追加的str的内容就会换行了。

5.字符流与字节流转换

转换流的特点: (1)其是字符流和字节流之间的桥梁

(2)可对读取到的字节数据经过指定编码转换成字符

(3)可对读取到的字符数据经过指定编码转换成字节

何时使用转换流? 当字节和字符之间有转换动作时;

流操作的数据需要编码或解码时。

具体的对象体现: InputStreamReader:字节到字符的桥梁

OutputStreamWriter:字符到字节的桥梁

这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。

/** * 将字节输出流转化为字符输出流 * */ import java.io.*; class hello{ public static void main(String[] args) throws IOException { String fileName= “d:”+File.separator+”hello.txt”; File file=new File(fileName); Writer out=new OutputStreamWriter(new FileOutputStream(file)); out.write(“hello”); out.close(); } }

/** * 将字节输入流变为字符输入流 * */ import java.io.*; class hello{ public static void main(String[] args) throws IOException { String fileName= “d:”+File.separator+”hello.txt”; File file=new File(fileName); Reader read=new InputStreamReader(new FileInputStream(file)); char[] b=new char[100]; int len=read.read(b); System.out.println(new String(b,0,len)); read.close(); } }

6.File类 File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。

实例:创建一个文件 import java.io.*; class hello{ public static void main(String[] args) { File f=new File(“D:\hello.txt”); try{ f.createNewFile(); }catch (Exception e) { e.printStackTrace(); } } }

:File类的两个常量 import java.io.*; class hello{ public static void main(String[] args) { System.out.println(File.separator); System.out.println(File.pathSeparator); } }

注:有些同学可能认为,我直接在windows下使用\进行分割不行吗?当然是可以的。但是在linux下就不是\了。所以,要想使得我们的代码跨平台,更加健壮,所以,大家都采用这两个常量吧,其实也多写不了几行。

:File类中的常量改写案例1的代码: import java.io.*; class hello{ public static void main(String[] args) { String fileName=”D:”+File.separator+”hello.txt”; File f=new File(fileName); try{ f.createNewFile(); }catch (Exception e) { e.printStackTrace(); } } } :删除一个文件(或者文件夹) import java.io.*; class hello{ public static void main(String[] args) { String fileName=”D:”+File.separator+”hello.txt”; File f=new File(fileName); if(f.exists()){ f.delete(); }else{ System.out.println(“文件不存在”); }

}

}

:创建一个文件夹 /** * 创建一个文件夹 * */ import java.io.*; class hello{ public static void main(String[] args) { String fileName=”D:”+File.separator+”hello”; File f=new File(fileName); f.mkdir(); } }

: 使用list列出指定目录的全部文件 /** * 使用list列出指定目录的全部文件 * */ import java.io.*; class hello{ public static void main(String[] args) { String fileName=”D:”+File.separator; File f=new File(fileName); String[] str=f.list(); for (int i = 0; i < str.length; i++) { System.out.println(str[i]); } } } 注意使用list返回的是String数组,。而且列出的不是完整路径,如果想列出完整路径的话,需要使用listFiles.它返回的是File的数组。

:使用isDirectory判断一个指定的路径是否为目录 /** * 使用isDirectory判断一个指定的路径是否为目录 * */ import java.io.*; class hello{ public static void main(String[] args) { String fileName=”D:”+File.separator; File f=new File(fileName); if(f.isDirectory()){ System.out.println(“YES”); }else{ System.out.println(“NO”); } } }

转载请注明原文地址: https://www.6miu.com/read-39137.html

最新回复(0)