java io 输入输出流

本文深入讲解Java中的IO流概念及分类,包括字节流与字符流的区别,常见类的继承结构,装饰器模式的应用,以及RandomAccessFile的特性和使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

字节流处理类 1

1.1 字节流详细介绍 1

1.2 控制台的输入输出 3

2 字符流处理类 4

3 RandomAccessFile 5

文件类型 7

5 txt按行处理程序 7

字节流处理类

1.1 字节流详细介绍

字节流:处理字节数据的流对象。设备上的数据无论是图片或者dvd,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。

 

那么为什么要有字符流呢?因为字符每个国家都不一样,所以涉及到了字符编码问题,那么GBK编码的中文用unicode编码解析是有问题的,所以需要获取中文字节数据的同时指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。

InputStream和OutputStream的常用类继承架构

 InputStream

ByteInputStream

 

 

ObjectInputStream

 

 

FileInputStream

 BufferedInputStream

 

FilterInputStream

 DataInputStream

 

 OutputStream

ByteOutputStream

 

 

ObjectOutputStream

 BufferedOutputStream

 

FileOutputStream

 DataOutputStream

 

FilterOutputStream

 PrintStream


Reader和Writer常用类继承架构

Reader

CharArrayReader

 

 

StringReader

 

 

BufferedReader

 

 

InputStreamReader

 FileReader


 

 Writer

 CharArrayWriter

 

 

 StringWriter

 

 

 BufferedWriter

 

 

 OutputStreamWriter

 FileWriter

 

 PrintWriter

 

 

串流处理装饰器:专职用于打包,方便数据操作。

常用的打包器有:

具备缓冲区作用的BufferedInputStream、 BufferedOutputStream(如果没有缓存,每次读写都要定位硬盘,效率显得很低。使用缓存可以减少读写次数,读写效率也大大提高,毕竟内存的读取速度很快)

具备数据转换处理作用的DataInputStream、 DataOutputStream(提供和读取、写入java基本数据类型的方法,像是读写int、double、boolean等方法。这些方法会在指定的类型与字节之间进行转换,不需要你亲自做字节与类型转换的动作)

具备对象串行化能力的ObjectInputStream、 ObjectOutputStream(ObjectInputStream提供readObject()方法将数据读入为对象,而ObjectOutputStream提供writeObject()方法将对象写至目的地,可以被这两个方法处理的对象,必须操作java.io.Serializable接口,这个接口并没有定义任何方法,只是作为标示之用,表示这个对象是可以串行化的(Serializable))

由于这些类本身并没有改变 InputStream、OutputStream 的行为,只不过在 InputStream 取得数据之后,再做一些加工处理,或者是要输出时做一些加工处理,再交由 OutputStream 真正进行输出,因此又称它们为装饰器(Decorator)。就像照片本身装上华丽外框,就可以让照片感觉更为华丽,或有点像小水管衔接大水管,如小水管(InputStream)读入数据,再由大水管(如BufferedInputStream)增加缓冲功能,如图10.5所示。

1.2 控制台的输入输出

System.in与System.out分别是InputStream与PrintStream的实例,分别代表标准输入(Standard input)与标准输出(Standard output),以个人计算机而言,通常对应至文本模式中的输入与输出。【控制台自动将字节数组数据解码为对应数据,类似与记事本打开就已经解码】

以System.in而言,因为文本模式下通常是取得整行用户输入,因此较少直接操作InputStream相关方法,如使java.util.Scanner打包System.in。操作Scanner相关方法时,Scanner会代你操控System.in取得数据,并转换为取得你想要的数据类型。

可以使用System的setIn()方法指定InputStream实例,重新指定标准输入来源

Scanner常用方法示例:s.hasNextInt();s.nextInt();等

System.out有静态方法print(),println(),可以直接打印出相应字符数据,如果是整形数据或通过String.valueOf(i)转换成字符输出; 以通过System.setOut()重新指定标准输出流串。

System.err也是PrintStream实例,称为标准错误输出流,可以通过System.setErr()重新指定标准错误输出流串。

 

2 字符流处理类

InputStream、OutputStream是用来读入与写出字节数据,若实际上处理的是字符数据,使用InputStream、OutputStream就得对照编码表,在字符与字节之间进行转换。所幸Java SE API已提供相关输入/输出字符处理类,让你不用亲自进行字节与字符编码转换的枯燥工作。

正如同InputStream、OutputStream有一些装饰器类,可以对InputStream、OutputStream打包增加额外功能,Reader、Writer也有一些装饰器类可供使用。下面介绍常用的字符处理装饰器类。

如果串流处理的字节数据,实际上代表某些字符的编码数据,而你想要将这些字节数据转换为对应的编码字符,可以使用InputStreamReader、OutputStreamWriter对串流数据打包

在建立InputStreamReader与OutputStreamWriter时,可以指定编码,如果没有指定编码,则以JVM启动时所获取的默认编码来做字符转换。

正如BufferedInputStream、BufferedOutputStream为InputStream、OutputStream提供缓冲区作用,以改进输入/输出的效率,BufferedReader、BufferedWriter可对Reader、Writer提供缓冲区作用,在处理字符输入/输出时,对效率也会有所帮助。

