当前位置: 首页 > news >正文

算法题基础 : Java : BufferedReader、BufferedWriter 和 StringTokenizer 详解

BufferedReaderBufferedWriterStringTokenizer 详解

在 Java 中,处理输入输出和字符串分割时,BufferedReaderBufferedWriterStringTokenizer 是非常实用的工具类。它们在处理大量数据或频繁 IO 操作时表现出色,尤其适合算法竞赛、大数据处理等场景。下面进行更详细的介绍:

一、BufferedReader:高效字符输入流

1. 核心原理

BufferedReader 是一个带缓冲区的字符输入流,它通过在内存中设置一块缓冲区(默认 8192 字符),一次性从底层输入流(如文件、键盘)读取大量数据到缓冲区,后续读取操作直接从缓冲区获取,减少了直接访问底层资源的次数,从而大幅提升读取效率。

对比 ScannerScanner 功能丰富(支持正则解析、不同数据类型直接读取),但每次读取都可能触发底层 IO 操作,在处理 10^6 级数据时速度明显慢于 BufferedReader

2. 类定义与构造方法

// 类定义(继承自 Reader)
public class BufferedReader extends Reader {// 构造方法:接收一个底层输入流(如 InputStreamReader、FileReader)public BufferedReader(Reader in) { ... }// 构造方法:指定缓冲区大小public BufferedReader(Reader in, int sz) { ... }
}

常用底层流搭配:

  • 读取键盘输入:new BufferedReader(new InputStreamReader(System.in))
  • 读取文件:new BufferedReader(new FileReader("file.txt"))

3. 常用方法详解

方法签名功能描述示例
String readLine()读取一整行文本(不含换行符),若已到流末尾则返回 nullString line = br.readLine();
int read()读取单个字符(返回 ASCII 码,-1 表示结束)。int c = br.read();
int read(char[] cbuf)读取字符到数组 cbuf 中,返回实际读取的字符数(-1 表示结束)。char[] buf = new char[1024];<br>int len = br.read(buf);
void close()关闭流,释放资源(必须调用,否则可能导致资源泄漏)。br.close();
long skip(long n)跳过 n 个字符(用于快速定位到需要读取的位置)。br.skip(100); // 跳过前100个字符

4. 异常处理

BufferedReader 的所有读取方法都会抛出 IOException(受检异常),必须处理:

  • 方式1:在方法上声明 throws IOException(简单直接,适合算法题);
  • 方式2:使用 try-catch 捕获异常(适合生产环境代码)。

5. 适用场景

  • 算法竞赛中处理大量输入(如 10^5 行数据);
  • 读取大文件内容;
  • 需要高效按行读取文本的场景。

二、BufferedWriter:高效字符输出流

1. 核心原理

BufferedWriterBufferedReader 对应,是带缓冲区的字符输出流。它先将数据写入内存缓冲区,当缓冲区满或手动刷新时,才将数据一次性写入底层输出流(如控制台、文件),减少底层 IO 操作次数,提升写入效率。

对比 System.out.printlnSystem.out 本质是 PrintStream,每次输出可能直接触发 IO 操作,而 BufferedWriter 通过缓冲机制显著提升大量数据的写入速度。

2. 类定义与构造方法

// 类定义(继承自 Writer)
public class BufferedWriter extends Writer {// 构造方法:接收一个底层输出流(如 OutputStreamWriter、FileWriter)public BufferedWriter(Writer out) { ... }// 构造方法:指定缓冲区大小public BufferedWriter(Writer out, int sz) { ... }
}

常用底层流搭配:

  • 输出到控制台:new BufferedWriter(new OutputStreamWriter(System.out))
  • 输出到文件:new BufferedWriter(new FileWriter("output.txt"))

3. 常用方法详解

方法签名功能描述示例
void write(String str)写入字符串(不自动换行)。bw.write("hello");
void write(char[] cbuf)写入字符数组。char[] arr = {'a','b'}; bw.write(arr);
void newLine()写入换行符(跨平台,自动适配 Windows 的 \r\n 或 Linux 的 \n)。bw.newLine();
void flush()强制刷新缓冲区,将数据立即写入底层流(必须调用,否则可能数据未输出)。bw.flush();
void close()关闭流(关闭前会自动刷新缓冲区)。bw.close();

4. 关键注意点

  • 必须刷新或关闭:数据先存于缓冲区,若未调用 flush()close(),可能导致数据未写入目标流(例如程序提前结束时);
  • 换行用 newLine():避免直接写 \n\r\nnewLine() 可保证跨平台兼容性;
  • 异常处理:所有方法抛出 IOException,需同 BufferedReader 一样处理。

5. 适用场景

  • 算法竞赛中输出大量结果(如 10^6 个数字);
  • 写入大文件内容;
  • 需要高效批量输出文本的场景。

三、StringTokenizer:字符串分割工具

1. 核心功能

StringTokenizer 用于将一个字符串按指定分隔符分割成多个子串(称为“令牌”,Token),是处理简单分隔符场景的高效工具。

对比 String.split()

  • StringTokenizer:不支持正则表达式,仅按固定字符分割,但效率更高,适合空格、逗号等简单分隔;
  • String.split():支持正则表达式,功能更强大,但分割复杂字符串时效率较低。

2. 类定义与构造方法

// 类定义
public class StringTokenizer implements Enumeration<Object> {// 构造方法1:按默认分隔符(空格、制表符\t、换行符\n、回车符\r、换页符\f)分割public StringTokenizer(String str) { ... }// 构造方法2:按指定分隔符delim分割public StringTokenizer(String str, String delim) { ... }// 构造方法3:指定是否返回分隔符本身(true则分隔符也作为令牌)public StringTokenizer(String str, String delim, boolean returnDelims) { ... }
}

