我有一个非常大的(280 Meg)xml文件,它都在一行上。我有几个编辑器几乎无法打开它,但没有什么能让我打印它。
我试图在Powershell中对其进行格式化,但还是无法弄清楚语法。我想要使文件更具可读性的方法是用回车符+换行符和结束标记替换所有结束标记,但我无法让它工作。
这是我到目前为止所尝试的:
(get-content .\ReallyHugeXMLFile2.xml) -replace ('</','`n</') | out-file .\ReallyHugeXMLFile2Formatted.xml
(get-content .\ReallyHugeXMLFile2.xml) -replace ('</','\r\n</') | out-file .\ReallyHugeXMLFile2Formatted2.xml
(get-content .\ReallyHugeXMLFile2.xml) -replace ('</','\\r\\n</') | out-file .\ReallyHugeXMLFile2Formatted3.xml
谢谢
TheIncorrigible1在评论中提供了关键指针:
假设你的大型XML文件仍然可以作为一个整体加载到System.Xml.XmlDocument
实例中,你可以简单地调用它的.Save()
方法来创建一个漂亮的打印输出文件(这样就不需要手动换行了;另外,使用一个XML解析器总是优于文本操作)。
# Load the file into a [xml] (System.Xml.XmlDocument) instance...
($xmlDoc = New-Object xml).Load($PWD.ProviderPath + '/HugeFile.xml')
# ... and save it, which automatically pretty-prints it.
$xmlDoc.Save($PWD.ProviderPath + '/HugeFilePrettyPrinted.xml')
请注意需要在文件名前加上$PWD.ProviderPath
,以确保.NET使用PowerShell的当前目录(.NET通常不同,.NET不知道使用New-PSDrive
创建的PowerShell驱动器)。[1]
注意:生成的文件将只有LF换行符,而不是CRLF换行符。
可行性论证:
首先,运行以下代码(PSv5 +)以创建大小约为280 MB的示例XML文件。请注意,您可以轻松调整代码以指定不同的目标大小。
注意:
HugeFile.xml
将在当前目录中创建,并且稍后运行pretty-printing命令会在同一位置创建(甚至更大)HugeFilePrettyPrinted.xml
。# Create a sample single-line XML file of a given size (approximately).
# Note: Depending on the target size, this can take a long time to complete.
# Additionally, for performance reasons the code is written so that
# the file content must fit into memory as a whole.
# The desired size of the resulting file.
$targetFileSize = 280mb
$targetFile = './HugeFile.xml'
# The XML element to repeat.
$repeatingElementTemplate = '<book><title>De Profundis {0:000000000000}</title></book>'
# Determine how often it must be repeated to reach the target size (approximately)
$repeatCount = $targetFileSize / ($repeatingElementTemplate.Length - 4)
Write-Verbose -vb "Creating XML file '$targetFile' of approximate size $('{0:N2}' -f ($targetFileSize / 1mb)) MB..."
# Create the file.
'<?xml version="1.0"?><catalog>' | Set-Content -NoNewline -Encoding Utf8 $targetFile
-join (1..$repeatCount).ForEach({ $repeatingElementTemplate -f $_ }) |
Add-Content -NoNewline -Encoding Utf8 $targetFile
'</catalog>' | Add-Content -NoNewline -Encoding Utf8 $targetFile
然后,运行上面的漂亮打印命令。
在具有3GB RAM(在旧硬件上)的单核Windows 10 VM上,这需要大约40秒。埃里克本人在他的机器上报告不到5秒钟。
[1]确保将相对PowerShell文件系统路径正确传递给.NET方法:
$PWD.ProviderPath
($PWD.ProviderPath + '<fileInCurrentDir>
)形成完整路径可确保PowerShell的当前文件系统位置表示为本机文件系统路径(谢谢,TheIncorrigible1)。 .NET方法只能理解后者;他们不知道使用New-PSDrive
创建的自定义PowerShell驱动器,并且他们不知道PowerShell的提供者前缀表示法,当当前位置是UNC路径时$PWD
字符串化(例如,
Microsoft.PowerShell.Core\FileSystem::\\some-server\some-share\some-folder
)。"$PWD/<fileInCurrentDir>"
。(Get-Location -PSProvider FileSystem).ProviderPath + '/<fileInCurrentDir>'
,因为PowerShell的当前位置可能来自文件系统提供者以外的提供者;例如,HKCU:\Console
(注册管理机构提供商)。