java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java获取文字中文字符数量

Java实现获取一段文字中文字符数量的工具类

作者:Katie。

随着互联网时代的到来,各类应用中对于文本的处理日益频繁,本文将设计实现一个通用的 Java 工具类,能够高效准确地统计一段文本中 中文字符的数量,感兴趣的可以了解下

1. 项目背景详细介绍

随着互联网时代的到来,各类应用中对于文本的处理日益频繁,其中往往需要对不同语言的字符进行分析与统计。在多语言混排的文本中,中文字符、英文字符、数字、标点符号等并存,而许多业务场景需要单独统计中文字符的数量。典型场景包括:

因此,本项目旨在设计并实现一个通用的 Java 工具类,能够高效、准确地统计一段文本中 中文字符 的数量。工具类应兼容各类 Java 环境,接口简单易用,并提供丰富的单元测试与文档说明,方便集成到各种 Java 应用中。

2. 项目需求详细介绍

为确保工具类功能完整、健壮易用,需明确以下 功能需求非功能需求

2.1 功能需求

中文字符统计

支持批量处理

可扩展正则

空值与异常处理

2.2 非功能需求

接口设计

性能

线程安全

测试覆盖

使用 JUnit 编写单元测试,覆盖正常和边界场景:中英混排、Emoji、全空、全中文、大文本等;

文档与注释

3. 相关技术详细介绍

实现上述功能,需要掌握或了解以下 Java 核心技术点:

3.1 正则表达式(java.util.regex)

Pattern 与 Matcher

Unicode 区间

3.2 字符与码点

流式 API(Java 8+)

3.3 IO 与大文本处理

Reader 与 BufferedReader

对于大文本,可支持 count(Reader),逐行或逐块读取并统计,降低内存压力;

并发与分段统计

可将大文本分为多段,在多个线程中并发处理,最后汇总结果;

3.4 单元测试

JUnit 5

4. 实现思路详细介绍

根据需求与技术选型,设定以下设计思路:

1.工具类与实例类分离

public final class ChineseCounter

public class ChineseCounter.Instance

接受自定义正则或 Unicode 区间;

内部持有 Pattern 实例,复用匹配;

2.静态方法实现

public static int countChinese(String text) {
    if (text == null || text.isEmpty()) return 0;
    Matcher m = DEFAULT_PATTERN.matcher(text);
    int count = 0;
    while (m.find()) count++;
    return count;
}

流式方法实现

public static long countByCodePoint(String text) {
    if (text == null) return 0;
    return text.codePoints()
        .filter(cp -> cp >= 0x4E00 && cp <= 0x9FFF)
        .count();
}

Reader 版本

public static int countChinese(Reader reader) {
    BufferedReader br = new BufferedReader(reader);
    String line;
    int total = 0;
    while ((line = br.readLine()) != null) {
        total += countChinese(line);
    }
    return total;
}

5. 完整实现代码

// 文件:ChineseCounter.java
package com.example.textcounter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 中文字符统计工具类
 * 支持静态方法与可配置实例对象两种方式
 */
public final class ChineseCounter {
    // 默认匹配汉字的正则:包含常用汉字(CJK Unified Ideographs)
    private static final Pattern DEFAULT_PATTERN = Pattern.compile("[\\u4E00-\\u9FFF]");

    // 私有构造,禁止实例化
    private ChineseCounter() {}

    /**
     * 静态方法:统计字符串中的中文字符数量(使用默认范围)
     * @param text 输入文本
     * @return 中文字符个数
     */
    public static int countChinese(String text) {
        if (text == null || text.isEmpty()) return 0;
        Matcher matcher = DEFAULT_PATTERN.matcher(text);
        int count = 0;
        while (matcher.find()) {
            count++;
        }
        return count;
    }

    /**
     * 静态方法:基于字符码点方式统计中文数量(推荐:性能更优)
     * @param text 输入文本
     * @return 中文字符个数
     */
    public static long countChineseByCodePoint(String text) {
        if (text == null) return 0;
        return text.codePoints()
            .filter(cp -> (cp >= 0x4E00 && cp <= 0x9FFF)) // 可扩展至其他 Unicode 区
            .count();
    }

    /**
     * 静态方法:按行读取字符流并统计中文数量(适合大文本)
     * @param reader 字符流 Reader
     * @return 中文字符个数
     * @throws IOException 读取异常
     */
    public static int countChinese(Reader reader) throws IOException {
        if (reader == null) return 0;
        BufferedReader br = new BufferedReader(reader);
        String line;
        int total = 0;
        while ((line = br.readLine()) != null) {
            total += countChinese(line);
        }
        return total;
    }

    /**
     * 可配置实例类(支持自定义正则)
     */
    public static class Instance {
        private final Pattern pattern;

