Parquet 查看与转换
数据互转
正在载入
正在加载工具
工具代码会在打开时按需载入,请稍候。
本工具的全部运算都发生在你的浏览器中,输入内容不会发送到任何服务器。
关于这个工具
无需上传内容,即可检查较小的本地 Parquet 文件。随站点打包的 hyparquet 读取器在浏览器工作线程中运行,读取采用 UNCOMPRESSED 或 SNAPPY 压缩的受支持扁平列。先查看物理类型、逻辑注解、可空性与本工具采用的表示方式,再分页浏览并导出首尾均包含的行范围。精确的 64 位整数、十进制数、二进制值和时间单位计数用结构说明的字符串表示;普通布尔值与受支持的有限数值保持类型。不支持的列会保留在结构中,注明原因并标为 unsupported:null;其数据行使用显式 null 占位,不能当作解码得到的源空值,受支持的列仍可使用。解释或导出结果前请检查这些警告。本工具不获取远程文件、不使用第三方 CDN,也不持久保存文件内容。
常见用途
- 将有界分析导出交给其他工具之前,先检查列名、可空字段、行数,以及物理类型和逻辑类型的区别,以及任何不支持列警告。
- 提取连续记录供电子表格检查,保留原文件不变,并为表头和文本启用公式保护。
- 下载带结构的 JSON 样本,区分 null 与空文本,并避免大整数标识符、固定小数位十进制数和时间戳单位被舍入。
使用方法
- 1.选择一个本地 Parquet 文件并加载。通过检查后查看结构、行数与行组。仅有 .parquet 扩展名并不能证明文件有效。逐一检查不支持列警告:这些列在结构中保留标记,但值为 null 占位;受支持列仍可查看。需要不支持列的原始值时请使用完整的本地 Parquet 工具。文件损坏或超限会加载失败,不会返回部分加载。
- 2.用上一页、下一页查看每页 25 行。预览只显示前 12 列,单元格超过 500 个字符时截短显示;所有列请查看结构,并结合空值和类型标记理解数据。页码只控制浏览,不决定导出哪些行。
- 3.按文件顺序输入从 1 开始、首尾均包含的起始行和结束行,再选择 CSV 或 JSON。零行文件使用 0–0 空范围,仅导出结构或表头。导出包含有效范围内的所有列与完整值,即使预览隐藏了列或截短了单元格。供电子表格检查时保留 CSV 公式保护;原始 CSV 需要明确选择。取消、重置或离开工具会丢弃内存中的文件和结果,继续使用时需重新选择文件。
来自合成 Parquet 文件的可执行示例
保留 Unicode、null 与基本类型
{
"file": "mixed-snappy-v1.parquet",
"format": "json",
"start": 1,
"end": 5,
"safe": true,
"excerptColumns": [
"name",
"active",
"int32_value"
]
}{
"schemaExcerpt": [
{
"name": "name",
"physicalType": "BYTE_ARRAY",
"logicalType": "STRING",
"representation": "text",
"nullable": true,
"supported": true
},
{
"name": "active",
"physicalType": "BOOLEAN",
"logicalType": "NONE",
"representation": "boolean",
"nullable": true,
"supported": true
},
{
"name": "int32_value",
"physicalType": "INT32",
"logicalType": "NONE",
"representation": "number",
"nullable": true,
"supported": true
}
],
"range": {
"start": 1,
"end": 5
},
"rowsExcerpt": [
{
"name": "東京 · café 😀",
"active": true,
"int32_value": -2147483648
},
{
"name": "",
"active": false,
"int32_value": 2147483647
},
{
"name": "\\N",
"active": null,
"int32_value": 0
},
{
"name": "=SUM(1,2)\r\n\"quoted\",value",
"active": true,
"int32_value": -1
},
{
"name": null,
"active": false,
"int32_value": null
}
]
}合成文件共 14 列、5 行,这里仅展示 name、active 与 int32_value。Unicode 和空文本保持不变;null 不等于 false 或数值零。完整 JSON 导出包含全部 14 个结构条目与列。
读取 Snappy 压缩的 v2 数据页
{
"file": "mixed-snappy-v2.parquet",
"format": "json",
"start": 1,
"end": 2,
"safe": true,
"excerptColumns": [
"name",
"int32_value"
]
}{
"schemaExcerpt": [
{
"name": "name",
"physicalType": "BYTE_ARRAY",
"logicalType": "STRING",
"representation": "text",
"nullable": true,
"supported": true
},
{
"name": "int32_value",
"physicalType": "INT32",
"logicalType": "NONE",
"representation": "number",
"nullable": true,
"supported": true
}
],
"range": {
"start": 1,
"end": 2
},
"rowsExcerpt": [
{
"name": "東京 · café 😀",
"int32_value": -2147483648
},
{
"name": "",
"int32_value": 2147483647
}
]
}这个独立写入的文件使用 SNAPPY、字典值和数据页 v2。前两条记录保留原始文本与有符号 INT32。excerptColumns 仅缩短文档示例,不是导出列选择功能。
导出包含两端的行范围
{
"file": "mixed-uncompressed-v1.parquet",
"format": "json",
"start": 2,
"end": 3,
"safe": true,
"excerptColumns": [
"name",
"int32_value"
]
}{
"schemaExcerpt": [
{
"name": "name",
"physicalType": "BYTE_ARRAY",
"logicalType": "STRING",
"representation": "text",
"nullable": true,
"supported": true
},
{
"name": "int32_value",
"physicalType": "INT32",
"logicalType": "NONE",
"representation": "number",
"nullable": true,
"supported": true
}
],
"range": {
"start": 2,
"end": 3
},
"rowsExcerpt": [
{
"name": "",
"int32_value": 2147483647
},
{
"name": "\\N",
"int32_value": 0
}
]
}UNCOMPRESSED/PLAIN 版本包含相同记录。start 2、end 3 按文件顺序同时包含第二、第三数据行。空字符串与实际反斜杠 N 文本在 JSON 中仍不同。此处仅展示两列,但导出包含所有列。
保留有符号与无符号 64 位整数
{
"file": "mixed-snappy-v1.parquet",
"format": "json",
"start": 1,
"end": 4,
"safe": true,
"excerptColumns": [
"id",
"uint64_value"
]
}{
"schemaExcerpt": [
{
"name": "id",
"physicalType": "INT64",
"logicalType": "NONE",
"representation": "integer:string",
"nullable": true,
"supported": true
},
{
"name": "uint64_value",
"physicalType": "INT64",
"logicalType": "UINT_64",
"representation": "integer:string",
"nullable": true,
"supported": true
}
],
"range": {
"start": 1,
"end": 4
},
"rowsExcerpt": [
{
"id": "-9223372036854775808",
"uint64_value": "18446744073709551615"
},
{
"id": "9223372036854775807",
"uint64_value": "9223372036854775808"
},
{
"id": "9007199254740993",
"uint64_value": "9007199254740993"
},
{
"id": "-9007199254740993",
"uint64_value": "0"
}
]
}INT64 与 UINT64 都是精确十进制字符串,零也如此。超过 2^53 的值以及有符号、无符号 64 位端点都不会舍入。结构标明物理类型、逻辑类型及 integer:string 表示。
保留十进制数声明的小数位
{
"file": "mixed-snappy-v1.parquet",
"format": "json",
"start": 1,
"end": 5,
"safe": true,
"excerptColumns": [
"amount"
]
}{
"schemaExcerpt": [
{
"name": "amount",
"physicalType": "FIXED_LEN_BYTE_ARRAY",
"logicalType": "DECIMAL(30,6)",
"representation": "decimal:string",
"nullable": true,
"supported": true
}
],
"range": {
"start": 1,
"end": 5
},
"rowsExcerpt": [
{
"amount": "9007199254740993.123456"
},
{
"amount": "-9007199254740993.000001"
},
{
"amount": "0.000001"
},
{
"amount": "0.000000"
},
{
"amount": null
}
]
}DECIMAL(30,6) 使用固定小数文本。0.000001 与 0.000000 均保留六位小数,大金额保留每个数字,null 仍为 null,不引入二进制浮点运算。
解释时间值前先看单位
{
"file": "mixed-snappy-v1.parquet",
"format": "json",
"start": 1,
"end": 4,
"safe": true,
"excerptColumns": [
"timestamp_us",
"timestamp_ns",
"date",
"time_us"
]
}{
"schemaExcerpt": [
{
"name": "timestamp_us",
"physicalType": "INT64",
"logicalType": "TIMESTAMP(MICROS,UTC)",
"representation": "timestamp:unit:string",
"nullable": true,
"supported": true
},
{
"name": "timestamp_ns",
"physicalType": "INT64",
"logicalType": "TIMESTAMP(NANOS,local)",
"representation": "timestamp:unit:string",
"nullable": true,
"supported": true
},
{
"name": "date",
"physicalType": "INT32",
"logicalType": "DATE(days since 1970-01-01)",
"representation": "date:days:string",
"nullable": true,
"supported": true
},
{
"name": "time_us",
"physicalType": "INT64",
"logicalType": "TIME(MICROS,UTC)",
"representation": "time:unit:string",
"nullable": true,
"supported": true
}
],
"range": {
"start": 1,
"end": 4
},
"rowsExcerpt": [
{
"timestamp_us": "-1",
"timestamp_ns": "-1",
"date": "-719162",
"time_us": "0"
},
{
"timestamp_us": "-1000001",
"timestamp_ns": "-1000000001",
"date": "-1",
"time_us": "1"
},
{
"timestamp_us": "0",
"timestamp_ns": "0",
"date": "0",
"time_us": "12345678901"
},
{
"timestamp_us": "9007199254740993",
"timestamp_ns": "9007199254740993",
"date": "20000",
"time_us": "86399999999"
}
]
}-1 保留为精确单位计数,不会转成 Date。timestamp_us 为带 UTC 调整的微秒;timestamp_ns 为本地语义纳秒。DATE 为自 1970-01-01 起的天数,TIME 使用声明单位。完整导出结构保留这些标记。
区分空二进制字节与 null
{
"file": "mixed-snappy-v1.parquet",
"format": "json",
"start": 1,
"end": 5,
"safe": true,
"excerptColumns": [
"binary",
"fixed_binary"
]
}{
"schemaExcerpt": [
{
"name": "binary",
"physicalType": "BYTE_ARRAY",
"logicalType": "NONE",
"representation": "binary:hex",
"nullable": true,
"supported": true
},
{
"name": "fixed_binary",
"physicalType": "FIXED_LEN_BYTE_ARRAY",
"logicalType": "NONE",
"representation": "binary:hex",
"nullable": true,
"supported": true
}
],
"range": {
"start": 1,
"end": 5
},
"rowsExcerpt": [
{
"binary": "0x00ff80",
"fixed_binary": "0x00ff8001"
},
{
"binary": "0x",
"fixed_binary": "0x00000000"
},
{
"binary": "0x000102030405060708090a0b0c0d0e0f",
"fixed_binary": "0x41424344"
},
{
"binary": "0x5c4e",
"fixed_binary": "0xfffefdfc"
},
{
"binary": null,
"fixed_binary": null
}
]
}二进制值用带 0x 前缀的小写十六进制表示。空字节为 0x,null 仍为 null。这是检查表示,不会将任意字节解释成 UTF-8 文本。
保留特殊浮点值
{
"file": "mixed-snappy-v1.parquet",
"format": "json",
"start": 1,
"end": 5,
"safe": true,
"excerptColumns": [
"float64_value",
"float32_value"
]
}{
"schemaExcerpt": [
{
"name": "float64_value",
"physicalType": "DOUBLE",
"logicalType": "NONE",
"representation": "float:number-or-special-string",
"nullable": true,
"supported": true
},
{
"name": "float32_value",
"physicalType": "FLOAT",
"logicalType": "NONE",
"representation": "float:number-or-special-string",
"nullable": true,
"supported": true
}
],
"range": {
"start": 1,
"end": 5
},
"rowsExcerpt": [
{
"float64_value": "NaN",
"float32_value": "NaN"
},
{
"float64_value": "+Infinity",
"float32_value": "+Infinity"
},
{
"float64_value": "-Infinity",
"float32_value": "-Infinity"
},
{
"float64_value": "-0",
"float32_value": "-0"
},
{
"float64_value": 1.25,
"float32_value": 1.5
}
]
}NaN、正负无穷与负零均为结构说明的显式字符串,有限值 1.25 与 1.5 仍为 JSON 数值。此表示避免 JSON.stringify 悄悄将非有限数转为 null 或丢失负零。
保护带多行的公式式文本
{
"file": "mixed-snappy-v1.parquet",
"format": "csv",
"start": 4,
"end": 4,
"safe": true,
"excerptColumns": [
"name",
"int32_value"
]
}{
"csvRecordsExcerpt": [
[
"name",
"int32_value"
],
[
"'=SUM(1,2)\r\n\"quoted\",value",
"-1"
]
]
}这里显示普通 CSV 解析后的部分列记录,并非完整 14 列 CSV。公式保护为高风险文本添加单引号;值中的逗号、双引号与 CRLF 通过引用保留。数值 INT32 -1 仍为 -1;以高风险字符串表示的精确值也可能被加保护前缀。
解码原始 CSV 的空值与反斜杠
{
"file": "mixed-snappy-v1.parquet",
"format": "csv",
"start": 2,
"end": 5,
"safe": false,
"excerptColumns": [
"name",
"active"
]
}{
"csvRecordsExcerpt": [
[
"name",
"active"
],
[
"",
"false"
],
[
"\\\\N",
"\\N"
],
[
"=SUM(1,2)\r\n\"quoted\",value",
"true"
],
[
"\\N",
"false"
]
]
}这些记录展示 CSV 解析后的值。源文本反斜杠 N 会增加第二个前导反斜杠,真正的 null 为单个反斜杠 N 标记,空文本仍为空。原始模式保留公式式字符串,直接在电子表格打开可能有风险;空值和反斜杠编码仍生效。
在嵌套占位旁保留受支持列
{
"file": "unsupported-struct.parquet",
"format": "json",
"start": 1,
"end": 2,
"safe": true,
"excerptColumns": [
"flat_id",
"nested"
]
}{
"schemaExcerpt": [
{
"name": "flat_id",
"physicalType": "INT32",
"logicalType": "NONE",
"representation": "number",
"nullable": true,
"supported": true
},
{
"name": "nested",
"physicalType": "GROUP",
"logicalType": "NONE",
"representation": "unsupported:null",
"nullable": true,
"supported": false,
"reason": "nested"
}
],
"range": {
"start": 1,
"end": 2
},
"rowsExcerpt": [
{
"flat_id": 1,
"nested": null
},
{
"flat_id": 2,
"nested": null
}
]
}flat_id 仍为 1、2。嵌套结构保留为 GROUP 条目,并标为 supported:false、reason nested、unsupported:null。两个 null 都是占位,源嵌套值可能不同。用 JSON 结构将它与真正解码的可空列区分。
标记不支持的压缩方式
{
"file": "unsupported-gzip.parquet",
"format": "json",
"start": 1,
"end": 3,
"safe": true,
"excerptColumns": [
"value"
]
}{
"schemaExcerpt": [
{
"name": "value",
"physicalType": "INT32",
"logicalType": "NONE",
"representation": "unsupported:null",
"nullable": true,
"supported": false,
"reason": "codec"
}
],
"range": {
"start": 1,
"end": 3
},
"rowsExcerpt": [
{
"value": null
},
{
"value": null
},
{
"value": null
}
]
}此查看器不解码 GZIP。value 列仍在结构中,reason 为 codec,所有行均为 null 占位。结果不能说明原单元格值,需要完整的 Parquet 读取器恢复。仅导出 CSV 会丢失这一原因。
常见 Parquet 检查误区
- 以为所有 .parquet 文件的类型、编码与压缩均受支持,或把不支持列占位误当作源空值。
- 把结构中说明为 INT64 或 DECIMAL 的字符串转成会舍入的浮点数。
- 未检查单位与 UTC 调整标记,就将时间戳的单位计数当作毫秒。
- 把截短的预览或隐藏列误认为成功导出也丢失了数据。
- 使用从 0 开始的行号,或误以为导出不包含结束行。
- 把 CSV 的 \N 当作普通文本,或忘记去掉转义文本额外的前导反斜杠。
- 以为取消、重置或更换文件后旧工作线程会话仍然存在。
- 在电子表格打开不可信原始 CSV,或误以为双引号能阻止公式执行。
限制与说明
- 每次仅处理一个文件,上限为 8 MiB、10,000 行、128 列和 200,000 个数据单元格。受支持的解码数据页合计预算为 32 MiB。文本单元格与原始二进制单元格分别上限为 256 KiB,二进制十六进制文本可占 512 KiB 加 2 字符前缀。页脚上限为 1 MiB,元数据最多 256 个行组,受支持数据最多 8,192 个数据页;列名最多 128 个 UTF-8 字节。每次导出上限为 8 MiB。加载、翻页和导出设有 10 秒期限。超限会使操作失败,不会悄悄返回部分文件或缩短后的导出。预览每页 25 行、仅前 12 列、每格最多显示 500 个字符。工作线程、大小检查和取消可减轻负载,但并非浏览器总内存的硬性上限,也不能保证恶意输入不会耗尽资源。
- 可解码子集为扁平的必填或可空基本类型列、数据页 v1/v2、PLAIN 或字典值编码,以及 UNCOMPRESSED 或 SNAPPY 压缩。受支持的物理值包含带兼容逻辑注解的 BOOLEAN、INT32、INT64、FLOAT、DOUBLE、BYTE_ARRAY 和 FIXED_LEN_BYTE_ARRAY。嵌套组、LIST/MAP/重复列、INT96、未知逻辑类型、其他值编码及其他压缩方式会保留为不受支持的结构条目,注明原因并用 null 占位;受支持列仍会加载。占位不是实际解码的源空值,也不能恢复原始值。不接受加密文件、外部列文件、损坏内容或远程 URL。此处的兼容范围小于完整 Parquet 规范或上游库。 已知物理类型与逻辑类型的无效组合会校验失败。不支持列的数据负载会跳过,不会解压或校验完整性;受支持列可读不代表原文件每个字节均有效。
- INT64 与 UINT64 均为十进制字符串,即使值能安全放入 JavaScript 数值也不例外。DECIMAL 为保留声明小数位数的精确固定小数字符串。二进制数据为带 0x 前缀的十六进制字符串。DATE、TIME 和 TIMESTAMP 保留为其声明日期或时间单位中的精确整数计数字符串;请查看逻辑类型中的单位和 UTC 调整标记。它们不是格式化日期,也不会转换成改变时区的 JavaScript Date。有限浮点值保留为数值;NaN、+Infinity、-Infinity 和负零使用结构说明的显式字符串。不支持的类型会在结构中标记并用 null 占位;解释空值前请检查 supported 与 reason。
- JSON 导出包含 schema、所选 range 和行对象 rows。结构记录各列的 name、physicalType、logicalType、representation、nullable、supported 和 reason。受支持列中的源空值保留为 JSON null,空文本仍为空字符串,精确值保留其规定的字符串表示。不支持列的 representation 为 unsupported:null,行值为 null 占位;结构保留原因,不应将这些占位解释为源空值。这是一种便于检查的格式,不会重新编码 Parquet,也不保证其他应用可重建全部原始元数据。行范围从 1 开始、首尾均包含且连续;它不是筛选、排序、任意选行或 SQL 查询。 零行文件仍会显示结构,只允许 start 0 / end 0 的空范围,导出包含 rows [] 的 JSON 或仅有表头的 CSV。
- CSV 使用 UTF-8、逗号分隔、CRLF 行尾,并为表头与非空值加双引号;null 为无引号的标记 \N。所有以反斜杠开头的非空文本值会额外添加一个前导反斜杠,因此实际文本 \N 在 CSV 解析后为 \\N。还原规则为:仅将完全等于 \N 的字段映射为 null;其他以两个反斜杠开头的值去掉一个前导反斜杠。CSV 不携带 Parquet 结构或不支持列原因,单凭 CSV 无法区分占位 null 与源 null,重要时请选择 JSON。默认公式保护会为高风险表头和以字符串表示的值加单引号前缀,包括负的 INT64、十进制数或时间计数字符串,并有意改变这些字符串;原始 CSV 关闭公式保护,但仍使用空值与反斜杠编码。原始 CSV 可能触发公式或电子表格类型转换。下载文件名为 parquet-rows.csv 或 parquet-rows.json。预览截短不会截短成功导出的值。取消、超时、工作线程失败、更换文件、重置或离开工具会释放会话;已下载文件仍留在设备上。
常见问题
为什么大整数、十进制数和时间戳被导出为字符串?
转成普通 JavaScript 数值或 Date 可能导致整数舍入、小数位变化或丢失亚毫秒时间戳精度。本工具将 INT64/UINT64 保留为十进制字符串,DECIMAL 保留为固定小数文本,时间值保留为精确单位计数。JSON 结构会说明解释方式,包括时间单位与 UTC 调整标记,不会猜测显示时区。
CSV 能区分 null、空字符串和文本 \N 吗?
null 为标记 \N。所有实际以反斜杠开头的文本值都会添加一个前导反斜杠,因此字符串 \N 在 CSV 解析后变为 \\N,空字符串仍为空。解码时仅把完全匹配的 \N 映射为 null,其他以两个反斜杠开头的值去掉一个前导反斜杠。CSV 仍不包含类型信息和不支持列 null 占位的原因。需要保留这些结构区别时请用 JSON。
不支持的 Parquet 列会如何处理?
列会保留在结构中,标记 supported:false、原因和 representation unsupported:null。显示与导出均用 null 占位,受支持列仍可读取。不要把占位当作真正的源空值。嵌套列、INT96,以及不支持的逻辑类型、编码或压缩方式可能触发这种处理。元数据损坏、受支持数据无效或资源超限会导致加载失败。不支持列的原始值请用完整的 Parquet 工具检查。
导出范围是否只包含当前预览?
不是。起始行和结束行按原文件顺序从 1 计数,且两端都包含。成功导出会包含该范围内所有列和完整值,不受当前预览页、12 列显示上限或 500 字符截短影响。无效范围或过大输出会被拒绝。空文件只使用特殊的 0–0 范围,导出结构或表头而没有数据行。取消或重置会丢弃加载的会话,需重新加载文件。