就装饰器的作用而言,InputStreamReader将System.in读入的字节数据做编码转换,而BufferedReader将编码转换后的数据做缓冲处理,以增加读取效率。BufferedReader的readLine()方法,可以读取一行数据(以换行字符为依据)并以字符串返回,返回的字符串不包括换行字符。

代码示例:

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));  

String name = reader.readLine();  

System.out.printf("Hello, %s!", name);  

PrintWriter与PrintStream使用上极为类似,不过除了可以对OutputStream打包之外,PrintWriter还可以对Writer进行打包,提供print()println()format()等方法。

 

3 RandomAccessFile

Java的RandomAccessFile提供对文件的读写功能,与普通的输入输出流不一样的是RamdomAccessFile可以任意的访问文件的任何地方。这就是“Random”的意义所在。

RandomAccessFile的对象包含一个记录指针,用于标识当前流的读写位置,这个位置可以向前移动,也可以向后移动。RandomAccessFile包含两个方法来操作文件记录指针。

long getFilePoint():记录文件指针的当前位置。

void seek(long pos):将文件记录指针定位到pos位置。

RandomAccessFile包含InputStream的三个read方法,也包含OutputStream的三个write方法。同时RandomAccessFile还包含一系列的readXxx和writeXxx方法完成输入输出。

使用示例:

import java.io.*;
public class RandomAccessFileDemo {

 public static void main(String[] args) throws IOException {
  RandomAccessFile raf = new RandomAccessFile("e:/mm.txt","rw");
      writeFile(raf);
 }
 public static void writeFile(RandomAccessFile raf) throws IOException
 {
  raf.write("张三".getBytes());
  raf.writeInt(97);
  raf.write("李四".getBytes());
  raf.writeInt(98);
  raf.close();
 }
}

 

 

文件类型

 

1)文本文件:每一个字符都被表示成1个或2个字节,具体方式依赖于该系统使用ASCII还是Unicode编码。例如int型值12345写入文件,将在该文件中放入5个字符。直接使用FileInputStreamFileOutputStream就可以读取和写入文本文件。

2)二进制文件:以相同格式存储同种基本类型数据的值。每个值都被存储为一连串相同个数的字节。例如:int型值12345写入文件,将在该文件中占据4个字节。使用ObjectInputStreamObjectOutputStream读取和写入二进制文件。(本质上就是个基本类型的包装类处理)具体使用示例:new ObjectInputStream(new FileInputStream(“x.txt”));

此外,类的串行化可将对象直接存入二进制文件。【串行化需要先将类实现Serializable接口】

(3)使用情形:如果想让文本编辑器或者创建一个程序将读取该文件,那么使用文本文件;在其他情况下,考虑使用二进制文件,原因是二进制文件通常占据更少的空间。

 

 

5 txt按行处理程序

package txt;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.Test;
/**
 *
 * 直接通过输入输出流读取文件
 * 需要完成:
 *
 */
public class JavaConstant {
    
 public static String readDoc(String filePath){
  File file = new File(filePath);
  FileReader fr = null;
  String content = "";
  String tempContent = null;
  String tempContent1 = null;
  try {
   fr = new FileReader(file);
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  }
  BufferedReader br = new BufferedReader(fr);
         while(true){
          try {
           //对每一行进行读取,然后处理
     tempContent = br.readLine();
     tempContent1 = "public final static int "+tempContent+"\r\n";
     tempContent1 = replace(tempContent1)+";\r\n";
    } catch (IOException e) {
     e.printStackTrace();
    }
          if(tempContent!=null){
           content +=tempContent1;
           System.out.println(content);
          }else{
           break;
          }
         }
         try {
   br.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
         try {
   fr.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
  return content;
 }
 public static boolean writeDoc(String filePath,String content){
   FileWriter fw = null;
  try {
   fw = new FileWriter(filePath);
  } catch (IOException e) {
   e.printStackTrace();
  }
         BufferedWriter bw = new BufferedWriter(fw);
         try {
   bw.write(content);
  } catch (IOException e) {
   e.printStackTrace();
  }
         try {
   bw.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
         try {
   fw.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
         return true;
 }
 public static String replace(String content){   
  //content="RESP_A_AZS表示0x00010001.";   
  String result = null;
        String regex1="[A-Z][^A-Z]{0,}0x\\d{4}.{0,}";   
        Pattern p;   
        Matcher m;   
        p=Pattern.compile(regex1);   
        m=p.matcher(content);   
        while(m.find()){   
         String x=m.group(); 
         CharSequence target = x.substring(1,x.indexOf("0x"));
         System.out.println("要替换的内容:"+target);
         String regex2=".{0,}[A-Z][^A-Z]{0,}0x\\d{4}.{0,}"; 
         p = Pattern.compile(regex2);
         m=p.matcher(content); 
         if(m.find()){
          x=m.group();
          System.out.println("全部内容:"+x);
         }
   CharSequence replacement = " = ";
   result = x.replace(target, replacement);
   System.out.println("替换后:"+x);
        }
        return result;
 }
 @Test
 public void testRead(){
  String filePath = "C:\\in.txt";
  String content = readDoc(filePath);
  System.out.println(content);
  if(writeDoc("C:\\out.txt", content)){
   System.out.println("文件写入成功!");
  }
 }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值