Java IO流——字节流和字符流

来源:互联网 发布:网络电话 知乎 编辑:程序博客网 时间:2024/05/17 07:23

来源IT资料库:http://www.itzlk.com/io/361.jhtml

关于字节流和字符流的概念:请参考——java IO流的概念与分类

 

使用字节流好还是字符流好呢?

答案是字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。 


【案例1】使用RandomAccessFile写入文件

  1. /**
  2.   * 使用RandomAccessFile写入文件
  3.  * */
  4. import java.io.*;
  5. class hello{
  6.     public static void main(String[] args) throws IOException {
  7.         String fileName="D:"+File.separator+"hello.txt";
  8.         File f=new File(fileName);
  9.         RandomAccessFile demo=new RandomAccessFile(f,"rw");
  10.         demo.writeBytes("asdsad");
  11.         demo.writeInt(12);
  12.         demo.writeBoolean(true);
  13.         demo.writeChar('A');
  14.         demo.writeFloat(1.21f);
  15.         demo.writeDouble(12.123);
  16.         demo.close();   
  17.     }
  18. }

如果你此时打开hello.txt查看的话,会发现那是乱码。


  • 字节流

 

【案例2】向文件中写入字符串

  1. /**
  2.  * 字节流
  3.  * 向文件中写入字符串
  4.  * */
  5. import java.io.*;
  6. class hello{
  7.     public static void main(String[] args) throws IOException {
  8.         String fileName="D:"+File.separator+"hello.txt";
  9.         File f=new File(fileName);
  10.         OutputStream out =new FileOutputStream(f);
  11.         String str="你好";
  12.         byte[] b=str.getBytes();
  13.         out.write(b);
  14.         out.close();
  15.     }
  16. }

查看hello.txt会看到“你好”

 

当然也可以一个字节一个字节的写。

  1. /**
  2.  * 字节流
  3.  * 向文件中一个字节一个字节的写入字符串
  4.  * */
  5. import java.io.*;
  6. class hello{
  7.     public static void main(String[] args) throws IOException {
  8.         String fileName="D:"+File.separator+"hello.txt";
  9.         File f=new File(fileName);
  10.         OutputStream out =new FileOutputStream(f);
  11.         String str="你好";
  12.         byte[] b=str.getBytes();
  13.         for (int i = 0; i < b.length; i++) {
  14.             out.write(b[i]);
  15.         }
  16.         out.close();
  17.     }
  18. }

结果还是:“你好”



【案例3】向文件中追加新内容:

  1. /**
  2.  * 字节流
  3.  * 向文件中追加新内容:
  4.  * */
  5. import java.io.*;
  6. class hello{
  7.     public static void main(String[] args) throws IOException {
  8.         String fileName="D:"+File.separator+"hello.txt";
  9.         File f=new File(fileName);
  10.         OutputStream out =new FileOutputStream(f,true);
  11.         String str="Rollen";
  12.         //String str="\r\nRollen";  可以换行
  13.         byte[] b=str.getBytes();
  14.         for (int i = 0; i < b.length; i++) {
  15.             out.write(b[i]);
  16.         }
  17.         out.close();
  18.     }
  19. }

【运行结果】:你好Rollen



【案例4】读取文件内容

  1. /**
  2.  * 字节流
  3.  * 读文件内容
  4.  * */
  5. import java.io.*;
  6. class hello{
  7.     public static void main(String[] args) throws IOException {
  8.         String fileName="D:"+File.separator+"hello.txt";
  9.         File f=new File(fileName);
  10.         InputStream in=new FileInputStream(f);
  11.         byte[] b=new byte[1024];
  12.         in.read(b);
  13.         in.close();
  14.         System.out.println(new String(b));
  15.     }
  16. }

【运行结果】

你好Rollen

 

 

但是这个例子读取出来会有大量的空格,我们可以利用in.read(b);的返回值来设计程序。如下:

  1. /**
  2.  * 字节流
  3.  * 读文件内容
  4.  * */
  5. import java.io.*;
  6. class hello{
  7.     public static void main(String[] args) throws IOException {
  8.         String fileName="D:"+File.separator+"hello.txt";
  9.         File f=new File(fileName);
  10.         InputStream in=new FileInputStream(f);
  11.         byte[] b=new byte[1024];
  12.         int len=in.read(b);
  13.         in.close();
  14.         System.out.println("读入长度为:"+len);
  15.         System.out.println(new String(b,0,len));
  16.     }
  17. }

【运行结果】:

读入长度为:12

你好Rollen

注:win7操作系统默认字符编码为utf8,"你好"占6个字节

 


