-
IO里面的常见类,字节流、字符流的差异
2020-02-07 17:34:23JAVA IO主要有这四个类InputStream、OutputStream、Reader、Writer来处理,要处理字节流的就用InputStream、OutputStream,要处理字符流,就用Reader、Writer,现实中根据需要,我们选择他们的相关子类进行数据的...JAVA IO主要有这四个类InputStream、OutputStream、Reader、Writer来处理,要处理字节流的就用InputStream、OutputStream,要处理字符流,就用Reader、Writer,现实中根据需要,我们选择他们的相关子类进行数据的读写
首先什么是流:
流(Stream)的概念来源于UNIX中的管道(pipe)概念,在unix中,管道是一条不间断的字节流,用来实现程序和进程间的通信,或者读写外围设备、外部文件等。流,必须有源端和目的端,可以是文件,内存或者网络等。流的创建是为了更方便的处理数据的输入输出。简单的来说:输入流就是从外部文件输入到内存,输出流主要是从内存输出到文件。我们用Eclipse开发小程序在控制台输入数据就属于输入流,即从控制台输入到内存。字节流
字节流主要是操作byte类型数据,以byte数组为准,主要操作类就是OutputStream、InputStream。两者都是抽象类,是字节输入、输出流的父类。以InputStream为例,最常用到的子类有:FileInputStream,ByteArrayInputStream,ObjectInputStream,BufferedInputStream、DataInputStream、PushbackInputStream。
其中前三类可以理解为针对流中不同的内容分别实现了类,这点可以通过查看各自类的构造函数来验证,比如说FileInputStream的一个构造方法为:FileInputStream(File file) ,即通过打开一个到实际文件的连接来创建一个FileInputStream。ByteArrayInputStream类的构造方法ByteArrayInputStream(byte[] buf) 的参数为byte[]数组。字符流
在程序中一个字符等于两个字节,java提供了Reader、Writer两个专门操作字符流的类。两者同样是抽象类。已Reader为例,其常用的子类有:BufferedReader,CharArrayReader,FilterReader,InputStreamReader,PipedReader,StringReader 。
对于字节流和字符流的区别:
字节流处理单元为1个字节,操作字节和字节数组,而字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串。程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件(特别是文本文件)时,也是一个字节一个字节地读取以形成字节序列。那么既然磁盘存储都是按字节,内存中处理为何还需要字符流呢?字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点!那开发中究竟用字节流好还是用字符流好呢?
在所有的硬盘上保存文件或进行传输的时候都是以字节的方法进行的,包括图片也是按字节完成,而字符是只有在内存中才会形成的,所以使用字节的操作是最多的。我们建议尽量尝试使用字符流,一旦程序无法成功编译,就不得不使用面向字节的类库,即字节流。 -
java的常见的字符字节处理
2015-12-29 21:11:47在最近在学习nio的过程中,温习了以前学习的socket的io处理,发现最基础的处理操作离不开BufferedReader和PrintWriter,他们对应着socket的输入和输出流对象。另外一个问题是PrintWriter和PrintStream的区别。 ...前言:
在最近在学习nio的过程中,温习了以前学习的socket的io处理,发现最基础的处理操作离不开BufferedReader和PrintWriter,他们对应着socket的输入和输出流对象。另外一个问题是PrintWriter和PrintStream的区别。
PrintWriter和PrintStream的区别
这个问题,我查了资料,主要在jdk的说明上和在stackoverflow上,下面是二者的总结:
PrintWriter实现了PritnStream的所有print方法。对于PrintStream,所有println方法都在内部调用相应的print方法,比如println(charx)的方法体就是调用print(x);再写入一个平台相关的换行符。PrintStream构建时会在内部new一个BufferedWriter,所有print方法都在内部调用这个Writer的write方法(write(String)或write(char[]))——对于print(char[]),直接调用write(char[]);对于其他的print方法,先用String.valueOf获得参数的字符串表示,然后调用write(String)。 对于PrintWriter,所有println方法也都在内部调用print方法,print方法调用write方法。传入OutputStream时,PrintWriter会在内部构造一个BufferedWriter;而传入Writer时,PrintStream内部直接使用该Writer,此时PrintWriter是否进行了缓冲全看该Writer。
上述的内容还需看下源码才能加深映象BufferedReader进行readLine什么时候返回null
while(reader.ready()) { //执行读取操作,即readLine }
- ready是查看流是否已经准备好被读,是一个非阻塞的方法,所以会立刻返回,由于服务器没有准备好被读,所以会立刻返回,所以读取到的都是null。
- readLine是一个阻塞的方法,只要没有断开连接,就会一直等待,直到有东西返回,那么什么时候返回空呢,只有读到数据流最末尾,才返回null。
特别要注意的是当reader.readLine已经读完之后,如果继续执行ready操作,会返回false; 因此,下面两段代码可能造成死循环:
while(reader.readLine()!==null){ //执行操作 while(!reader.ready){ //阻塞,等待一段时间 } } while(reader.readLine()!==null){ //执行操作 } while(!reader.ready){ //阻塞,等待一段时间 }
先写这么多,遇到问题在添加!
-
字节流与字符流
2021-01-25 18:24:47今天主要总结一下字节流和字符流的用法以及特点,一开始东西多,建议大家记忆常见的父类中的方法 记忆具体的实现子类对应的操作,因为子类继承了父类带有其方法,但子类自己独特的方法还需单独记忆。 流模型字节流...- 今天主要总结一下字节流和字符流的用法以及特点,一开始东西多,建议大家记忆常见的父类中的方法 记忆具体的实现子类对应的操作,因为子类继承了父类带有其方法,但子类自己独特的方法还需单独记忆。
- 主要目的:屏蔽具体实现的区别,使用统一的方法进行编程
- 输入和输出
- 字节和字符
- 节点和过滤 装饰模式
- BIO NIO AIO
字节流
- 父类InputStream和OutputStream
- 一次一字节的操作方式,一般用于声音、图像、视频之类的二进制文件
InputStream
方法: - read():int -1 - read(byte[]):int -1 - close():void - FileInputStream主要用于操作文件 - System.in 主要用于接收用户输入
OutputStream
方法: - write(int):void - write(byte[],int,int):void - close():void - FileOutputStream主要用于操作文件 - new FileOutputStream(“文件名称”)采用文件覆盖的方式操作 - new FileOutputStream(“文件名称”,boolean是否采用追加操作) - System.out和System.err 用于输出到标准输出设备
public class Test1 { public static void main(String[] args) throws IOException { //try/resource的写法,会自动执行关闭操作,但是要求实现closeable接口 try (OutputStream os = new FileOutputStream("data.txt",true); InputStream is = new FileInputStream("Test1.java");) { int kk; while ((kk = is.read()) > -1) { os.write(kk); } } } //由于是一次读取一字节的操作,所以在操作输出时会有问题,但是文件拷贝不会有任何问题 }
上面的方法采用的是一次一字节的操作方法,效率较低,可以考虑引入byte[]缓存的方式提高执行效率
public class Test1 { public static void main(String[] args) throws IOException { try (OutputStream os = new FileOutputStream("data.txt",true); InputStream is = new FileInputStream("Test1.java");) { int kk; byte[] buffer=new byte[8192];//如果不确定缓存的大小,建议使用8192,即8kB while ((kk = is.read(buffer)) > -1) { //返回值是读取的字节数,最多8192字节,但是 实际上并不一定读取8192字节 String ss=new String(buffer,0,kk);//主要解决多字节的字符组装问题 System.out.println(ss); os.write(buffer,0,kk);//读取多少个字节则写出多少个字节 } } } }
复杂样例
- 实现文件夹的拷贝和移动
文件夹的深度无法提前预知,所以这里采用递归调用的方式进行操作
public class Test1 { private static String source; private static String target; public static void main(String[] args) throws IOException { source="C:\\software\\EditPlus 3"; target="c:\\ddd"; File ff=new File(source); copy(ff); } public static void copy(File file)throws IOException{ if(file!=null && file.exists()) { if(file.isDirectory()) { String path=file.getAbsolutePath(); String newPath=path.replace(source, target); File tmp=new File(newPath); if(!tmp.exists())tmp.mkdirs(); File[] fs=file.listFiles(); if(fs!=null && fs.length>0)for(File temp:fs)copy(temp); }else if(file.isFile()) { //事实上有简化写法 String path=file.getAbsolutePath(); String newPath=path.replace(source, target); try( InputStream is=new FileInputStream(file); OutputStream os=new FileOutputStream(newPath); ){ byte[] buffer=new byte[8192]; int len=0; while((len=is.read(buffer))>0) os.write(buffer,0,len); } } } } }
字符流
一次操作一个字符 一般用于操作文本文件,注意word文档不是字符文件
Reader字符输入流
- read():int 0-65535 -1
- read(char[]):int -1
- close():void
- FileReader用于操作文件,属于节点流
读取指定文件并在控制台上进行显示
public class Test2 { public static void main(String[] args)throws Exception { File f=new File("Test1.java"); if(f.exists()) { //如果文件不存在,则在执行read操作时会抛出FileNotFoundException try(Reader r=new FileReader(f);){ int cc; while((cc=r.read())!=-1) { System.out.print((char)cc);//windows下的换行和linux中的换行不一样 } } }else { System.out.println("文件不能读取!"); } } }
Writer字符输出流
- write(int):void
- write(char[],int,int):void
- close()
- FileWriter用于操作文件
----new FileWriter(String leName)
-----new FileWriter(String leName, boolean append)默认覆盖,boolean表示是否追加
public class Test2 { public static void main(String[] args)throws Exception { File f=new File("Test1.java"); if(f.exists()) { //如果文件不存在,则在执行read操作时会抛出FileNotFoundException try(Reader r=new FileReader(f); Writer w=new FileWriter("c:/bbb.txt"); ){ int len=0; char[] buffer=new char[8192]; while((len=r.read(buffer))!=-1) { System.out.print(buffer);//windows下的换行和linux中的换行不一样 w.write(buffer,0,len);//读取多少字符则写出多少字符 } } }else { System.out.println("文件不能读取!"); } } }
小结
- 在学些BIO时记忆父类的方法,区分子类的实现不同
--------InputStream中的方法 read(byte[]):int; Reader中方法read(char[]):int 如果到达流末尾则-1
-------OutputStream中的方法 write(byte[],0,len):void;Writer中的方法write(char[],0,len)/write(String) - 一般在使用中,如果读取数据使用字节流,则写出数据采用的也是字节流;不建议混用,除非引入桥接流
- 文件流
----FileInputStream(“le-name”) FileInputStream(File) FileNotFoundException
----FileReader(“le-name”) FileReader(File) FileNotFoundException
----FileOutputStream(“le-name”) FileOutputStream(“le-name”,true) 默认文件覆盖,如果参数true表示追加
----FileWriter(“le-name”) FileWriter(“le-name”,true)
----一般不使用单字节或者单字符的操作方法,使用数组 - 注意:try(){}是推荐写法,否则应该使用try{}nally{}结构保证流的关闭
- 针对二进制文件不建议使用字符流,建议使用字节流进行操作,否则有可能拷贝文件出现问题:
- 如果针对文本文件则建议使用字符流,因为编码使用比较方便
编写一个程序实现如下功能,文件n.txt是无行结构(无换行符)的汉语文件,从n中读取字符,写入文件fout.txt中,每40个字符一行(最后一行可能少于40个字)
public class Test3 { public static void main(String[] args) throws IOException{ File f=new File("c:/fin.txt"); if(f.isFile()&& f.exists()) { try( Reader r=new FileReader("c:/fin.txt"); Writer w=new FileWriter("c:/fout.txt"); ){ int counter=0; int cc; while((cc=r.read())!=-1) { counter++; System.out.print((char)cc); w.write(cc); if(counter%40==0) { System.out.println(); w.write("\n"); } } } } } }
统计一个文件calcCharNum.txt中字母’A’和’a’出现的总次数
public class Test3 { public static void main(String[] args) throws IOException{ File f=new File("c:/calcCharNum.txt"); if(f.isFile() && f.exists()) { try( Reader r=new FileReader(f); ){ int cc; int counter=0; while((cc=r.read())!=-1) { if(cc=='a' || cc=='A') counter++; } System.out.println("A或者a出现次数为:"+counter); } } } }
统计一个文件calcCharNum.txt中各个字母出现次数:A(8),B(16),C(10)…,a(12),b(10),c(3)…, 括号内代表字符出现次数; 存储数据的方法1:采用数组,例如数组1中存储大写字母,数组2中存储小写字母
public class Test3 { public static void main(String[] args) throws IOException{ File f=new File("c:/calcCharNum.txt"); if(f.isFile() && f.exists()) { try( Reader r=new FileReader(f); ){ int[] carr1=new int[26];//存储大写字母的出现次数,每个位置对应一个字符 int[] carr2=new int[26];//存储小写字母的出现次数,每个位置对应一个字符 int cc; while((cc=r.read())!=-1) { if(cc>='a'&&cc<='z')carr2[cc-'a']++;//将读取的字符转换为下标,然后对应位 置加1,默认初始值为0 if(cc>='A'&&cc<='Z')carr1[cc-'A']++; } for(int i=0;i<carr1.length;i++) System.out.print((char)('A'+i)+"("+carr1[i]+"),"); System.out.println(); for(int i=0;i<carr2.length;i++) System.out.print((char)('a'+i)+"("+carr2[i]+"),"); } } } }
方法2:采用自定义类的方式记录字符和对应的出现次数
public class CharNum { private char c; //对应的字符 private int num=1; //该字符出现的次数 public CharNum(char c) { //构建对象时必须告知所封装的字符,而且不允许修改 this.c=c; } public char getC() { return c; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } }
最多可以有52【26*2】个对象,可以定义一个数组用于存储数据CharNum[] cn=new CharNum[52];
public class Test3 { public static void main(String[] args) throws IOException{ File f=new File("c:/calcCharNum.txt"); if(f.isFile() && f.exists()) { try( Reader r=new FileReader(f); ){ CharNum[] carr=new CharNum[52]; int cc; while((cc=r.read())!=-1) { //从流中读取字符数据 if((cc>='A'&&cc<='Z') || (cc>='a'&&cc<='z')) {//判读英文字母 boolean bb=false; int i=0; for(;i<carr.length;i++) { //遍历数组,判断是否已经存储这个字符 if(carr[i]==null) { //已经遍历了前面的所有存储内容,该字符不存在 bb=true; //表示需要新增到数组中 break; }else { if(cc==carr[i].getC()) { //如果读取字符和第i个位置上存放的字符相 同 carr[i].setNum(carr[i].getNum()+1); //统计次数+1 break; //一个字符只对应一个存储位置 } } } if(bb) carr[i]=new CharNum((char)cc); } } for(CharNum tmp:carr) if(tmp!=null) System.out.print(tmp+","); } } } }
编写一个程序,把指定目录下的所有的带.java文件都拷贝到另一个目录中,拷贝成功后,把后缀名是.java的改成.txt
--------------文件夹的深度未知
----------------FilenameFilterpublic class Test1 { private static String source = "C:\\workspace\\eclipse-workspace\\test"; private static String target = "c:\\ddd"; public static void main(String[] args) throws Exception { File f = new File(target); if (!f.exists()) f.mkdirs(); f = new File(source); copyJavaFile(f); } public static void copyJavaFile(File file) throws IOException { if (file != null && file.exists()) { if (file.isDirectory()) { File[] fs = file.listFiles((dir, name) -> { File temp = new File(dir, name); if (temp.isFile()) return name.endsWith(".java"); return true; }); if (fs != null && fs.length > 0) { for (File temp : fs) { copyJavaFile(temp); } } } else if (file.isFile()) { String path = file.getAbsolutePath(); String fileName=path.substring(path.lastIndexOf("\\")); fileName=target+fileName; try (Reader r = new FileReader(file); Writer w = new FileWriter(fileName,true);) { char[] arr = new char[8192]; int len = 0; while ((len = r.read(arr)) > 0) { w.write(arr, 0, len); } } } } } }
节点流类型 类型 字符流 字节流
File文件 FileReader、FileWriter FileInputStream、FileOutputStream
内存数组 CharArrayReader、 CharArrayWriter ByteArrayInputStream、 ByteArrayOutputStream 内存字串
StringReader、 StringWriter
管道 PipedReader、 PipedWriter PipedInputStream、 PipedOutputStream文件节点流
- FileInputStream和FileOutputStream是文件字节流,是一种节点流
文件字节输入流的构造方法: - FileInputStream(“文件名称”),如果文件不存在则FileNotFoundException
- FileInputStream(File)
文件字节输出流的构造方法:
- FileOutputStream(“文件名称”) 如果文件不存在则新建文件,如果文件存在则覆盖文件内容
- FileOutputStream(String name文件名称, boolean append是否采用追加方式)
FileReader和FileWriter类似
内存数组节点
如果文本则使用char[],如果二进制则使用byte[]
构造器方法- CharArrayReader(char[] buf)其中char[]就是数据的来源,也就是说Reader就是从char[]中读取数据
- CharArrayRead(char[] buf, int oset, int length)
CharArrayWriter用于实现向一个字符数组中写入数据,这个数组可以自动调整大小
ByteArrayInputStream、ByteArrayOutputStream和CharArrayReader以及CharArrayWriter类似,支持操作的内容不同而已,操作byte[]与char[]
从一个文件中读取内容并写入到char[]中
public class Test2 { public static void main(String[] args)throws Exception { Reader r=new FileReader("Test1.java"); //实际上就是一个writer,向CharArrayWriter写出数据,实际上会自动写入一个相关联的char数组中 Writer w=new CharArrayWriter(); int cc; while((cc=r.read())!=-1) { w.write(cc); } r.close(); w.close(); //CharArrayWriter中的特殊方法,用于获取CharArrayWriter的输出数组 char[] arr=((CharArrayWriter)w).toCharArray(); System.out.println(arr); } }
从char数组中读取数据
public class Test3 { public static void main(String[] args)throws Exception { String str="中国人民解放军asdfasd"; Reader r=new CharArrayReader(str.toCharArray()); int kk; while((kk=r.read())!=-1) { System.out.println((char)kk); } r.close(); } }
内存字串流
StringReader用于从一个字串String中读取数据,StringWriter用于给一个StringBuer中写入数据,实现一个可边长的字串public class Test4 { public static void main(String[] args)throws Exception { String str="王一新说'我爱玉衡'"; Reader r=new StringReader(str); int kk; while((kk=r.read())!=-1) { System.out.print((char)kk); } r.close(); } }
键盘录入内容,并缓存在内存中,输入quit表示输入完成,输入完成后再在控制台上显示所有输入的内容
public class Test5 { public static void main(String[] args)throws Exception { Scanner sc=new Scanner(System.in); Writer w=new StringWriter(); int counter=0; while(true) { String str=sc.nextLine(); if("quit".equals(str)) break; w.write("第"+(++counter)+"次输入为:"+str+"\n"); } w.close(); StringBuffer sb=((StringWriter)w).getBuffer(); System.out.println(sb); } }
总结
- 读写文件使用节点流FileInputStream/FileOutputStream和FileReader/FileWriter,如果操作文本文件,建议使用FileReader/FileWriter,如果操作二进制文件建议使用FileInputStream/FileOutputStream
- 需要建立缓冲区(建立临时文件的方式效率低),可以考虑使用内存节点,例如CharArrayReader/CharArrayWriter、StringReader/StringWriter和ByteArrayInputStream/ByteArrayOutputStream
- 如果需要一个二进制缓冲区可以使用ByteArrayInputStream/ByteArrayOutputStream,如果需要一个字符缓存可以使用CharArrayReader/CharArrayWriter StringReader/StringWriter
- 如果数据量不是特别大使用CharArrayReader/CharArrayWriter更为方便,如果数据量大而且可能需要直接操作缓冲区则使StringReader/StringWriter
- StringWriter中提供了方法getBuer():StringBuer
-
java常用的字节流和字符流操作
2020-06-28 21:45:09java 的 IO 流有很多类,常见常用的也就是字节流 InputStream 和 OutputStream 输入输出流,这是字节流两个顶级父类(当然上面还有接口),还有 FileReader 和 FileWriter 输入输出流,这是字符流两个顶级父类 ...
前言
java 的 IO 流有很多类,常见常用的也就是字节流 InputStream 和 OutputStream 输入输出流,这是字节流两个顶级父类(当然上面还有接口),还有 FileReader 和 FileWriter 输入输出流,这是字符流两个顶级父类
输入和输出可以理解为相对于内存或者屏幕来说的,从磁盘读取到内存中是输入,写进磁盘则表示输出。所以很好理解, InputStream 和 FileReader 用来做读取数据操作,OutputStream 和 FileWriter 用来做把数据写入磁盘的操作
下面这有一张菜鸟教程中的图片,很清晰的展示了各个类之间的父子关系
字节流
常用的 OutputStream 和 InputStream 是输出流和输入流,二者都是抽象类,然后我们常用其中的 FileOutStream 和 FileInputStream,还有一个缓冲流 BufferedOutputStream 和 BufferedInputStream 是一个缓冲器,构造器分别接收 OutputStream 和 InputStream 的参数类型
字节流的追加就是在构造器的时候第二个参数传入 true 即可,不传默认是 false 就是完全覆盖
OutputStream 字节输出流
字节输出流,下图中我们知道 java.io 包中有如下这些字节输出流的类,其中 OutputStream 是一个抽象类
其实绝大部分程序员最常用的也就是 FileOutputStream 和 BufferedOutputStream
小例子如下,其写入文件磁盘只能接收 int 和 byte 类型,int 就是 ascall 码对应的数字,字节就是一个字节,注意可不是 char 类型
如果我们不是用 buffer 也行,如果使用的话
buffer.close()
必加,不加的话 buffer 中的字节没办法存进磁盘中!!!public class IOOperation { @Test public void fun() throws IOException { FileOutputStream stream = new FileOutputStream("src\\test\\java\\temp.txt"); BufferedOutputStream buffer = new BufferedOutputStream(stream); buffer.write(new byte[]{'a', 'b', 'c'}); buffer.close(); stream.close(); } }
注意点
- 如果使用了 buffer 注意要加``buffer.close()`否则不会将缓冲区的内容写进磁盘!
InputStream 字节输入流
字节输入流,下图中我们知道 java.io 包中有如下这些字节输出流的类,其中 InputStream 是一个抽象类
其实绝大部分程序员最常用的也就是 FileInputStream 和 BufferedInputStream
public class IOOperation { @Test public void fun() throws IOException { FileInputStream stream = new FileInputStream("src\\test\\java\\temp.txt"); BufferedInputStream buffer = new BufferedInputStream(stream); System.out.println(buffer.read()); System.out.println(buffer.read()); System.out.println(buffer.read()); System.out.println(buffer.read()); buffer.close(); stream.close(); } }
注意点
- 如果使用了 buffer 加不加``buffer.close()`都可以直接看到控制台有正常输出,这一点与输出流是不同的
- 使用 read 方法如果读到没有字节了,会直接返回 -1,read 方法返回 int 类型
- 每次使用 read 方法之后,一个字节一个字节的往后读
字符流
Writer 和 Reader 分别是字符输出流和字符输入流,二者都是抽象类,然后往下继承的子类 OutputStreamWriter 和 InputStreamReader 都是实体类
字符流的追加就是在构造器的时候第二个参数传入 true 即可,不传默认是 false 就是完全覆盖
Writer 字符输出流
字符输出流
其实一般情况下我们使用最多也就是 FileWriter 和 BufferedWriter
下面有个小例子,展示的是追加文件,先进入下一行,然后写上 aaabbbccc
public class IOOperation { @Test public void fun() throws IOException { FileWriter writer = new FileWriter("src\\test\\java\\temp.txt", true); BufferedWriter buffer = new BufferedWriter(writer); buffer.newLine(); buffer.write("aaa"); buffer.append("bbb").append("ccc"); buffer.close(); writer.close(); } }
注意点
- 字符流除了有 write 方法,还有 append 方法,write 方法没有返回值且不可接受 null,但是 append 方法似乎就要灵活一些了,可以接收 null,写入磁盘就是 null 的字符串,而且有返回值,返回就是字符流本身,因此可以不断的
.append("").append("")
的形式 - buffer 必加上 close,否则磁盘没有内容
Reader 字符输入流
字符输入流
其实一般情况下我们使用最多也就是 FIleReader 和 BufferedReader
我们直接看下面的例子即可
public class IOOperation { @Test public void fun() throws IOException { FileReader reader = new FileReader("src\\test\\java\\temp.txt"); BufferedReader buffer = new BufferedReader(reader); System.out.println(buffer.read()); System.out.println(buffer.readLine()); buffer.close(); reader.close(); } }
注意点
- 与字节流相似,输入字符流在使用 buffer 时候没有加 close 关掉 buffer 也一样是可以把文件中的内容读取到控制台中的,相比输出字符流就必须要加上 buffer 的 close 方法了
- read 方法返回 int 型,也就是一个字符的 ascall 码,readLine 方法可以返回当前位置后一整行的字符串类型
- 如果 read 方法读不到字符了它会返回 -1,如果 readLine 方法读不到行了它会返回 null 的字符串
二者区别
字节流读取字节,字符流读取一个字符
字符流是可以设置编码方式的
字符流更加灵活,推荐文本文件使用
使用场景
如果是操作文本文件,我建议直接使用字符流来操作,简单便捷,若是图片或者其他文件(电脑中的文件都是二进制形式文件,都可以使用字节流操作),我就推荐直接使用字节流来操作了
其他注意点
-
Write 输出流的 flush() 操作是指,一般 IO 操作在有缓冲区的情况下,调用 close() 方法缓冲区才会被输出到磁盘中,如果直接执行 flush 可以在缓冲区没有满的时候手动输出一次到磁盘
-
字节流设置编码方式可以通过 InputStreamReader 或者 OutputStreamWriter 的构造器来做,第二个参数传输编码名字,这两个类父类分别是 Reader 和 Writer,子类分别是 FileReader 和 FIleWriter,它虽然是属于字符流家族的,但实际上是做字节流的编码方式设定,InputStreamReader 构造器的第一个参数类型是 InputStream 类型,InputStream 是字节流家族的,并且我查看了源码发现如果不传第二个参数编码方式,它会执行这段代码
Charset.defaultCharset().name()
,它读的是配置的语言编码,或者说自己环境的语言编码 -
如果是中文,java 字节流也是可以读取的但是读取的东西可能就不好认识了,比如说一个“啊”读取到屏幕上显示 229 149 138
-
字符流和字节流
2015-08-03 07:35:00/*字符流和字节流: 字节流两个基类:InputStream OutputStream 字符流两个基类:Reader Writer 先学习一下字符流特点。 既然IO流是用于操作数据的。那么数据的最常见体现形式是:文件。 那么先以操作文件为主... -
java-字节流/字符流
2021-01-25 23:19:36今天主要总结一下字节流和字符流的用法以及特点,建议大家记忆常见的父类中的方法 记忆具体的实现子类对应的操作。 流模型字节流InputStreamOutputStream字符流Reader字符输入流Writer字符输出流文件节点流内存数组... -
常见的流对象有几种?什么是字节流,什么是文件,什么是字符流?
2019-08-17 18:07:43File文件,字节输入流,字节输入流,字符输入流,字节输出流的详解 File文件概述 1.File类型:用于表示一个文件或者是文件夹的路径的对象(抽象路径名) 2.路径:用于描述文件或者是文件夹的所在路径的所在的字符串 3.... -
java学习21-字符流,字节流,转换流的理解
2018-05-05 22:31:141:字符流 (1)字节流操作中文数据不是特别的方便,所以就出现了转换流。...字符流 = 字节流 + 编码表 (3)编码表 A:就是由字符和对应的数值组成的一张表 B:常见的编码表 ASCII ISO-8859-1 GB2312 GBK GB18030 UTF-8... -
day21 IO字节流字符流
2020-10-25 22:21:18字符流 = 字节流 + 编码表 (3)编码表 A:就是由字符和对应的数值组成的一张表 B:常见的编码表 ASCII ISO-8859-1 GB2312 GBK GB18030 UTF-8 C:字符串中的编码问题 编码 String – byte[] 解码 byte[] – String (4)IO... -
Java IO:简述字节流、字符流、缓冲流
2021-01-20 11:53:45Java IO:字节/字符输入输出流及缓冲输入输出流字节流字节输入流字节缓冲输入流字节输出流字节缓冲输出流字符流字符输入流字符缓冲输入流字符输出流字符缓冲输出流补充 Java的字节输入输出与字符的其实大同小异,... -
java.io中的字节流和字符流、socket
2019-12-11 11:14:03字符流常见的类 java.io的字节流 高级的字节流类 java.io里面的装饰器模式 FileInputStream里面添加了缓冲的功能,但是它还是一个InputStream Socket是网络通信的端点 通过socket发送数据 通过socket接收数据... -
java IO字节流和字符流常见类总结
2017-07-26 15:41:01前述 程序在运行结束后,数据内容就会被内存回收掉,从而消失...数据的传输都是通过两种类型的流:输入流和输出流,这就是IO。 流的继承关系图 需要读入数据使用输入流,需要写入数据使用输出流; 按照操作的数 -
java进阶之IO流(字节流、字符流)
2020-09-04 10:59:20用缓冲流按行读取四、字节流字符流总结案例:先注册,再登录系统玩猜数字游戏五、对象流(序列化流)六、其它流 三、字符流 (1)字节流操作中文数据不是特别的方便,所以就出现了转换流。 转换流的作用就是把字节... -
Java笔记----字节流与字符的常见类型
2017-04-29 13:03:00字节流: InputStream |-- FileInputStream (基本文件流) |-- BufferedInputStream |-- DataInputStream |-- ObjectInputStream 字符流 Reader |-- InputStreamReader (byte->char 桥梁) |-- ... -
字符留和字节流的总结
2014-12-15 15:37:13字符流的特点: 所有文件的存储都是字节的...在读取文件时,也是一个字节一个字节的读取,然后生成字节的序列数据最常见的体现形式是:文件文本文件以字符形式存在,读取(写入)文件需要用到字符流**************** -
Java字符流和字节流的桥梁InputStreamReader
2020-11-20 16:46:43miaoshu 常用方法 描述 父类:Reader 子类:FileReader 常见IO流:InputStream、OutputStream、Writer -
Java字符流和字节流的桥梁OutputStreamWriter
2020-11-20 16:50:52miaoshu1 常用方法 描述 父类:Writer 子类:FileWriter 常见IO流:InputStream、OutputStream、Reader -
java IO怎么判断流类是字符流还是字节流
2018-04-06 09:11:12java中怎么判断流类是字符流还是字节流 这个问题在面试中很常见,也比较容易搞混淆。java的IO操作中有面向字节(byte)和面向字符(Character)两种方式。 面向字节的操作以8位为单位对二进制数据进行操作,对... -
字节缓冲流、转换流、字符流
2020-03-22 11:47:17字节缓冲流、转换流字节缓冲流字节缓冲区流的概述和使用案例代码字节流四种方式复制AVI并测试效率案例代码转换流转换流出现的原因案例代码转换流的组成部分编码表概述和常见编码表乱码问题String类中的编码和解码... -
常见字符流
2018-08-25 22:10:29字符流的由来:字符流读取文字字节数据以后,不直接操作而是先查指定的编码表,获取对应的文字,再对该文字进行操作,简单说字符流就是字节流+编码表。所以对于文字的操作优先使用字符流。 一、利用字符流实现文本... -
java IO之 字符流 (字符流 = 字节流 + 编码表) 装饰器模式
2016-04-25 10:56:40所以字符流是建立在字节流之上的,它能够提供字符 层次的编码和解码。列如,在写入一个字符时,Java虚拟机会将字符转为文件指定的编码(默认 是系统默认编码),在读取字符时,再将文件指定的编码转化为字符。 常见... -
字符流转化为字节流_advancedday12IO流字符流,转换流,对象操作流及Properties
2020-12-19 15:21:31编码和解码常见的字符编码: ASCII: 包含最基本字符(英文字母、数字、标点符号...) GBK: 兼容ASCII编码,还包含中文。 一个汉字占2个字节 UTF-8: 兼容ASCII编码,包含中文,还包含其他国家的文字 一个汉字占3个字节... -
I/O流,字节流,字符流,数据流,缓存流,转换流,对象流,随机访问流
2020-09-02 20:29:00流 根据流的方向性,可以分为输入流和输出流。 以java为例,则输入流是由文件“流向”程序,输出流是程序“流向”文件。 ...根据数据的类型分为:字节流和字符流 字节流 :以字节为单位(byte), -
吃透Java IO:字节流、字符流、缓冲流
2021-01-23 11:30:35字节流和字符流的关系与区别? 缓冲流的效率一定高吗? 缓冲流体现了Java 中哪种设计模式思想? 为什么要实现序列化?如何实现序列化? 序列化数据后,再次修改类文件,读数据会出问题,如何解决呢? 1.初始 ... -
文件操作学习(二)字节流和字符流
2020-09-27 15:46:02在众多的流当中,InputStream、OutputStream、Reader、Writer为众多流中最顶层的父类,在这众多的流中,最常见的流已在上图中用红框标识出,首先小猿来复习字节流有关的知识,在操作系统中,我们可以把一切皆当成... -
Java中字符与字节流的转化
2018-04-12 21:37:45几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码? 要回答这个问题,必须要回答计算机是如何表示我们人类能够理解的符合的,这些符号也就是我们人类使用的... -
Java IO——字节流与字符流
2011-05-08 22:00:00Java IO——字节流与字符流 流是一个有序的字节或字符序列,可作为一个输入源,也可作为一个输出的目的地。 字节流以字节为单位输入输出,字节流类名含有stream;常见的有BufferedInputStream、... -
Java常见IO流整理,及使用方法(一)之字节流,字符流 ,Jdk7/Jdk9IO流异常处理,属性集(Properties),...
2020-04-24 18:06:531.字节流 2.字符流 3.IO流中的异常处理方式 4.属性集(Properties) 5.缓冲流 6.转换流 7.序列化 8.打印流 IO流概述 I:input 输入(读取) 把硬盘中的数据,读取到内存中使用 O:output 输出(写入) 把内存中的数据... -
Java基础——IO流(字节流、字符流)
2020-03-21 21:02:111、IO流 1.1 IO流概述和分类 IO流介绍 IO:输入/输出(Input/Output) 流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输 ...字节流 字节输入流 字节输出...
-
MinGW.zip 工具包
-
Python启蒙到架构师的核心技术精讲课程
-
flyPointData.json
-
Linux基础入门系列课程
-
APPLICATION FAILED TO START
-
搭建docker私有库的具体方法
-
多列排序-先a降序排序再按b升序排序,其中包含了排序信息-实现方法function multipleSort(data, sorts)
-
HWIDGen.zip
-
最新H5猜骰子游戏二次开发版源码.zip
-
@CSDN官方
-
git pull 之后本地代码被覆盖 解决方案
-
NFS 网络文件系统
-
项目经理成长之路
-
中兴刷机工具putty
-
08 JavaWeb - HttpServletResponse
-
expand.zip
-
vue3从0到1-超详细
-
基拉前端-源码
-
Dos命令
-
office是指什么