mikaio.dev/freetools

Parquet 转 CSV 转换器

无需安装任何软件,直接打开 Apache Parquet 文件并转换成 CSV。文件在浏览器标签页内解码,不会离开你的设备,断网也照样能用。

文件在本地读取:不上传、无服务器、不追踪。

这个转换器做什么

Apache Parquet 是如今几乎所有数据管道都会写出的格式:列式、压缩、二进制,为分析引擎而设计。它对机器友好,对人眼无用。你无法用文本编辑器打开它,无法直接发给整天用表格的同事,也无法粘贴进一张工单里。CSV 恰恰相反:做分析笨拙,却在任何地方都能读。

这个页面用最直接的方式把两端连起来。你从磁盘选一个 .parquet 文件,页面就地解码,告诉你找到了多少行多少列,显示一段预览,并生成可下载的 CSV。没有账号,没有排队,没有上传进度条,因为整个过程根本没有服务器参与。

最后这一点正是这个工具存在的理由。多数在线 Parquet 转换器不过是一个把文件发往后端的表单。如果文件里装的是客户名单、薪资、病历编号,或任何受数据政策约束的内容,那次上传本身就是问题所在。这里的转换是在你的标签页中运行的 JavaScript,读取的是你选择文件时浏览器已经交给页面的字节。

四步用法

  1. 在文件框中选择 .parquet 文件。在此之前不会发生任何事。
  2. 选择分隔符。默认是逗号;分号适合以逗号作小数点的地区所配置的表格软件;制表符会生成 TSV,粘贴进大多数表格程序都很干净。
  3. 决定第一行是否放列名。表头复选框默认勾选,切换它会立即重排输出,无需重新读取文件。
  4. 看一眼预览,然后点击下载 CSV。预览只显示前 200 行以保持页面流畅;下载的文件始终包含 Parquet 中的全部行。

转换之后再改分隔符或表头开关,不会重新读盘。解码后的表格保存在标签页内存中,因此即使是几十万行,这些切换也是瞬时的。

Parquet 如何存放一张表,以及为什么转换并不简单

CSV 是一串行的流。Parquet 正好相反:它把每一列分开存放,装进称为 row group 的块里;在一个 row group 内部,一列存在由若干页组成的 chunk 中。每一页都可以被压缩,页内的值还可以用多种不同方式编码。

因此读取它意味着层层拆解:

一切顺利时这些细节无关紧要;出问题时才重要。正因为解码器理解每一层,遇到不支持的文件时,它给出的是关于压缩、编码或嵌套的具体提示,而不是一份被悄悄弄坏的 CSV。

实例演算:你会看到怎样的值

有三种 Parquet 类型在 CSV 中没有直接对应,值得说清楚输出到底长什么样。

日期列。 DATE 类型存的是自 1970 年 1 月 1 日起的 32 位天数。若存储的数字是 19723,那么纪元之后第 19723 天正是 2024 年 1 月 1 日,CSV 单元格写作 2024-01-01。不套用任何时区,因为日期没有可以平移的时间部分。

微秒时间戳。 微秒精度的 TIMESTAMP 列存的是自纪元起的 64 位微秒数。取值 1704112215123456,除以 1000000 得到整数秒 1704112215,也就是 2024 年 1 月 1 日 12:30:15 UTC,余下 123456 微秒。单元格写作 2024-01-01 12:30:15.123456。小数末尾的零会被去掉,所以正好落在整秒上的时间戳不带小数部分。

decimal 列。 DECIMAL(12,2) 列以整数加上一个 scale 存储。整数 1230、scale 为 2,表示 12.30,就原样写成 12.30。这正是财务列绝不该经过浮点数的原因:文本既保住了精确数值,也保住了 schema 承诺的小数位数。

布尔值写作 truefalse,空值变成空字段,而不是合法 UTF-8 的二进制列会以 base64 输出,避免原始字节破坏 CSV 的结构。

离线转换器的用武之地

最明显的场景是保密:一份用户记录导出,你想在它接近共享盘之前先看一眼。数据不出本机,也就没有任何规定被绕开。

第二个场景是摩擦。同事发来一份 Parquet 抽样,你只想核对三列,为此安装 Python 加 PyArrow,而这个文件五分钟后就会被删掉,代价荒唐;打开一个标签页则不然。

第三个场景是你无权配置的机器:被锁定的公司笔记本、客户的电脑、不允许装包的实验室机器。浏览器本来就在那里。

第四个场景是教学。同一张表先呈现为不透明的二进制块,再呈现为纯文本,能让列式存储与行式存储的区别变得具体,这是示意图很难做到的。

常见错误与规避方法

在表格软件里打开 CSV,只看到一个超宽的列。 你的软件按本地设置期待某个分隔符。改用分号选项重新生成,或走导入对话框并明确指定分隔符。

很长的数字编号变成科学计数法。 那是表格软件所为,不是 CSV 的问题。文件里存的就是那些数字,是程序决定按浮点显示。请把该列按文本导入。

期待本地时间。 时间戳按 UTC 输出。Parquet 通常把时间戳存为一个时刻,若擅自转换到你机器恰好所处的时区,会悄悄改变每一个值。若确实需要本地时间,请事后有意识地做偏移。

丢进嵌套导出文件。 含 struct、list 或 map 列的文件会被拒绝。请先用 pandas.json_normalize、Polars 的 unnest,或用 DuckDB 查询选出叶子字段来展平,写出扁平的 Parquet,再来转换。

局限:什么时候不该用它

它会把整个文件读入内存,因此几百兆以上的大导出更适合交给 DuckDB,或用逐个 row group 流式处理的小脚本。Zstd、Brotli 与 LZ4 压缩会被直接拒绝,而不是解码到一半;请用 Snappy 或 Gzip 重新写出。加密的 Parquet 文件按设计完全不支持。嵌套 schema 同样不在范围内,因为把一个列表列塞进 CSV 单元格是关于你的数据的决定,通用转换器不该悄悄替你做主。

隐私

页面里没有上传代码,不对你的文件做任何统计,转换过程中也不发出任何网络请求。文件由浏览器自带的文件接口读取,并在标签页内解码。如果你想要的是验证而非承诺:加载页面后断开网络,再转换一个文件,结果完全一样——因为线的另一端从来就没有东西。

Parquet 转 CSV 常见问题

数据真的完全不会被上传吗?
确实如此。转换器是纯 JavaScript,它读取你在文件框中选择的字节并直接在页面里解码,没有上传、没有接口调用,也不会统计你的数据。页面加载完成后你可以断开网络,工具依旧正常工作——这是最简单的自我验证方式。
支持哪些 Parquet 文件?
支持由 pandas、PyArrow、Polars、DuckDB、Spark 等常用工具写出的扁平表格。可解码未压缩、Snappy 与 Gzip 页面,支持 PLAIN、字典、RLE、delta 与 byte-stream-split 编码,数据页 v1 与 v2 均可。Zstd、Brotli、LZ4 以及加密文件会给出明确提示而不是输出错误结果。
嵌套列会怎样处理?
会被明确拒绝。struct、list、map 列没有唯一合理的 CSV 形式,默默选一种反而会破坏数据。请先在 pandas、Polars 或 DuckDB 中展平结构,写出扁平的 Parquet 文件后再来转换。
日期、时间戳和 decimal 如何输出?
日期输出为 YYYY-MM-DD。时间戳按 UTC 输出为 YYYY-MM-DD HH:MM:SS,并保留列本身的毫秒、微秒或纳秒位。decimal 列以文本保留精确小数位,12.30 依然是 12.30,不会变成四舍五入的浮点数。空值输出为空字段。