读者观察上面的例子可以看出,我们预先申请了一个指定大小的空间,但是有时候这个空间可能太小,有时候可能太大,我们需要准确的大小,这样节省空间,那么我们可以这样干:

  1. /**
  2.  * 字节流
  3.  * 读文件内容,节省空间
  4.  * */
  5. import java.io.*;
  6. class hello{
  7.     public static void main(String[] args) throws IOException {
  8.         String fileName="D:"+File.separator+"hello.txt";
  9.         File f=new File(fileName);
  10.         InputStream in=new FileInputStream(f);
  11.         byte[] b=new byte[(int)f.length()];
  12.         in.read(b);
  13.         System.out.println("文件长度为:"+f.length());
  14.         in.close();
  15.         System.out.println(new String(b));
  16.     }
  17. }

读入长度为:12

你好Rollen


将上面的例子改为一个一个读:

  1. /**
  2.  * 字节流
  3.  * 读文件内容,节省空间
  4.  * */
  5. import java.io.*;
  6. class hello{
  7.     public static void main(String[] args) throws IOException {
  8.         String fileName="D:"+File.separator+"hello.txt";
  9.         File f=new File(fileName);
  10.         InputStream in=new FileInputStream(f);
  11.         byte[] b=new byte[(int)f.length()];
  12.         for (int i = 0; i < b.length; i++) {
  13.             b[i]=(byte)in.read();
  14.         }
  15.         in.close();
  16.         System.out.println(new String(b));
  17.     }
  18. }

输出的结果和上面的一样。


细心的读者可能会发现,上面的几个例子都是在知道文件的内容多大,然后才展开的,有时候我们不知道文件有多大,这种情况下,我们需要判断是否独到文件的末尾。

  1. /**
  2.  * 字节流
  3.  *读文件
  4.  * */
  5. import java.io.*;
  6. class hello{
  7.     public static void main(String[] args) throws IOException {
  8.         String fileName="D:"+File.separator+"hello.txt";
  9.         File f=new File(fileName);
  10.         InputStream in=new FileInputStream(f);
  11.         byte[] b=new byte[1024];
  12.         int count =0;
  13.         int temp=0;
  14.         while((temp=in.read())!=(-1)){
  15.             b[count++]=(byte)temp;
  16.         }
  17.         in.close();
  18.         System.out.println(new String(b));
  19.     }
  20. }

【运行结果】

你好Rollen

提醒一下,当独到文件末尾的时候会返回-1.正常情况下是不会返回-1



  • 字符流

 

【案例5】向文件中写入数据

 

现在我们使用字符流

  1. /**
  2.  * 字符流
  3.  * 写入数据
  4.  * */
  5. import java.io.*;
  6. class hello{
  7.     public static void main(String[] args) throws IOException {
  8.         String fileName="D:"+File.separator+"hello.txt";
  9.         File f=new File(fileName);
  10.         Writer out =new FileWriter(f);
  11.         String str="hello";
  12.         out.write(str);
  13.         out.close();
  14.     }
  15. }

当你打开hellotxt的时候,会看到hello

其实这个例子上之前的例子没什么区别,只是你可以直接输入字符串,而不需要你将字符串转化为字节数组。

当你如果想问文件中追加内容的时候,可以使用将上面的声明out的哪一行换为: 

Writer out =new FileWriter(f,true);

这样,当你运行程序的时候,会发现文件内容变为:

hellohello如果想在文件中换行的话,需要使用“\r\n

比如将str变为String str="\r\nhello";

这样文件追加的str的内容就会换行了。

 

 

【案例5】从文件中读内容:

  1. /**
  2.  * 字符流
  3.  * 从文件中读出内容
  4.  * */
  5. import java.io.*;
  6. class hello{
  7.     public static void main(String[] args) throws IOException {
  8.         String fileName="D:"+File.separator+"hello.txt";
  9.         File f=new File(fileName);
  10.         char[] ch=new char[100];
  11.         Reader read=new FileReader(f);
  12.         int count=read.read(ch);
  13.         read.close();
  14.         System.out.println("读入的长度为:"+count);
  15.         System.out.println("内容为"+new String(ch,0,count));
  16.     }
  17. }

【运行结果】:

读入的长度为:5

内容为hello

 


当然最好采用循环读取的方式,因为我们有时候不知道文件到底有多大。

  1. /**
  2.  * 字符流
  3.  * 从文件中读出内容
  4.  * */
  5. import java.io.*;
  6. class hello{
  7.     public static void main(String[] args) throws IOException {
  8.         String fileName="D:"+File.separator+"hello.txt";
  9.         File f=new File(fileName);
  10.         char[] ch=new char[100];
  11.         Reader read=new FileReader(f);
  12.         int temp=0;
  13.         int count=0;
  14.         while((temp=read.read())!=(-1)){
  15.             ch[count++]=(char)temp;
  16.         }
  17.         read.close();
  18.         System.out.println("内容为"+new String(ch,0,count));
  19.     }
  20. }

