如何在MarkLogic中获取文本文件大小并解决计算差异问题
问题:MarkLogic中获取与系统一致的日志文件大小及日期统计问题
我需要在MarkLogic中获取文本文件大小,以此统计特定日期日志文件的增长量。以下是我编写的代码:
xquery version "1.0-ml"; declare function local:convertToKilobytes($sizeInCharacters as xs:integer) as xs:decimal { $sizeInCharacters * 2 div 1024 }; let $error-log := "C:\Program Files\MarkLogic\Data\Logs\ErrorLog.txt" let $logLines := fn:tokenize(xdmp:filesystem-file($error-log), '\r?\n') let $uniqueDates := distinct-values( for $line in $logLines let $logDate := fn:substring($line, 1, 10) where $logDate ne '' return $logDate ) let $currentSize := sum(for $line in $logLines return string-length($line)) let $logEntries := for $date in $uniqueDates let $sizeInCharacters := sum(for $l in $logLines where fn:contains($l, $date) return string-length($l)) let $sizeInKilobytes := local:convertToKilobytes($sizeInCharacters) return <log-entry date="{$date}" size-in-kilobytes="{$sizeInKilobytes}"/> return <log-growth>{ $logEntries }</log-growth>
运行上述代码后得到结果:
<log-growth> <log-entry date="2023-09-11" size-in-kilobytes="75.05859375"> </log-entry> </log-growth>
但查看系统文件属性时,显示文件大小为38KB,磁盘占用大小为128KB,两者结果不一致。请问MarkLogic是否有特定函数可获取与系统一致的文件大小?求相关建议。
解决方案
1. 结果不一致的核心原因
- 字符编码假设错误:你默认每个字符占2字节,但MarkLogic读取文本文件时用UTF-8编码,ASCII字符仅占1字节,多字节字符占2-4字节,直接乘以2会导致计算值偏大。
- 丢失换行符字节:
tokenize拆分时丢弃了原文件中的换行符(\r\n占2字节),这部分字节未被统计,导致结果偏差。 - 系统显示的“文件大小”是实际字节数,“磁盘占用大小”是文件系统按簇分配的空间,二者本身存在差异,我们需要对齐的是实际文件大小。
2. 使用MarkLogic内置函数获取准确文件大小
MarkLogic提供xdmp:filesystem-file-size()函数,可直接获取文件的实际字节数,与系统属性中的“文件大小”完全一致。
3. 优化后的代码
以下代码同时实现获取系统一致的文件总大小,以及按日期统计日志行的实际字节占比:
xquery version "1.0-ml"; let $error-log := "C:\Program Files\MarkLogic\Data\Logs\ErrorLog.txt" // 获取文件实际总字节数,与系统显示一致 let $file-total-bytes := xdmp:filesystem-file-size($error-log) let $file-content := xdmp:filesystem-file($error-log) let $logLines := fn:tokenize($file-content, '\r?\n') let $uniqueDates := distinct-values( for $line in $logLines let $logDate := fn:substring($line, 1, 10) where $logDate ne '' return $logDate ) let $logEntries := for $date in $uniqueDates let $date-lines := $logLines[fn:contains(., $date)] // 计算每行实际字节数(含换行符):内容字节数 + 换行符字节(Windows为2,Linux为1) let $date-bytes := sum( for $line in $date-lines return fn:string-length(xs:hexBinary(xs:string($line))) div 2 + 2 ) let $sizeInKilobytes := $date-bytes div 1024 return <log-entry date="{$date}" size-in-kilobytes="{$sizeInKilobytes}" bytes="{$date-bytes}"/> return <log-growth> <file-total-bytes>{$file-total-bytes}</file-total-bytes> <file-total-kilobytes>{$file-total-bytes div 1024}</file-total-kilobytes> {$logEntries} </log-growth>
4. 关键说明
xdmp:filesystem-file-size($path):返回文件实际字节数,与系统“文件大小”完全匹配。- 按日期统计时,通过
xs:hexBinary计算每行真实字节数,加上换行符字节,确保统计值接近实际占比。 - 系统“磁盘占用大小”是操作系统层面的簇分配信息,MarkLogic无法直接获取,若需获取可通过调用外部系统命令(如Windows的
dir、Linux的ls -s),但需配置xdmp:invoke权限。
内容的提问来源于stack exchange,提问作者Dharmendra Kumar Singh
相关产品推荐
相关产品推荐

