Chris LaJoie said:
Sounds good Jon. I'm anxious to see what you can do with that. If you
don't mind, I plan on submitting this code (with proper credit of course) to
various sites so compression code isn't so hard to come by.
Sure. This is really only "early morning for fun" code though - no
comments, no error checking, hideously inefficient etc - I just wanted
to see how it would do.
Also, due to the fact that it *can* compress so well, the
GetMaxCharCount may well mean that some other classes will seriously
overallocate space.
So, with all the caveats over with, here's the code.
using System;
using System.Text;
using System.IO;
public class SpaceSaver : Encoding
{
public override int GetByteCount (char[] text, int start,
int length)
{
return ToBinary(text, start, length).Length;
}
public override int GetBytes (char[] text, int textStart,
int length, byte[] buffer,
int bufferStart)
{
byte[] binary = ToBinary(text, textStart, length);
Array.Copy (binary, 0, buffer, bufferStart, binary.Length);
return binary.Length;
}
public override int GetCharCount (byte[] binary, int start,
int length)
{
return ToString(binary, start, length).Length;
}
public override int GetChars (byte[] binary, int binaryStart,
int length, char[] buffer,
int bufferStart)
{
char[] chars = ToString (binary, binaryStart,
length).ToCharArray();
Array.Copy (chars, 0, buffer, bufferStart, chars.Length);
return chars.Length;
}
public override int GetMaxByteCount(int length)
{
return length;
}
public override int GetMaxCharCount(int length)
{
return length*129;
}
String ToString (byte[] data, int start, int length)
{
StringBuilder builder = new StringBuilder();
foreach (byte b in data)
{
if (b < 128)
builder.Append ((char)b);
else
builder.Append (new string (' ', b-126));
}
return builder.ToString();
}
byte[] ToBinary (char[] text, int start, int length)
{
using (MemoryStream ms = new MemoryStream())
{
int spaces=0;
foreach (char t in text)
{
if (t==' ')
{
spaces++;
if (spaces==130)
{
ms.WriteByte(255);
spaces=1;
}
}
else
{
switch (spaces)
{
case 0:
break;
case 1:
ms.WriteByte(32);
break;
default:
ms.WriteByte((byte)(spaces+126));
break;
}
spaces=0;
ms.WriteByte ((byte)t);
}
}
switch (spaces)
{
case 0:
break;
case 1:
ms.WriteByte(32);
break;
default:
ms.WriteByte((byte)(spaces+126));
break;
}
ms.Flush();
return ms.ToArray();
}
}
static void Main(string[] args)
{
string inputFile = args[0];
Encoding encoding = new SpaceSaver();
try
{
// Create the reader and writer with appropriate encodings.
using (StreamReader inputReader =
new StreamReader (inputFile, Encoding.ASCII))
{
string allText = inputReader.ReadToEnd();
byte[] data = encoding.GetBytes(allText);
Console.WriteLine ("data length="+data.Length);
string recovered = encoding.GetString(data);
if (recovered != allText)
{
Console.WriteLine ("Oops!");
Console.WriteLine (recovered.Substring (0, 100));
}
}
}
catch (IOException e)
{
Console.WriteLine ("Exception during processing: {0}",
e.Message);
}
}
}