运行结果:

读入的长度为:5

内容为hello

 

读者可以试着将上面的字节流和字符流的程序的最后一行关闭文件的代码注释掉,然后运行程序看看。你就会发现使用字节流的话,文件中已经存在内容,但是使用字符流的时候,文件中还是没有内容的,这个时候就要刷新缓冲区。

 

 

【案例6】文件的复制

其实DOS下就有一个文件复制功能,比如我们想把d盘下面的hello.txt文件复制到d盘下面的rollen.txt文件中,那么我们就可以使用下面的命令:

copy d:\hello.txt d:\rollen.txt

运行之后你会在d盘中看见rollen.txt

下面我们使用程序来复制文件。

基本思路还是从一个文件中读入内容,边读边写入另一个文件,就是这么简单。

 

首先编写下面的代码:

  1. /**
  2.  * 文件的复制
  3.  * */
  4. import java.io.*;
  5. class hello{
  6.     public static void main(String[] args) throws IOException {
  7.         if(args.length!=2){
  8.             System.out.println("命令行参数输入有误,请检查");
  9.             System.exit(1);
  10.         }
  11.         File file1=new File(args[0]);
  12.         File file2=new File(args[1]);
  13.          
  14.         if(!file1.exists()){
  15.             System.out.println("被复制的文件不存在");
  16.             System.exit(1);
  17.         }
  18.         InputStream input=new FileInputStream(file1);
  19.         OutputStream output=new FileOutputStream(file2);
  20.         if((input!=null)&&(output!=null)){
  21.             int temp=0;
  22.             while((temp=input.read())!=(-1)){
  23.                 output.write(temp);
  24.             }
  25.         }
  26.         input.close();
  27.         output.close(); 
  28.     }
  29. }

然后在命令行下面

javac hello.java

java hello d:\hello.txt d:\rollen.txt

现在你就会在d盘看到rollen.txt了,

 

OutputStreramWriter 和InputStreamReader类

整个IO类中除了字节流和字符流还包括字节和字符转换流。

OutputStreramWriter将输出的字符流转化为字节流

InputStreamReader将输入的字节流转换为字符流

但是不管如何操作,最后都是以字节的形式保存在文件中的。


将字节输出流转化为字符输出流

  1. /**
  2.  * 将字节输出流转化为字符输出流
  3.  * */
  4. import java.io.*;
  5. class hello{
  6.     public static void main(String[] args) throws IOException {
  7.         String fileName= "d:"+File.separator+"hello.txt";
  8.         File file=new File(fileName);
  9.         Writer out=new OutputStreamWriter(new FileOutputStream(file));
  10.         out.write("hello");
  11.         out.close();
  12.     }
  13. }

【运行结果】:文件中内容为:hello

 

将字节输入流变为字符输入流

  1. /**
  2.  * 将字节输入流变为字符输入流
  3.  * */
  4. import java.io.*;
  5. class hello{
  6.     public static void main(String[] args) throws IOException {
  7.         String fileName= "d:"+File.separator+"hello.txt";
  8.         File file=new File(fileName);
  9.         Reader read=new InputStreamReader(new FileInputStream(file));
  10.         char[] b=new char[100];
  11.         int len=read.read(b);
  12.         System.out.println(new String(b,0,len));
  13.         read.close();
  14.     }
  15. }

【运行结果】:hello

 

【案例7】内存操作流

前面列举的输出输入都是以文件进行的,现在我们以内容为输出输入目的地,使用内存操作流

ByteArrayInputStream 主要将内容写入内容

ByteArrayOutputStream  主要将内容从内存输出

 

使用内存操作流将一个大写字母转化为小写字母

  1. /**
  2.  * 使用内存操作流将一个大写字母转化为小写字母
  3.  * */
  4. import java.io.*;
  5. class hello{
  6.     public static void main(String[] args) throws IOException {
  7.         String str="ROLLENHOLT";
  8.         ByteArrayInputStream input=new ByteArrayInputStream(str.getBytes());
  9.         ByteArrayOutputStream output=new ByteArrayOutputStream();
  10.         int temp=0;
  11.         while((temp=input.read())!=-1){
  12.             char ch=(char)temp;
  13.             output.write(Character.toLowerCase(ch));
  14.         }
  15.         String outStr=output.toString();
  16.         input.close();
  17.         output.close();
  18.         System.out.println(outStr);
  19.     }
  20. }

【运行结果】:rollenholt

内容操作流一般使用来生成一些临时信息采用的,这样可以避免删除的麻烦。

0 0
原创粉丝点击