C# C-XML-压缩
我遇到过这样一种情况,即生成一个XML文件以提交给Web服务,有时是因为它的数据量超过了30mb或50mb 我需要使用c、.net framework 4.0压缩该文件,而不是使用包含大部分数据的节点之一。。我不知道该怎么做。。有没有可能,如果有人能给我一个例子,我可以如何做到这一点,请 xml文件如下所示C# C-XML-压缩,c#,.net,xml,compression,nodes,C#,.net,Xml,Compression,Nodes,我遇到过这样一种情况,即生成一个XML文件以提交给Web服务,有时是因为它的数据量超过了30mb或50mb 我需要使用c、.net framework 4.0压缩该文件,而不是使用包含大部分数据的节点之一。。我不知道该怎么做。。有没有可能,如果有人能给我一个例子,我可以如何做到这一点,请 xml文件如下所示 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <HeaderTalk xmlns="http://www.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<HeaderTalk xmlns="http://www.w3schools.com/xml">
<EnvelopeVersion>2.0</EnvelopeVersion>
<Header>
<MessageDetails>
<Class>CHAR-CLM</Class>
</MessageDetails>
<SenderDetails>
<IDAuthentication>
<SenderID>aaaaaa</SenderID>
<Authentication>
<Method>MD5</Method>
<Role>principal</Role>
<Value>a3MweCsv60kkAgzEpXeCqQ==</Value>
</Authentication>
</IDAuthentication>
<EmailAddress>Someone@somewhere.com</EmailAddress>
</SenderDetails>
</Header>
<TalkDetails>
<ChannelRouting>
<Channel>
<URI>1953</URI>
<Product>My product</Product>
<Version>2.0</Version>
</Channel>
</ChannelRouting>
</TalkDetails>
<Body>
<envelope xmlns="http://www.w3schools.com/xml/">
<PeriodEnd>2013-08-13</PeriodEnd>
<IRmark Type="generic">zZrxvJ7JmMNaOyrMs9ZOaRuihkg=</IRmark>
<Sender>Individual</Sender>
<Report>
<AuthOfficial>
<OffName>
<Fore>B</Fore>
<Sur>M</Sur>
</OffName>
<Phone>0123412345</Phone>
</AuthOfficial>
<DefaultCurrency>GBP</DefaultCurrency>
<Claim>
<OrgName>B</OrgName>
<ref>AB12345</ref>
<Repayment>
<Account>
<Donor>
<Fore>Barry</Fore>
</Donor>
<Total>7.00</Total>
</Account>
<Account>
<Donor>
<Fore>Anthony</Fore>
</Donor>
<Total>20.00</Total>
</Account>
</Repayment>
</Claim>
</Report>
</envelope>
</Body>
</HeaderTalk>
以及要关闭的其余节点
我需要使用c、.NETFramework 4.0压缩该文件,而不是使用其中一个节点
你可以用。差不多
public static void Compress(FileInfo fileToCompress)
{
using (FileStream originalFileStream = fileToCompress.OpenRead())
{
if ((File.GetAttributes(fileToCompress.FullName) & FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz")
{
using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz"))
{
using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
{
originalFileStream.CopyTo(compressionStream);
Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
fileToCompress.Name, fileToCompress.Length.ToString(), compressedFileStream.Length.ToString());
}
}
}
}
}
public static void Decompress(FileInfo fileToDecompress)
{
using (FileStream originalFileStream = fileToDecompress.OpenRead())
{
string currentFileName = fileToDecompress.FullName;
string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length);
using (FileStream decompressedFileStream = File.Create(newFileName))
{
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
{
decompressionStream.CopyTo(decompressedFileStream);
Console.WriteLine("Decompressed: {0}", fileToDecompress.Name);
}
}
}
}
另一种可能的方法是放气。看见GZipStream和Deflate stream之间的主要区别在于,GZipStream将添加CRC以确保数据没有错误。您所要求的是可能的,但有些涉及。您需要在内存中创建压缩节点,然后将其写入。我不知道您是如何编写XML的,因此我假设您有如下内容:
open xml writer
write <MessageDetails>
write <SenderDetails>
write other nodes
write Claim node
write other stuff
close file
然后,您的数据位于compressedData字符串中,您可以将其作为元素数据写入
正如我在评论中所说,GZip通常会将原始XML大小减少80%,因此50mb变成10mb。但base64编码将使压缩大小增加33%。我预计结果大约为13.5MB
使现代化
根据您的附加代码,您尝试执行的操作看起来并不太困难。我想你想做的是:
// do a bunch of stuff
GovtSenderClaim.AppendChild(GovtSenderRepayments);
// start of added code
// compress the GovtSenderClaim element
// This code writes the GovtSenderClaim element to a compressed MemoryStream.
// We then read the MemoryStream and create a base64 encoded representation.
string compressedData;
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gz = new GZipStream(CompressionMode.Compress, true))
{
using (StreamWriter writer = StreamWriter(gz))
{
GovtSenderClaim.Save(writer);
}
}
// now base64 encode the memory stream buffer
byte[] buff = ms.ToArray();
compressedData = Convert.ToBase64String(buff, 0, buff.Length);
}
// compressedData now contains the compressed Claim node, encoded in base64.
// create the CompressedPart element
XElement CompressedPart = xmldoc.CreateElement("CompressedPart");
CompressedPart.SetAttributeValue("Type", "gzip");
CompressedPart.SetValue(compressedData);
GovtSenderReport.AppendChild(CompressedPart);
// GovtSenderReport.AppendChild(GovtSenderClaim);
您可以尝试这样做:它将只压缩您选择的节点。它与您要求的有点不同,因为它将替换元素的内容,保留元素及其属性不变
{
// You are using a namespace!
XNamespace ns = "http://www.w3schools.com/xml/";
var xml2 = XDocument.Parse(xml);
// Compress
{
// Will compress all the XElement that are called Claim
// You should probably select the XElement in a better way
var nodes = from p in xml2.Descendants(ns + "Claim") select p;
foreach (XElement el in nodes)
{
CompressElementContent(el);
}
}
// Decompress
{
// Will decompress all the XElement that are called Claim
// You should probably select the XElement in a better way
var nodes = from p in xml2.Descendants(ns + "Claim") select p;
foreach (XElement el in nodes)
{
DecompressElementContent(el);
}
}
}
public static void CompressElementContent(XElement el)
{
string content;
using (var reader = el.CreateReader())
{
reader.MoveToContent();
content = reader.ReadInnerXml();
}
using (var ms = new MemoryStream())
{
using (DeflateStream defl = new DeflateStream(ms, CompressionMode.Compress))
{
// So that the BOM isn't written we use build manually the encoder.
// See for example http://stackoverflow.com/a/2437780/613130
// But note that false is implicit in the parameterless constructor
using (StreamWriter sw = new StreamWriter(defl, new UTF8Encoding()))
{
sw.Write(content);
}
}
string base64 = Convert.ToBase64String(ms.ToArray());
el.ReplaceAll(new XText(base64));
}
}
public static void DecompressElementContent(XElement el)
{
var reader = el.CreateReader();
reader.MoveToContent();
var content = reader.ReadInnerXml();
var bytes = Convert.FromBase64String(content);
using (var ms = new MemoryStream(bytes))
{
using (DeflateStream defl = new DeflateStream(ms, CompressionMode.Decompress))
{
using (StreamReader sr = new StreamReader(defl, Encoding.UTF8))
{
el.ReplaceAll(ParseXmlFragment(sr));
}
}
}
}
public static IEnumerable<XNode> ParseXmlFragment(StreamReader sr)
{
var settings = new XmlReaderSettings
{
ConformanceLevel = ConformanceLevel.Fragment
};
using (var xmlReader = XmlReader.Create(sr, settings))
{
xmlReader.MoveToContent();
while (xmlReader.ReadState != ReadState.EndOfFile)
{
yield return XNode.ReadFrom(xmlReader);
}
}
}
这就是我所做的,使它发挥作用
public void compressTheData(string xml)
{
XNamespace ns = "http://www.w3schools.com/xml/";
var xml2 = XDocument.Load(xml);
// Compress
{
var nodes = (from p in xml2.Descendants(ns + "Claim") select p).ToList();
foreach (XElement el in nodes)
{
CompressElementContent(el);
}
}
xml2.Save(xml);
}
public static void CompressElementContent(XElement el)
{
string content = el.ToString();
using (var ms = new MemoryStream())
{
using (GZipStream defl = new GZipStream(ms, CompressionMode.Compress))
{
using (StreamWriter sw = new StreamWriter(defl))
{
sw.Write(content);
}
}
string base64 = Convert.ToBase64String(ms.ToArray());
XElement newEl = new XElement("CompressedPart", new XText(base64));
XAttribute attrib = new XAttribute("Type", "gzip");
newEl.Add(attrib);
el.ReplaceWith(newEl);
}
}
感谢大家的投入 为什么不通缩呢?通常情况下会更好。@xanatos有很多方法。在底部也添加了Deflate链接:Hi-Ehsan,但这一个将压缩整个xml文件,我只希望压缩xml文件中的一个节点。1.NET GZip只是Deflate,添加了几个字节的头,因此大小没有太大差异。2 OP询问如何压缩部分文件,用CompressedPart节点替换Claim节点。这与您建议的压缩整个文件大不相同。您可以修改web服务吗?如果web服务支持gzip或deflate编码,您可能可以发送压缩的文件,而无需更改数据。信封背面的计算表明,gzip可以将您的50MB压缩为10MB,可能更大,不太可能,但是您必须对其进行base64编码,这会将大小增加到13.5MB左右。这够省钱吗?嗨Romoku。。这是第三方服务,所以我不能修改Web服务。非常感谢Xanatos。。这让我开始了。我现在正在尝试使用ZIP或GZIPHi的设置标准,我不得不做一些轻微的更改以使其正常工作。再次感谢您Hi Jim,我正在使用普通的Xmlelemnt、create元素、appendchild等。我已经编辑了问题并添加了我使用的代码。。谢谢Jim,唯一的问题是我在创建文件时没有使用Xelement。。按老办法做。所以不要有储蓄。对于xmlement@user2664502:对Save的调用正在将元素写入内存流。这就是压缩它的原因。然后,代码读取该内存流并创建compressedData字符串,该字符串将写入CompressedPart元素。我将为示例添加一些注释。
string compressedData;
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gz = new GZipStream(CompressionMode.Compress, true))
{
using (XmlWriter writer = XmlWriter.Create(gz))
{
writer.WriteStartElement("Claim");
// write claim stuff here
writer.WriteEndElement();
}
}
// now base64 encode the memory stream buffer
byte[] buff = ms.GetBuffer();
compressedData = Convert.ToBase64String(buff, 0, buff.Length);
}
// do a bunch of stuff
GovtSenderClaim.AppendChild(GovtSenderRepayments);
// start of added code
// compress the GovtSenderClaim element
// This code writes the GovtSenderClaim element to a compressed MemoryStream.
// We then read the MemoryStream and create a base64 encoded representation.
string compressedData;
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gz = new GZipStream(CompressionMode.Compress, true))
{
using (StreamWriter writer = StreamWriter(gz))
{
GovtSenderClaim.Save(writer);
}
}
// now base64 encode the memory stream buffer
byte[] buff = ms.ToArray();
compressedData = Convert.ToBase64String(buff, 0, buff.Length);
}
// compressedData now contains the compressed Claim node, encoded in base64.
// create the CompressedPart element
XElement CompressedPart = xmldoc.CreateElement("CompressedPart");
CompressedPart.SetAttributeValue("Type", "gzip");
CompressedPart.SetValue(compressedData);
GovtSenderReport.AppendChild(CompressedPart);
// GovtSenderReport.AppendChild(GovtSenderClaim);
{
// You are using a namespace!
XNamespace ns = "http://www.w3schools.com/xml/";
var xml2 = XDocument.Parse(xml);
// Compress
{
// Will compress all the XElement that are called Claim
// You should probably select the XElement in a better way
var nodes = from p in xml2.Descendants(ns + "Claim") select p;
foreach (XElement el in nodes)
{
CompressElementContent(el);
}
}
// Decompress
{
// Will decompress all the XElement that are called Claim
// You should probably select the XElement in a better way
var nodes = from p in xml2.Descendants(ns + "Claim") select p;
foreach (XElement el in nodes)
{
DecompressElementContent(el);
}
}
}
public static void CompressElementContent(XElement el)
{
string content;
using (var reader = el.CreateReader())
{
reader.MoveToContent();
content = reader.ReadInnerXml();
}
using (var ms = new MemoryStream())
{
using (DeflateStream defl = new DeflateStream(ms, CompressionMode.Compress))
{
// So that the BOM isn't written we use build manually the encoder.
// See for example http://stackoverflow.com/a/2437780/613130
// But note that false is implicit in the parameterless constructor
using (StreamWriter sw = new StreamWriter(defl, new UTF8Encoding()))
{
sw.Write(content);
}
}
string base64 = Convert.ToBase64String(ms.ToArray());
el.ReplaceAll(new XText(base64));
}
}
public static void DecompressElementContent(XElement el)
{
var reader = el.CreateReader();
reader.MoveToContent();
var content = reader.ReadInnerXml();
var bytes = Convert.FromBase64String(content);
using (var ms = new MemoryStream(bytes))
{
using (DeflateStream defl = new DeflateStream(ms, CompressionMode.Decompress))
{
using (StreamReader sr = new StreamReader(defl, Encoding.UTF8))
{
el.ReplaceAll(ParseXmlFragment(sr));
}
}
}
}
public static IEnumerable<XNode> ParseXmlFragment(StreamReader sr)
{
var settings = new XmlReaderSettings
{
ConformanceLevel = ConformanceLevel.Fragment
};
using (var xmlReader = XmlReader.Create(sr, settings))
{
xmlReader.MoveToContent();
while (xmlReader.ReadState != ReadState.EndOfFile)
{
yield return XNode.ReadFrom(xmlReader);
}
}
}
{
XNamespace ns = "http://www.w3schools.com/xml/";
var xml2 = XDocument.Parse(xml);
// Compress
{
// Here the ToList() is necessary, because we will replace the selected elements
var nodes = (from p in xml2.Descendants(ns + "Claim") select p).ToList();
foreach (XElement el in nodes)
{
CompressElementContent(el);
}
}
// Decompress
{
// Here the ToList() is necessary, because we will replace the selected elements
var nodes = (from p in xml2.Descendants("CompressedPart") select p).ToList();
foreach (XElement el in nodes)
{
DecompressElementContent(el);
}
}
}
public static void CompressElementContent(XElement el)
{
string content = el.ToString();
using (var ms = new MemoryStream())
{
using (DeflateStream defl = new DeflateStream(ms, CompressionMode.Compress))
{
// So that the BOM isn't written we use build manually the encoder.
using (StreamWriter sw = new StreamWriter(defl, new UTF8Encoding()))
{
sw.Write(content);
}
}
string base64 = Convert.ToBase64String(ms.ToArray());
var newEl = new XElement("CompressedPart", new XText(base64));
el.ReplaceWith(newEl);
}
}
public static void DecompressElementContent(XElement el)
{
var reader = el.CreateReader();
reader.MoveToContent();
var content = reader.ReadInnerXml();
var bytes = Convert.FromBase64String(content);
using (var ms = new MemoryStream(bytes))
{
using (DeflateStream defl = new DeflateStream(ms, CompressionMode.Decompress))
{
using (StreamReader sr = new StreamReader(defl, Encoding.UTF8))
{
var newEl = XElement.Parse(sr.ReadToEnd());
el.ReplaceWith(newEl);
}
}
}
}
public void compressTheData(string xml)
{
XNamespace ns = "http://www.w3schools.com/xml/";
var xml2 = XDocument.Load(xml);
// Compress
{
var nodes = (from p in xml2.Descendants(ns + "Claim") select p).ToList();
foreach (XElement el in nodes)
{
CompressElementContent(el);
}
}
xml2.Save(xml);
}
public static void CompressElementContent(XElement el)
{
string content = el.ToString();
using (var ms = new MemoryStream())
{
using (GZipStream defl = new GZipStream(ms, CompressionMode.Compress))
{
using (StreamWriter sw = new StreamWriter(defl))
{
sw.Write(content);
}
}
string base64 = Convert.ToBase64String(ms.ToArray());
XElement newEl = new XElement("CompressedPart", new XText(base64));
XAttribute attrib = new XAttribute("Type", "gzip");
newEl.Add(attrib);
el.ReplaceWith(newEl);
}
}