示例:

// 按默认分隔符分割(空格、制表符等)
StringTokenizer st1 = new StringTokenizer("a b\tc\nd");// 按逗号分割
StringTokenizer st2 = new StringTokenizer("1,2,3", ",");// 按冒号分割,且返回冒号本身
StringTokenizer st3 = new StringTokenizer("x:y:z", ":", true);

3. 常用方法详解

方法签名功能描述示例
boolean hasMoreTokens()判断是否还有未处理的令牌(子串)。while (st.hasMoreTokens()) { ... }
String nextToken()返回下一个令牌,若没有则抛出 NoSuchElementExceptionString token = st.nextToken();
int countTokens()返回剩余的令牌数量(估计值,可能因分隔符设置变化)。int count = st.countTokens();

4. 典型用法(算法题输入分割)

算法题中常需读取一行空格分隔的数字,用 StringTokenizer 分割效率最高:

String line = "3 1 4 1 5";
StringTokenizer st = new StringTokenizer(line);
int n = Integer.parseInt(st.nextToken()); // 3
int a = Integer.parseInt(st.nextToken()); // 1
// 依次读取后续数字...

5. 局限性

  • 不支持正则表达式(如无法用 \d+ 分割数字);
  • 无法直接获取所有令牌(需循环调用 nextToken());
  • 不保留空令牌(例如 "a,,b" 按逗号分割时,会忽略中间的空字符串)。

四、三者协同使用示例(算法题场景)

下面是一个完整示例,展示如何用三者处理输入输出:

import java.io.*;
import java.util.StringTokenizer;public class Main {public static void main(String[] args) throws IOException {// 1. 初始化输入输出流BufferedReader br = new BufferedReader(new InputStreamReader(System.in));BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));// 2. 读取第一行:n和q(如区间加问题的输入)StringTokenizer st = new StringTokenizer(br.readLine());int n = Integer.parseInt(st.nextToken());int q = Integer.parseInt(st.nextToken());// 3. 处理q次操作int[] arr = new int[n + 1]; // 1-based索引for (int i = 0; i < q; i++) {st = new StringTokenizer(br.readLine());int li = Integer.parseInt(st.nextToken());int ri = Integer.parseInt(st.nextToken());int vi = Integer.parseInt(st.nextToken());// 区间内vi的倍数加1(核心逻辑)for (int j = li; j <= ri; j++) {if (j % vi == 0) {arr[j]++;}}}// 4. 输出结果for (int i = 1; i <= n; i++) {bw.write(arr[i] + "");}// 5. 释放资源bw.flush(); // 确保数据输出br.close();bw.close();}
}

总结

核心优势典型应用场景性能特点
BufferedReader高效读取文本,减少IO次数算法题大量输入、大文件读取速度远快于 Scanner
BufferedWriter高效写入文本,缓冲减少IO次数算法题大量输出、大文件写入速度远快于 System.out
StringTokenizer简单分隔符分割字符串,效率高空格/逗号分隔的输入解析(如算法题)速度快于 String.split()(简单场景)

掌握这三个类的使用,能显著提升 Java 程序处理输入输出的效率,尤其在时间敏感的算法竞赛中,是提升程序性能的关键技巧。

http://www.dtcms.com/a/464972.html

相关文章:

  • 企业微信 自建应用审批流程引擎功能开发【报错分析】
  • Slf4j 接口文档左侧菜单有显示,但是点击后空白
  • 【AES加密专题】4.Sbox的解析和生成
  • 考完HCIE数通,能转云计算 / 安全 / AI方向吗?
  • 重庆企业网站建设推荐怎么申请域名和备案
  • 松江 网站建设公司拼多多推广联盟
  • 中国极端气象干旱事件(1951-2022)
  • 一文详解Go 语言内存逃逸(Escape Analysis)
  • 学习threejs,实现粒子化交互文字
  • 密码学基础:RSA与AES算法的实现与对比
  • RAG:生成与检索的完美结合
  • 一款由网易出品的免费、低延迟、专业的远程控制软件,支持手机、平板、Mac 、PC、TV 与掌机等多设备远控电脑!
  • [C# starter-kit] Blazor EntityTable 组件 | 预构建
  • 深入浅出 AI Agent:从概念本质到技术基石
  • 宁波网站制作服务wordpress搭建淘客网站
  • 第五章:Go的“面向对象”编程
  • 【实用工具】mac电脑计算文件的md5、sha1、sha256
  • 数据结构算法学习:LeetCode热题100-矩阵篇(矩阵置零、螺旋矩阵、旋转图像、搜索二维矩阵 II)
  • CAD文件处理控件Aspose.CAD教程:在 Python 中将 SVG 转换为 PDF
  • Go语言游戏后端开发9:Go语言中的结构体
  • 网页网站作业制作郑州企业网站排名
  • C4D域的应用之鞋底生长动画制作详解
  • C语言自学--文件操作
  • 免费小程序网站网站建设优劣的评价标准
  • Kubernetes(K8S)全面解析:核心概念、架构与实践指南
  • 软件测试分类指南(上):从目标、执行到方法,系统拆解测试核心维度
  • 李宏毅机器学习笔记18
  • 深圳做网站优化工资多少长沙官网seo分析
  • 深入理解SELinux:从核心概念到实战应用
  • W5500接收丢数据