I have a project that is almost near completion aside from a couple of stubborn but probably simple error Im receiving. I am by know means knowledgeable of C and me getting this project this far is a miracle. Im hoping someone can detect what it is I am missing in my code. Here is the view of the errors and below is the code.
private void button1_Click(object sender, EventArgs e)
{
Random rnd = new Random();
StringBuilder bin = new StringBuilder();
int buf = 0;
int bufLen = 0;
int left = 53;
for (int i = 106; i >= 1; i += -1)
{
buf <<= 1;
if (rnd.Next(i) < left)
{
buf += 1;
left -= 1;
}
bufLen += 1;
if (bufLen == 4)
{
bin.Append("0123456789ABCDEF"(buf));
bufLen = 0;
buf = 0;
}
}
string b = bin.ToString();
bin.Append("048c"(buf));
System.Security.Cryptography.SHA1Managed m = new System.Security.Cryptography.SHA1Managed();
byte[] hash = m.ComputeHash(Encoding.UTF8.GetBytes(b));
//replace first two bits in hash with bits from buf
hash(0) = Convert.ToByte(hash(0) & 0x3f | (buf * 64));
//append 24 bits from hash
b = b.Substring(0, 26) + BitConverter.ToString(hash, 0, 3).Replace("-", string.Empty);
}
}
}
x(y) means "call x with y as a parameter".
You have written "0123456789ABCDEF"(buf). "0123456789ABCDEF" isn't a function (or a functor) so you can't call it.
Perhaps you meant to index it, with "0123456789ABCDEF"[buf]? This returns the buf'th character from "0123456789ABCDEF", which is buf in hexadecimal as long as buf is between 0 and 15.
You can't concatenate a string literal with a string variable.
#include <iostream>
using std::cout;
void concatenate(const std::string& s)
{
cout << "In concatenate, string passed is: "
<< s
<< "\n";
}
int main(void)
{
std::string world = " World!\n";
concatenate("Hello"(world));
return 0;
}
Thomas#HastaLaVista ~/concatenation
# g++ -o main.exe main.cpp
main.cpp: In function `int main()':
**main.cpp:15: error: `"Hello"' cannot be used as a function**
Thomas#HastaLaVista ~/concatenation
# g++ --version
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
You will need a temporary string variable:
if (bufLen == 4)
{
std::string temp("01234567890ABCDEF");
temp += buf;
bin.Append(temp);
bufLen = 0;
buf = 0;
}
Related
I'm implementing LZF compress in managed memory environment and decompress from ios environment.
So this is my code implement lzf decompress like this
in c#
private static int LZFDecompress(byte[] input, byte[] output)
{
int inputLength = input.Length;
int outputLength = output.Length;
uint iidx = 0;
uint oidx = 0;
do
{
uint ctrl = input[iidx++];
if (ctrl < (1 << 5)) /* literal run */
{
ctrl++;
if (oidx + ctrl > outputLength)
{
//SET_ERRNO (E2BIG);
return 0;
}
do
output[oidx++] = input[iidx++];
while ((--ctrl) != 0);
}
else /* back reference */
{
uint len = ctrl >> 5;
int reference = (int)(oidx - ((ctrl & 0x1f) << 8) - 1);
if (len == 7)
len += input[iidx++];
reference -= input[iidx++];
if (oidx + len + 2 > outputLength)
{
//SET_ERRNO (E2BIG);
return 0;
}
if (reference < 0)
{
//SET_ERRNO (EINVAL);
return 0;
}
output[oidx++] = output[reference++];
output[oidx++] = output[reference++];
do
output[oidx++] = output[reference++];
while ((--len) != 0);
}
}
while (iidx < inputLength);
return (int)oidx;
}
and porting to swift like this
private static func LZFDecompress(input: [UInt8],
output: inout [UInt8])
-> Int
{
let inputLength = input.count
let outputLength = output.count
var iidx = 0
var oidx = 0
repeat
{
var ctrl = Int(input[iidx])
iidx += 1
if ctrl < (1 << 5)
{
ctrl += 1
if oidx + ctrl > outputLength
{
return 0
}
repeat
{
output[oidx] = input[iidx]
oidx += 1
iidx += 1
ctrl -= 1
}
while ctrl != 0
}
else
{
var len = ctrl >> 5
var reference = oidx - ((ctrl & 0x1f) << 8) - 1
if len == 7
{
len += Int(input[iidx])
iidx += 1
}
reference -= Int(input[iidx])
iidx += 1
if oidx + len + 2 > outputLength
{
return 0
}
if reference < 0
{
return 0
}
output[oidx] = output[reference]
oidx += 1
reference += 1
output[oidx] = output[reference]
oidx += 1
reference += 1
repeat
{
output[oidx] = output[reference]
oidx += 1
reference += 1
len -= 1
}
while len != 0
}
}
while iidx < inputLength
return oidx
}
But I have a problem, it is a performance difference.
It costs 2-3 seconds in c# but costs 9-10 seconds in swift to decompress same files...
I can't understand this situation.
I tested c# from console in windows.
And I tested swift from playground or project in mac.
It was not efficient code unconsidered SIMD and CPUs.
So I used decompress method (lz4, zlib) is provided by apple.
It's so faster than before. It costs below 1-second decompressing 200Mb file.
But In a managed environment (c#) it's slower than unmanaged.
If you want more performance, implement native.
I use these lzib managed codes.
https://github.com/jstedfast/Ionic.Zlib
https://github.com/Kulestar/unity-zlib (unity version, dotnet-mono)
It costs 6-7 seconds for decompressing and 30 seconds for compressing at the same file.
And then you should know this code to be compatible to lzip in apple.
It includes adding the header for compressed data.
public static byte[] Compress(byte[] inputData)
{
var zlib = new ZlibCodec(CompressionMode.Compress);
zlib.CompressLevel = Zlib.CompressionLevel.AppleSupported; // Level5
zlib.InputBuffer = inputData;
zlib.OutputBuffer = new byte[inputData.Length];
zlib.NextIn = 0;
zlib.AvailableBytesIn = inputData.Length;
zlib.NextOut = 0;
zlib.AvailableBytesOut = inputData.Length;
zlib.InitializeDeflate(Zlib.CompressionLevel.AppleSupported, false);
// 'false' means it's 1951(deflate) version not 1950(lzib) version
zlib.Deflate(FlushType.Finish);
var output = new byte[zlib.TotalBytesOut];
Array.Copy(zlib.OutputBuffer, output, (int)zlib.TotalBytesOut);
return output;
}
public static byte[] Decompress(byte[] inputData, int outputSize)
{
var zlib = new ZlibCodec(CompressionMode.Decompress);
zlib.CompressLevel = Zlib.CompressionLevel.AppleSupported;
zlib.InputBuffer = inputData;
zlib.OutputBuffer = new byte[outputSize];
zlib.NextIn = 0;
zlib.AvailableBytesIn = inputData.Length;
zlib.NextOut = 0;
zlib.AvailableBytesOut = outputSize;
zlib.InitializeInflate(false);
zlib.Inflate(FlushType.Finish);
var output = new byte[zlib.TotalBytesOut];
Array.Copy(zlib.OutputBuffer, output, (int)zlib.TotalBytesOut);
return output;
}
I wish to help the same person like me who implement multi-platform compressing.
I have this function is Node.js
// #param {BigInteger} checksum
// #returns {Uint8Array}
function checksumToUintArray(checksum) {
var result = new Uint8Array(8);
for (var i = 0; i < 8; ++i) {
result[7 - i] = checksum.and(31).toJSNumber();
checksum = checksum.shiftRight(5);
}
return result;
}
What would be the equivalent in c#?
I'm thinking:
public static uint[] ChecksumToUintArray(long checksum)
{
var result = new uint[8];
for (var i = 0; i < 8; ++i)
{
result[7 - i] = (uint)(checksum & 31);
checksum = checksum >> 5;
}
return result;
}
But I'm no sure.
My main dilemma is the "BigInteger" type (but not only).
Any help would be appropriated.
UInt8 is "unsigned 8-bit integer". In C# that's byte, because uint is "unsigned 32-bit integer". So UInt8Array is byte[].
Javascript BigInteger corresponds to C# BigInteger (from System.Numerics dll or nuget package), not to long. In some cases, long might be enough. For example, if BigInteger in javascript algorithm is used only because there is no such thing as 64bit integer in javascript - then it's fine to replace it with long in C#. But in general, without any additional information about expected ranges - range of javascript BigInteger is much bigger than range of C# long.
Knowing that, your method becomes:
public static byte[] ChecksumToUintArray(BigInteger checksum) {
var result = new byte[8];
for (var i = 0; i < 8; ++i) {
result[7 - i] = (byte) (checksum & 31);
checksum = checksum >> 5;
}
return result;
}
Have a problem, much like this post: How to read a .NET Guid into a Java UUID.
Except, from a remote svc I get a hex str formatted like this: ABCDEFGH-IJKL-MNOP-QRST-123456.
I need to match the GUID.ToByteArray() generated .net byte array GH-EF-CD-AB-KL-IJ-OP-MN- QR- ST-12-34-56 in Java for hashing purposes.
I'm kinda at a loss as to how to parse this. Do I cut off the QRST-123456 part and perhaps use something like the Commons IO EndianUtils on the other part, then stitch the 2 arrays back together as well? Seems way too complicated.
I can rearrange the string, but I shouldn't have to do any of these. Mr. Google doesn't wanna help me neither..
BTW, what is the logic in Little Endian land that keeps those last 6 char unchanged?
Yes, for reference, here's what I've done {sorry for 'answer', but had trouble formatting it properly in comment}:
String s = "3C0EA2F3-B3A0-8FB0-23F0-9F36DEAA3F7E";
String[] splitz = s.split("-");
String rebuilt = "";
for (int i = 0; i < 3; i++) {
// Split into 2 char chunks. '..' = nbr of chars in chunks
String[] parts = splitz[i].split("(?<=\\G..)");
for (int k = parts.length -1; k >=0; k--) {
rebuilt += parts[k];
}
}
rebuilt += splitz[3]+splitz[4];
I know, it's hacky, but it'll do for testing.
Make it into a byte[] and skip the first 3 bytes:
package guid;
import java.util.Arrays;
public class GuidConvert {
static byte[] convertUuidToBytes(String guid) {
String hexdigits = guid.replaceAll("-", "");
byte[] bytes = new byte[hexdigits.length()/2];
for (int i = 0; i < bytes.length; i++) {
int x = Integer.parseInt(hexdigits.substring(i*2, (i+1)*2), 16);
bytes[i] = (byte) x;
}
return bytes;
}
static String bytesToHexString(byte[] bytes) {
StringBuilder buf = new StringBuilder();
for (byte b : bytes) {
int i = b >= 0 ? b : (int) b + 256;
buf.append(Integer.toHexString(i / 16));
buf.append(Integer.toHexString(i % 16));
}
return buf.toString();
}
public static void main(String[] args) {
String guid = "3C0EA2F3-B3A0-8FB0-23F0-9F36DEAA3F7E";
byte[] bytes = convertUuidToBytes(guid);
System.err.println("GUID = "+ guid);
System.err.println("bytes = "+ bytesToHexString(bytes));
byte[] tail = Arrays.copyOfRange(bytes, 3, bytes.length);
System.err.println("tail = "+ bytesToHexString(tail));
}
}
The last group of 6 bytes is not reversed because it is an array of bytes. The first four groups are reversed because they are a four-byte integer followed by three two-byte integers.
I'm trying to figure out how to get a string from an array starting at some given position. Say we have an array that's arbitrarily long and my string starts at location 1000. If I wanted to get a string from a file I would simply use something like getc or scanf or something. How do I carry out these same functions on an array instead of a file?
*oh, keep in mind that the array is of type int and is full of numerical representations of ASCII characters.
If you were dealing with a byte[] array then you could just do this:
string yourString = Encoding.ASCII.GetString(yourArray, startIndex, length);
Since your array is of type int[] then -- assuming that each element represents a single ASCII character -- you'll need to convert those ints to bytes first. If the array is "arbitrarily long" then you may not want to convert the whole thing to a byte[] array, in which case just convert the section that you need:
byte[] temp =
yourArray.Skip(startIndex).Take(length).Select(i => (byte)i).ToArray();
string yourString = Encoding.ASCII.GetString(temp);
If each element of your int[] array doesn't actually represent a single ASCII character then you'll need to give us more info about the precise format that it uses.
Assuming the string is null terminated (you don't specify how you know the end of the string) then a bit of Linq should do the trick:
var chars = ints.Skip(1000).TakeWhile(i => i != 0).Select(i => (char)i);
var str = new string(chars.ToArray());
The first like skips 1000 ints, takes them while they're not a null-terminator, and then converts them to a char as appropriate for ints representing ASCII codes. The second line simply makes them into a string.
If the string has no null terminator, and just ends when the array ends, then just remove the call to TakeWhile.
Here is an alternative (similar to the solution provided by LukeH) that might be faster (since it uses built in array methods rather than LINQ):
public static string GetString(int[] array, int startIndex, int length)
{
var subarray = new int[length];
Array.Copy(array, startIndex, subarray, 0, length);
return Encoding.ASCII.GetString(Array.ConvertAll(subarray, i => (byte)i));
}
Could you slice the elements from the array and call ASCIIEncoding.GetString() on it
LINQ can be pretty hand at times...
var ints = Enumerable.Range(0, 255).ToArray();
var start = 65;
var length = 26;
var value = new string(ints.Select(i => (char)i)
.Skip(start)
.Take(length)
.ToArray());
Console.WriteLine(value); //ABCDEFGHIJKLMNOPQRSTUVWXYZ
Here is my code just for reference. If you goto the "SYSCALL" section you will find an if statement pertaining to "open 4" this is where I'm stuck. Oh, by the way, I'm not using visual studio, I'm using a program called "Verilator" which allows me to interface Verilog Code with C++ code.
#include "VMIPS.h"
#include "VMIPS_MIPS.h"//required to explicitly access signals from submodules
#include <verilated.h>
#include <cstdio>
#include <cmath>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <vector>
using namespace std;
unsigned int main_time = 0;
static inline int hexCharValue(char ch)
{
if (ch>='0' && ch<='9')return ch-'0';
if (ch>='a' && ch<='f')return ch-'a'+10;
return 0;
}
int main(int argc, char **argv)
{
///////////////////////////////////////// Instruction Capture /////////////////////////////////////////////
ifstream inClientFile( "TEXT.txt",ios::in ); //stream object
//test if instruction file can be opened
if ( !inClientFile )
{
cerr << "File couldn't be opened" << endl;
return 1; //no point using exit inside main
}
//fill string array with all file values and determines length of program
vector<string> words;
words.reserve(274815);
string word;
while (inClientFile >> word)words.push_back(word); //helper function is unnecessary
cout << "Number of words:" << words.size() << endl;
const int wordCount=words.size();
vector<int> InstructionMemory;
vector<string> tempInstructionMemory;
tempInstructionMemory.reserve(wordCount);
//cut out undesired strings from vector
for(int i=0; i<wordCount; i++)
{
if (words[i].length()==8 && words[i].find("fs24")==string::npos) //f0 can exist at pos 1 in a valid hex string
{
tempInstructionMemory.push_back(words[i]);
}
}
//convert string hex to numerical decimal
InstructionMemory.resize(tempInstructionMemory.size());
for( int j=0; j<tempInstructionMemory.size(); j++ )
{
for( int y=0; y<8; y++)
{
InstructionMemory[j]+=hexCharValue(tempInstructionMemory[j][y])<<(4*(7-y));//4194608+4*
}
}
//printf("Amortized Instruction Vector Size:%d\n",InstructionMemory.size());
////////////////////////////////////// Data Capture ////////////////////////////////////////////////
ifstream inClientDataFile( "DATA.txt",ios::in ); //stream object
//test if instruction file can be opened
if ( !inClientDataFile )
{
cerr << "File couldn't be opened" << endl;
return 1; //no point using exit inside main
}
//fill string array with all file values and determines length of program
vector<string> datas;
datas.reserve(274815);
string data;
while (inClientDataFile >> data)datas.push_back(data); //helper function is unnecessary
cout << "Number of data packets:" << datas.size() << endl;
const int dataCount=datas.size();
vector<int> DataMemory;
vector<string> tempDataMemory;
tempDataMemory.reserve(dataCount);
//cut out undesired strings from vector
for( int i=0; i<dataCount; i++)
{
if (datas[i].length()==8 && datas[i].find("fs24")==string::npos) //f0 can exist at pos 1 in a valid hex string
{
tempDataMemory.push_back(datas[i]);
}
}
//convert string hex to numerical decimal
DataMemory.resize(tempDataMemory.size());
for( int j=0; j<tempDataMemory.size(); j++ )
{
for( int y=0; y<8; y++)
{
DataMemory[j]+=hexCharValue(tempDataMemory[j][y])<<(4*(7-y));
}
}
//printf("Amortized Data Vector Size:%d\n",DataMemory.size());
/////////////////////////////////////////// MIPS I processor interface /////////////////////////////////////////////
Verilated::commandArgs(argc, argv);
VMIPS *top = new VMIPS;
top->CLK = 0;
vector<int> HS0,HS1,HS2;
vector<string> FDT_filename;
vector<int> FDT_state;//1 = open, 0 = closed
int FileDescriptorIndex = 3;//start of non-reserved indecies
FILE *f;
//first 3 positions reserved for stdin, stdout, and stderr
FDT_filename.push_back("stdin");
FDT_filename.push_back("stdout");
FDT_filename.push_back("stderr");
FDT_state.push_back(0);
FDT_state.push_back(0);
FDT_state.push_back(0);
//int FDT[100];
printf("IMAddr:%d IM:%d \n***************\n",top->Iaddr,InstructionMemory[(top->Iaddr)/4]);
while (!Verilated::gotFinish())
{
//clock generation
top->CLK=!(top->CLK);
//vector mapping
if ( ( top->Daddr >= 0 ) && ( top->Daddr <= 419604 ) )
{
if(top->MemRead)
top->Din = HS0[(top->Daddr)/4];
if(top->MemWrite)
HS0[(top->Daddr)/4] = top->Dout;
}
else if ( ( top->Daddr >= (419608+InstructionMemory.size()+4) ) && ( top->Daddr <= 268435452 ) )
{
if(top->MemRead)
top->Din = HS1[(top->Daddr-419608)/4];
if(top->MemWrite)
HS1[(top->Daddr-419608)/4] = top->Dout;
}
else if ( ( top->Daddr >= 268435456 ) && ( top->Daddr <= (268435456+DataMemory.size()) ) )
{
if(top->MemRead)
top->Din = DataMemory[(top->Daddr-2668435456)/4];
if(top->MemWrite)
DataMemory[(top->Daddr-2668435456)/4] = top->Dout;
}
else if ( top->Daddr >=(268435456+DataMemory.size()+4) )
{
if(top->MemRead)
top->Din = HS2[(top->Daddr-(268435456+DataMemory.size()+4))/4];
if(top->MemWrite)
HS2[(top->Daddr-(268435456+DataMemory.size()+4))/4] = top->Dout;
}
//instruction supply mapping
if ( top->Iaddr < 4194608 )
{
top->Iin = InstructionMemory[(top->Iaddr)/4];
}
else
{
top->Iin = InstructionMemory[(top->Iaddr-4194608)/4];
}
//instruction split
if(main_time%2)
printf("IMAddr:%d IM:%d \n***************\n",top->Iaddr,InstructionMemory[(top->Iaddr)/4]);//-4194608)/4]);
//evaluate instruction call and increment time counter
top->eval();
main_time++;
//exit loop
if(main_time>=2)
{
return 0;
}
top->Iin = 3690987776;
//SYSCALL
if ( top->Iin == 3690987584 )//exit 1
{
cout << "Exit" << endl;
return 0;
}
else if ( top->Iin == 3690987776 )//open 4
{
cout << endl << endl << "Open File" << endl << endl;
string filename;
filename = "DATA.txt";
//fill filename with characters from memory
//FDT_filename(top->a0) is the string start pointer
FDT_filename.push_back(filename);//add new filename to newest location
FDT_state.push_back(1);//add new open indicator to newest location
top->v0 = FileDescriptorIndex;//place file descriptor into register
FileDescriptorIndex++;//ready the next file descriptor
//printf("Filename:%d FileDescriptorIndex:%d",FDT_filename.at3(FileDescriptorIndex),FileDescriptorIndex);
}
else if ( top->Iin == 3690987648 )//read 2
{
cout << "Read" << endl;
int max_char_count = top->a2;
int char_CTR = 0;
//create file object and open filename
//read chars from file
//place in
//FILE *f = fopen(filename,"rb");
//scanf("%s %top->a2",&FDT_filename(top->a0) >> top->a1;
//top->v0 = char_CTR;
}
else if ( top->Iin == 3690987712 )//write 3
{
cout << "Write" << endl;
int max_char_count = top->a2;
int char_CTR = 0;
//f fopen(FDT_filename(top->a0));
}
else if ( top->Iin == 3690987840 )//close 5
{
cout << "Close File" << endl;
//FDT_state(top->v0)=0;
}
else if ( top->Iin == 3690987904 )//time 6
{
cout << "Time:" << main_time << endl;
top->a0 = main_time;
top->a1 = main_time;
}
}
}
I am trying to send a UDP packet of bytes corresponding to the numbers 1-1000 in sequence. How do I convert each number (1,2,3,4,...,998,999,1000) into the minimum number of bytes required and put them in a sequence that I can send as a UDP packet?
I've tried the following with no success. Any help would be greatly appreciated!
List<byte> byteList = new List<byte>();
for (int i = 1; i <= 255; i++)
{
byte[] nByte = BitConverter.GetBytes((byte)i);
foreach (byte b in nByte)
{
byteList.Add(b);
}
}
for (int g = 256; g <= 1000; g++)
{
UInt16 st = Convert.ToUInt16(g);
byte[] xByte = BitConverter.GetBytes(st);
foreach (byte c in xByte)
{
byteList.Add(c);
}
}
byte[] sendMsg = byteList.ToArray();
Thank you.
You need to use :
BitConverter.GetBytes(INTEGER);
Think about how you are going to be able to tell the difference between:
260, 1 -> 0x1, 0x4, 0x1
1, 4, 1 -> 0x1, 0x4, 0x1
If you use one byte for numbers up to 255 and two bytes for the numbers 256-1000, you won't be able to work out at the other end which number corresponds to what.
If you just need to encode them as described without worrying about how they are decoded, it smacks to me of a contrived homework assignment or test, and I'm uninclined to solve it for you.
I think you are looking for something along the lines of a 7-bit encoded integer:
protected void Write7BitEncodedInt(int value)
{
uint num = (uint) value;
while (num >= 0x80)
{
this.Write((byte) (num | 0x80));
num = num >> 7;
}
this.Write((byte) num);
}
(taken from System.IO.BinaryWriter.Write(String)).
The reverse is found in the System.IO.BinaryReader class and looks something like this:
protected internal int Read7BitEncodedInt()
{
byte num3;
int num = 0;
int num2 = 0;
do
{
if (num2 == 0x23)
{
throw new FormatException(Environment.GetResourceString("Format_Bad7BitInt32"));
}
num3 = this.ReadByte();
num |= (num3 & 0x7f) << num2;
num2 += 7;
}
while ((num3 & 0x80) != 0);
return num;
}
I do hope this is not homework, even though is really smells like it.
EDIT:
Ok, so to put it all together for you:
using System;
using System.IO;
namespace EncodedNumbers
{
class Program
{
protected static void Write7BitEncodedInt(BinaryWriter bin, int value)
{
uint num = (uint)value;
while (num >= 0x80)
{
bin.Write((byte)(num | 0x80));
num = num >> 7;
}
bin.Write((byte)num);
}
static void Main(string[] args)
{
MemoryStream ms = new MemoryStream();
BinaryWriter bin = new BinaryWriter(ms);
for(int i = 1; i < 1000; i++)
{
Write7BitEncodedInt(bin, i);
}
byte[] data = ms.ToArray();
int size = data.Length;
Console.WriteLine("Total # of Bytes = " + size);
Console.ReadLine();
}
}
}
The total size I get is 1871 bytes for numbers 1-1000.
Btw, could you simply state whether or not this is homework? Obviously, we will still help either way. But we would much rather you try a little harder so you can actually learn for yourself.
EDIT #2:
If you want to just pack them in ignoring the ability to decode them back, you can do something like this:
protected static void WriteMinimumInt(BinaryWriter bin, int value)
{
byte[] bytes = BitConverter.GetBytes(value);
int skip = bytes.Length-1;
while (bytes[skip] == 0)
{
skip--;
}
for (int i = 0; i <= skip; i++)
{
bin.Write(bytes[i]);
}
}
This ignores any bytes that are zero (from MSB to LSB). So for 0-255 it will use one byte.
As states elsewhere, this will not allow you to decode the data back since the stream is now ambiguous. As a side note, this approach crams it down to 1743 bytes (as opposed to 1871 using 7-bit encoding).
A byte can only hold 256 distinct values, so you cannot store the numbers above 255 in one byte. The easiest way would be to use short, which is 16 bits. If you realy need to conserve space, you can use 10 bit numbers and pack that into a byte array ( 10 bits = 2^10 = 1024 possible values).
Naively (also, untested):
List<byte> bytes = new List<byte>();
for (int i = 1; i <= 1000; i++)
{
byte[] nByte = BitConverter.GetBytes(i);
foreach(byte b in nByte) bytes.Add(b);
}
byte[] byteStream = bytes.ToArray();
Will give you a stream of bytes were each group of 4 bytes is a number [1, 1000].
You might be tempted to do some work so that i < 256 take a single byte, i < 65535 take two bytes, etc. However, if you do this you can't read the values out of the stream. Instead, you'd add length encoding or sentinels bits or something of the like.
I'd say, don't. Just compress the stream, either using a built-in class, or gin up a Huffman encoding implementation using an agree'd upon set of frequencies.