moonreader

    MoonReader — 纯 MoonBit 实现的文件内容读取库(TXT / CSV / JSON / JSONL / TAR)

    Download zip
    Author
    Version
    0.1.2
    License
    Apache-2.0
    Last updated
    17 hours ago
    Downloads
    4

    Dependencies

    #MoonReader

    纯 MoonBit 实现的文件内容读取库,支持 TXT / CSV / JSON / JSONL / XML / Markdown / ZIP / TAR / DOCX / XLSX / PPTX / PDF 十二种格式,全程中文文件名友好(Windows 下 UTF-8 路径感知)。

    定位:面向信创 / 国产化场景,纯 MoonBit 实现多类型文件内容读取。

    #快速开始

    // 一键读取:按扩展名自动识别格式
    let content = @moonreader.read("data/sample.csv")
    match content {
    Table(rows) => for row in rows { ... }
    Lines(lines) => ...
    JsonValue(j) => ...
    JsonRows(js) => ...
    XmlDoc(root) => ...
    MarkdownBlocks(blocks) => ...
    ZipFiles(entries) => ...
    TarFiles(entries) => ...
    DocxText(text) => ...
    ExcelSheets(sheets) => ...
    PptxSlides(slides) => ...
    PdfPages(pages) => ...
    }

    #统一入口

    函数说明
    detect_format(path) -> FileFormat按扩展名识别格式(.txt/.csv/.json/.jsonl/.xml/.md/.zip/.tar/.docx/.xlsx/.pptx/.pdf,不区分大小写,未知按 TXT)
    read(path) -> Content自动分派,返回统一结果

    Content 是一个带数据的枚举,按格式返回对应结构:

    变体对应格式载荷类型
    LinesTXTArray[String](按行)
    TableCSVArray[Array[String]](行 → 字段)
    JsonValueJSONJson(动态值)
    JsonRowsJSONLArray[Json](每行一个对象)
    XmlDocXMLXmlElement(根元素树)
    MarkdownBlocksMarkdownArray[MarkdownBlock](块结构)
    ZipFilesZIPArray[ZipEntry](包内条目:文件名 + 内容字节)
    TarFilesTARArray[TarEntry](包内条目:文件名 + 内容字节)
    DocxTextDOCXString(文档全部文本)
    ExcelSheetsXLSXArray[ExcelSheet](全部工作表)
    PptxSlidesPPTXArray[String](每页文本)
    PdfPagesPDFArray[String](每页文本)

    #各格式细粒度 API

    // TXT
    read_txt(path) // 整个文件 → String
    read_txt_by_line(path) // → Array[String]
    read_txt_by_byte(path) // → Bytes(原始字节)
    read_txt_by_block(path, n) // 每 n 个字符一块 → Array[String]

    // 通用文件字节读写(任意格式,中文文件名友好)
    read_file_to_bytes(path) // 读文件原始字节 → Bytes
    write_file_to_bytes(path, data) // 写字节到文件(覆盖写)

    // CSV
    read_csv_by_line(path) // → Array[Array[String]]
    read_csv_by_column(path) // 转置 → Array[Array[String]]
    read_csv_by_block(path, n)

    // JSON / JSONL
    read_json(path) // → Json
    read_json_by_block(path, n)
    read_jsonl_by_line(path) // → Array[Json]

    // XML
    read_xml(path) // → XmlElement(根元素树)
    parse_xml(text) // 解析字符串 → XmlElement

    // Markdown
    read_markdown(path) // → Array[MarkdownBlock](标题/段落/代码/引用/列表/水平线)
    parse_markdown(text) // 解析字符串 → Array[MarkdownBlock]

    // ZIP(解压基于 hustcer/fzip)
    read_zip_entries(path) // 一次读盘,返回所有条目(ZipEntry)
    list_zip_filenames(path) // 列出包内文件名
    read_zip_file(path, inner) // 读包内文件原始字节
    read_zip_text(path, inner) // 读包内文件并 UTF-8 解码

    // TAR
    read_tar_entries(path) // 一次读盘,返回所有条目(TarEntry)
    list_tar_filenames(path) // 列出包内文件名
    read_tar_file(path, inner) // 读包内文件原始字节
    read_tar_text(path, inner) // 读包内文件并 UTF-8 解码

    // Office(OOXML,内部解压基于 hustcer/fzip + XML 解析)
    read_docx_text(path) // Word 全部文本 → String
    read_docx_paragraphs(path) // Word 各段文本 → Array[String]
    read_excel_sheets(path) // Excel 全部工作表 → Array[ExcelSheet](name + rows)
    read_excel_sheet_rows(path, i) // Excel 第 i 个工作表 → Array[Array[String]](行 → 单元格)
    read_excel_sheet_text(path, i) // Excel 第 i 个工作表 → String(制表符/换行分隔)
    read_excel_first_sheet_rows(path) // Excel 第一个工作表 → Array[Array[String]]
    read_excel_first_sheet_text(path) // Excel 第一个工作表 → String
    read_pptx_text(path) // PPT 全部文本 → String
    read_pptx_text_by_slide(path) // PPT 每页文本 → Array[String]
    read_pdf_text(path) // PDF 全部文本 → String
    read_pdf_text_by_page(path) // PDF 每页文本 → Array[String]

    read_tar_entries 返回 TarEntry 数组(name 字段 + content 字节字段,另有 text() 方法解码为字符串),适合一次读取包内多个文件、避免反复读盘:

    for e in @moonreader.read_tar_entries("data.tar") {
    println("\{e.name}: \{e.text()}")
    }

    #编码检测与转换

    文本类格式(TXT / CSV / JSON / JSONL / XML / Markdown,以及 ZIP / TAR 内层文本)默认自动检测编码,也可显式指定 encoding 参数:

    // 自动检测:BOM → UTF-32/16 零字节模式 → UTF-8 严格校验 → GBK/Big5 启发式 → Latin-1
    read_txt("data/老数据.txt") // 老系统导出的 GBK 文件直接读出中文

    // 显式指定:GBK 与 Big5 字节层面无法可靠区分,繁体需显式 big5
    read_txt("data/繁体.txt", encoding=Some(Encoding::Big5))
    read_csv_by_line("data.csv", encoding=Some(Encoding::Gbk))

    #检测 / 解码 / 编码 / 转换

    函数说明
    detect_encoding(bytes) -> Encoding探测字节流编码
    parse_encoding("gbk") -> Encoding?编码名 → 枚举(别名:gbk/gb2312/cp936/gb18030big5/cp950utf-8/utf-16/utf-16le/utf-16be/utf-32/latin1 等)
    decode(bytes, encoding) -> String按指定编码解码为 UTF-8 字符串
    decode_auto(bytes) -> String自动检测并解码
    encode(text, encoding, bom?=false) -> Bytes编码为指定编码字节
    convert(bytes, from, to) -> Bytes任意两种编码互转(= encode(decode(...))

    // 任意编码互转:GBK 老数据 → UTF-8 字节 → 写回新文件(支持中文文件名)
    let gbk = @moonreader.read_txt_by_byte("data/老数据.csv")
    let utf8 = @moonreader.convert(gbk, Encoding::Gbk, Encoding::Utf8)
    @moonreader.write_file_to_bytes("data/新数据.csv", utf8)

    Encoding 枚举:Utf8 / Utf16Le / Utf16Be / Utf32Le / Utf32Be / Gbk / Big5 / Latin1。编码时不可映射字符(如 emoji、生僻字转 GBK)替换为 ?(0x3F)。

    #错误处理

    所有函数失败时抛出统一错误 ReaderError

    try {
    let j = @moonreader.read_json("data.json")
    } catch {
    Io(msg) => println("IO 错误: \{msg}")
    Parse(msg) => println("解析错误: \{msg}")
    }

    #CLI 演示

    moon run cmd/main -- testdata/sample.csv moon run cmd/main -- testdata/sample.zip # 列出并 dump 包内文件 moon run cmd/main -- testdata/sample.zip sample.txt # 读取包内指定文件 moon run cmd/main -- testdata/sample.tar # 列出并 dump 包内文件 moon run cmd/main -- testdata/sample.tar alpha.txt # 读取包内指定文件 moon run cmd/main -- testdata/sample.docx # 读取 Word 文档文本 moon run cmd/main -- testdata/sample.xlsx # 读取 Excel 表格 moon run cmd/main -- testdata/sample.pptx # 读取 PPT 每页文本 moon run cmd/main -- testdata/sample.pdf # 读取 PDF 每页文本 # 编码转换:convert <文件> <目标编码> [源编码] [输出路径] moon run cmd/main -- convert testdata/encoding_gbk.txt utf-8 # 自动检测源编码,覆盖写回 moon run cmd/main -- convert testdata/encoding_gbk.txt utf-8 gbk # 显式源编码 moon run cmd/main -- convert testdata/encoding_gbk.txt utf-8 gbk 新.txt # 另存为新文件

    #Wasm-GC CLI 模式(浏览器 / IDE 预览)

    同一套 CLI 可编译到 wasm-gc 目标运行:文件读写委托给 moonbitlang/x/fs(底层走 moonrun 的 __moonbit_fs_unstable 宿主),路径以字符串交给宿主,中文文件名天然支持,编码自动检测(GBK / Big5 等)同样生效。

    moon run --target wasm-gc cmd/main -- testdata/sample.csv moon run --target wasm-gc cmd/main -- testdata/中文.txt moon run --target wasm-gc cmd/main -- testdata/encoding_gbk.txt moon run --target wasm-gc cmd/main -- convert testdata/encoding_gbk.txt utf-8 gbk 新.txt

    #中文文件名

    库内部用 _wfopen + UTF-8 路径转换打开文件,外层路径和 zip/tar 包内文件名均可为中文。

    ReaderError

    pub(all) suberror ReaderError {
    Io(String)
    Parse(String)
    }

    统一的错误类型:IO 错误 / 解析错误

    Content

    pub enum Content {
    Lines(Array[String])
    Table(Array[Array[String]])
    JsonValue(Json)
    JsonRows(Array[Json])
    XmlDoc(XmlElement)
    MarkdownBlocks(Array[MarkdownBlock])
    ZipFiles(Array[ZipEntry])
    TarFiles(Array[TarEntry])
    DocxText(String)
    ExcelSheets(Array[ExcelSheet])
    PptxSlides(Array[String])
    PdfPages(Array[String])
    } derive(Eq,
    Debug
    )

    统一读取结果。调用方按格式 match 得到对应结构。

    Encoding

    pub(all) enum Encoding {
    Utf8
    Utf16Le
    Utf16Be
    Utf32Le
    Utf32Be
    Gbk
    Big5
    Latin1
    } derive(Eq,
    Debug
    )

    文本编码类型

    ExcelSheet

    pub(all) struct ExcelSheet {
    name : String
    rows : Array[Array[String]]
    } derive(Eq,
    Debug
    )

    一个工作表:名称 + 二维表(行 → 单元格)

    FileFormat

    pub(all) enum FileFormat {
    Txt
    Csv
    Json
    Jsonl
    Xml
    Markdown
    Zip
    Tar
    Docx
    Xlsx
    Pptx
    Pdf
    } derive(Eq,
    Debug
    )

    库当前支持的格式

    MarkdownBlock

    pub(all) enum MarkdownBlock {
    Heading(Int, String)
    Paragraph(String)
    CodeBlock(String, String)
    Quote(String)
    ListItem(String)
    HorizontalRule
    } derive(Eq,
    Debug
    )

    Markdown 块:标题 / 段落 / 代码块 / 引用 / 列表项 / 水平线

    MarkdownBlock::to_string

    fn MarkdownBlock::to_string(self : MarkdownBlock) -> String

    渲染为 Markdown 文本(近似还原)

    TarEntry

    pub(all) struct TarEntry {
    name : String
    content : Bytes
    } derive(Eq,
    Debug
    )

    tar 包内的一个条目:文件名 + 原始内容字节

    TarEntry::text

    fn TarEntry::text(self : TarEntry, encoding? : Encoding?) -> String

    把条目内容自动检测编码并解码为字符串(非法字节用 U+FFFD 替换)。 encoding 可显式指定解码方式。

    XmlElement

    pub(all) struct XmlElement {
    name : String
    attrs : Array[(String, String)]
    children : Array[XmlNode]
    } derive(Eq,
    Debug
    )

    XML 元素:标签名 + 属性 + 子节点

    XmlElement::attr

    fn XmlElement::attr(self : XmlElement, key : String) -> String?

    按属性名取值,不存在返回 None

    XmlElement::child_elements

    fn XmlElement::child_elements(self : XmlElement) -> Array[XmlElement]

    直接子元素(过滤掉文本节点)

    XmlElement::find

    fn XmlElement::find(self : XmlElement, name : String) -> XmlElement?

    查找第一个名为 name 的后代元素(含自身),找不到返回 None

    XmlElement::find_all

    fn XmlElement::find_all(self : XmlElement, name : String) -> Array[XmlElement]

    查找所有名为 name 的后代元素(含自身)

    XmlElement::text

    fn XmlElement::text(self : XmlElement) -> String

    该元素的全部文本内容(含子孙文本节点,按顺序拼接)

    XmlElement::to_string

    fn XmlElement::to_string(self : XmlElement) -> String

    渲染为带缩进的 XML 字符串(用于展示)

    XmlNode

    pub(all) enum XmlNode {
    Text(String)
    Element(XmlElement)
    } derive(Eq,
    Debug
    )

    XML 节点:文本或子元素

    ZipEntry

    pub(all) struct ZipEntry {
    name : String
    content : Bytes
    } derive(Eq,
    Debug
    )

    ZIP 包内的一个条目:文件名 + 原始内容字节

    ZipEntry::text

    fn ZipEntry::text(self : ZipEntry, encoding? : Encoding?) -> String

    把条目内容自动检测编码并解码为字符串(非法字节用 U+FFFD 替换)。 encoding 可显式指定解码方式。

    convert

    fn convert(bytes : Bytes, from : Encoding, to : Encoding) -> Bytes

    在任意两种编码之间转换字节内容:先按 from 解码,再按 to 编码。 等价于 encode(decode(bytes, from), to)。

    decode

    fn decode(bytes : Bytes, encoding : Encoding) -> String

    按指定编码解码为字符串(损坏字节替换为 U+FFFD)

    decode_auto

    fn decode_auto(bytes : Bytes) -> String

    自动检测编码并解码(= decode(bytes, detect_encoding(bytes)))

    decode_big5

    fn decode_big5(bytes : Bytes) -> String

    显式按 Big5(繁体中文)解码。 GBK 与 Big5 在字节层面无法可靠区分,自动检测默认判 GBK, 繁体文本需显式调用本函数。

    decode_gbk

    fn decode_gbk(bytes : Bytes) -> String

    显式按 GBK(简体中文)解码。自动检测对双字节文本默认即判 GBK。

    detect_encoding

    fn detect_encoding(bytes : Bytes) -> Encoding

    检测字节流的文本编码(启发式,面向文本文件)。

    无法确定时优先 UTF-8 → GBK → Latin-1,简体中文环境下默认判 GBK。

    detect_format

    fn detect_format(path : String) -> FileFormat

    根据文件扩展名识别格式(不区分大小写)。 未知扩展名按文本 TXT 处理。

    encode

    fn encode(text : String, encoding : Encoding, bom? : Bool) -> Bytes

    按指定编码把字符串编码为字节序列。 不可映射的字符替换为 '?'(0x3F)。bom 为 true 时对 UTF-8/16/32 写出 BOM。

    list_tar_filenames

    fn list_tar_filenames(file_path : String) -> Array[String] raise ReaderError

    列出 tar 包内所有文件名

    list_zip_filenames

    fn list_zip_filenames(file_path : String) -> Array[String] raise ReaderError

    列出 zip 包内所有文件名(只读中央目录,不解压内容)

    parse_encoding

    fn parse_encoding(name : String) -> Encoding?

    解析编码名称为 Encoding(不区分大小写),支持常见别名。 无法识别时返回 None,调用方可回退到自动检测。

    parse_markdown

    fn parse_markdown(text : String) -> Array[MarkdownBlock]

    解析 Markdown 字符串为块结构

    parse_xml

    fn parse_xml(text : String) -> XmlElement raise ReaderError

    解析 XML 字符串,返回根元素

    read

    fn read(path : String) -> Content raise ReaderError

    一键读取:根据扩展名自动识别格式并返回对应结果。

    read_csv_by_block

    fn read_csv_by_block(file_path : String, block_size : Int, encoding? : Encoding?) -> Array[Array[Array[String]]] raise ReaderError

    按块读取 CSV:每 block_size 行一个块

    read_csv_by_column

    fn read_csv_by_column(file_path : String, encoding? : Encoding?) -> Array[Array[String]] raise ReaderError

    按列读取 CSV:返回「列 → 值」的二维数组(转置)

    read_csv_by_line

    fn read_csv_by_line(file_path : String, encoding? : Encoding?) -> Array[Array[String]] raise ReaderError

    按行读取 CSV,返回「行 → 字段」的二维数组

    read_docx_paragraphs

    fn read_docx_paragraphs(path : String) -> Array[String] raise ReaderError

    读取 docx 各段落文本(每段一个字符串)

    read_docx_text

    fn read_docx_text(path : String) -> String raise ReaderError

    读取 docx 全部文本(段落按换行拼接)

    read_excel_first_sheet_rows

    fn read_excel_first_sheet_rows(path : String) -> Array[Array[String]] raise ReaderError

    读取 xlsx 第一个工作表为二维表(行 → 单元格)。 多 sheet 时仅取第一张;需要其它 sheet 请用 read_excel_sheet_rows。

    read_excel_first_sheet_text

    fn read_excel_first_sheet_text(path : String) -> String raise ReaderError

    读取 xlsx 第一个工作表为字符串(单元格用制表符分隔,行用换行分隔)

    read_excel_sheet_rows

    fn read_excel_sheet_rows(path : String, sheet_index : Int) -> Array[Array[String]] raise ReaderError

    读取 xlsx 指定下标工作表为二维表(行 → 单元格),共享字符串已解析为文本。 下标越界返回空表。

    read_excel_sheet_text

    fn read_excel_sheet_text(path : String, sheet_index : Int) -> String raise ReaderError

    读取 xlsx 指定下标工作表为字符串(单元格用制表符分隔,行用换行分隔)

    read_excel_sheets

    fn read_excel_sheets(path : String) -> Array[ExcelSheet] raise ReaderError

    读取 xlsx 全部工作表(含多 sheet),共享字符串已解析为文本

    read_file_to_bytes

    fn read_file_to_bytes(path : String) -> Bytes raise ReaderError

    以路径读取文件为原始字节(支持中文文件名)。 内部按目标自动选择 native C stub 或 wasm-gc 的 @fs,公开面一致。

    read_json

    fn read_json(file_path : String, encoding? : Encoding?) -> Json raise ReaderError

    解析 JSON 文件为动态值(Json)

    read_json_by_block

    fn read_json_by_block(file_path : String, block_size : Int, encoding? : Encoding?) -> Array[Array[Json]] raise ReaderError

    按块读取 JSON:假设顶层是数组,每 block_size 个元素一个块

    read_jsonl_by_line

    fn read_jsonl_by_line(file_path : String, encoding? : Encoding?) -> Array[Json] raise ReaderError

    按行读取 JSONL(每行一个 JSON 对象)

    read_markdown

    fn read_markdown(file_path : String, encoding? : Encoding?) -> Array[MarkdownBlock] raise ReaderError

    读取并解析 Markdown 文件为块结构

    read_pdf_text

    fn read_pdf_text(path : String) -> String raise ReaderError

    读取 PDF 全部文本(各页按换行拼接)

    read_pdf_text_by_page

    fn read_pdf_text_by_page(path : String) -> Array[String] raise ReaderError

    读取 PDF 每页文本(一页一个字符串,页内文本片段按换行拼接)

    read_pptx_text

    fn read_pptx_text(path : String) -> String raise ReaderError

    读取 pptx 全部文本(各页按换行拼接)

    read_pptx_text_by_slide

    fn read_pptx_text_by_slide(path : String) -> Array[String] raise ReaderError

    读取 pptx 每页文本(一页一个字符串)

    read_tar_entries

    fn read_tar_entries(file_path : String) -> Array[TarEntry] raise ReaderError

    一次读盘并解析 tar 内所有条目(文件名 + 内容)。 需要多个条目时用这个,避免反复读盘。

    read_tar_file

    fn read_tar_file(file_path : String, inner_name : String) -> Bytes raise ReaderError

    读取 tar 包内某个文件的内容,返回原始字节

    read_tar_text

    fn read_tar_text(file_path : String, inner_name : String, encoding? : Encoding?) -> String raise ReaderError

    读取 tar 包内某个文件的内容,自动检测编码并解码为字符串。 encoding 可显式指定解码方式。

    read_txt

    fn read_txt(file_path : String, encoding? : Encoding?) -> String raise ReaderError

    读取整个文本文件为字符串(UTF-8 路径感知,支持中文文件名)。 encoding 缺省自动检测(BOM / UTF-8 / UTF-16 / GBK / Big5 / Latin-1); 显式指定则按指定编码解码。

    read_txt_by_block

    fn read_txt_by_block(file_path : String, block_size : Int, encoding? : Encoding?) -> Array[String] raise ReaderError

    按块读取文本文件:每块 block_size 个字符(注意是字符数,非字节数),转成字符串。 encoding 缺省自动检测,可显式指定。

    read_txt_by_byte

    fn read_txt_by_byte(file_path : String) -> Bytes raise ReaderError

    读取文本文件为字节序列(等价 read_file_to_bytes,属 TXT 系列命名)

    read_txt_by_line

    fn read_txt_by_line(file_path : String, encoding? : Encoding?) -> Array[String] raise ReaderError

    按行读取文本文件,返回字符串数组(已去除行尾 \n / \r\n)。 encoding 缺省自动检测,可显式指定。

    read_xml

    fn read_xml(file_path : String, encoding? : Encoding?) -> XmlElement raise ReaderError

    读取并解析 XML 文件,返回根元素

    read_zip_entries

    fn read_zip_entries(file_path : String) -> Array[ZipEntry] raise ReaderError

    一次读盘并解压 zip 内所有条目(文件名 + 内容)。 需要多个条目时用这个,避免反复读盘。

    read_zip_file

    fn read_zip_file(file_path : String, inner_name : String) -> Bytes raise ReaderError

    读取 zip 包内某个文件的内容,返回原始字节

    read_zip_text

    fn read_zip_text(file_path : String, inner_name : String, encoding? : Encoding?) -> String raise ReaderError

    读取 zip 包内某个文件的内容,自动检测编码并解码为字符串。 encoding 可显式指定解码方式。

    write_file_to_bytes

    fn write_file_to_bytes(path : String, data : Bytes) -> Unit raise ReaderError

    以路径把字节写入文件(覆盖写,支持中文文件名)