        /**
         * 使用正则表达式创建统计实例
         * @param regex 自定义正则(必须非空)
         */
        public Instance(String regex) {
            if (regex == null || regex.isEmpty()) {
                throw new IllegalArgumentException("正则表达式不能为空");
            }
            this.pattern = Pattern.compile(regex);
        }

        /**
         * 使用 Unicode 范围创建统计实例
         * @param start 起始码点(如 0x4E00)
         * @param end   结束码点(如 0x9FFF)
         */
        public Instance(int start, int end) {
            if (start > end) {
                throw new IllegalArgumentException("起始码点不能大于结束码点");
            }
            String regex = String.format("[%s-%s]",
                new String(Character.toChars(start)),
                new String(Character.toChars(end)));
            this.pattern = Pattern.compile(regex);
        }

        /**
         * 使用该实例统计字符串中的匹配字符数量
         * @param text 输入文本
         * @return 匹配字符数量
         */
        public int count(String text) {
            if (text == null || text.isEmpty()) return 0;
            Matcher matcher = pattern.matcher(text);
            int count = 0;
            while (matcher.find()) {
                count++;
            }
            return count;
        }
    }
}
// 文件:ChineseCounterTest.java
package com.example.textcounter;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

/**
 * 中文字符统计测试类
 */
public class ChineseCounterTest {

    @Test
    public void testNullAndEmpty() {
        assertEquals(0, ChineseCounter.countChinese(null));
        assertEquals(0, ChineseCounter.countChinese(""));
    }

    @Test
    public void testMixedContent() {
        String text = "你好,world!123";
        assertEquals(2, ChineseCounter.countChinese(text));
    }

    @Test
    public void testOnlyChinese() {
        String text = "这是纯中文";
        assertEquals(5, ChineseCounter.countChinese(text));
    }

    @Test
    public void testCodePointMethod() {
        String text = "ABC和中文组合🙂";
        assertEquals(3, ChineseCounter.countChineseByCodePoint(text));
    }

    @Test
    public void testCustomInstanceRegex() {
        ChineseCounter.Instance custom = new ChineseCounter.Instance("[\\u4E00-\\u9FFF]");
        assertEquals(4, custom.count("中英文混排测试"));
    }

    @Test
    public void testUnicodeRange() {
        ChineseCounter.Instance range = new ChineseCounter.Instance(0x4E00, 0x9FFF);
        assertEquals(2, range.count("Hello中国"));
    }

    @Test
    public void testInvalidRegex() {
        assertThrows(IllegalArgumentException.class, () -> new ChineseCounter.Instance(""));
    }

    @Test
    public void testInvalidUnicodeRange() {
        assertThrows(IllegalArgumentException.class, () -> new ChineseCounter.Instance(0x9FFF, 0x4E00));
    }
}

6. 代码详细解读(方法作用说明)

7. 项目详细总结

本项目实现了一个轻量级、高性能、可复用的中文字符统计工具。它通过 Java 正则表达式、字符码点等核心技术,准确识别一段文字中的常用中文字符数量,并提供了灵活的 API 接口:

本工具可广泛应用于文本分析、内容审核、界面字符计数等需求场景中,也可作为其他 NLP 工具的子模块进行集成。

8. 项目常见问题及解答

Q1: 为什么正则只用了 [\\u4E00-\\u9FFF]?

这是最常用的 CJK 汉字区,基本能覆盖日常中文应用。若需要扩展到 CJK 扩展 A/B/C 区,可在 countChineseByCodePoint() 中修改范围。

Q2: 是否支持统计标点符号、日文、韩文?

默认不支持。如果需要,可通过实例化构造器传入包含这些字符的正则(如 [\u4E00-\u9FFF\u3000-\u303F])。

Q3: 对 emoji 有影响吗?

没有影响,emoji 属于 Unicode 较高区段,不会被默认正则匹配。

Q4: 处理超大文本安全吗?

是。通过 Reader 输入并逐行处理的版本可以用于几 MB 甚至 GB 级别的文本处理。

Q5: 线程安全吗?

工具类无状态;实例类仅读共享 Pattern,是线程安全的;可放心在并发环境中使用。

9. 扩展方向与性能优化

1.多 Unicode 范围支持

2.字符频率统计

3.多线程加速

将长文本切片后在并行流中统计,进一步提升性能;

4.使用 Re2J 替代 JDK 正则引擎

对正则匹配密集场景可提高性能;

5.集成语言识别与 NLP 模块

搭配 HanLP、Jieba 分词库进一步识别实体、语法等。

到此这篇关于Java实现获取一段文字中文字符数量的工具类的文章就介绍到这了,更多相关Java获取文字中文字符数量内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文